[SCM] A client for connecting to 3D metaverses such as Linden Labs Secondlife(tm) and OpenSim grids branch, upstream, updated. upstream/1.21.6-13-g1836a2b

Robin Cornelius robin.cornelius at gmail.com
Tue Apr 14 11:12:12 UTC 2009


The following commit has been merged in the upstream branch:
commit 077c8f1dac4b3a55adc5b56b7a5df8807abb5ab2
Author: Robin Cornelius <robin.cornelius at gmail.com>
Date:   Wed Jan 28 20:36:59 2009 +0000

    Imported Upstream version 1.22.7

diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..658864a
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,46 @@
+topic/debian/71_use_debian_alternatives_for_www_browser.diff -p1
+topic/debian/Allow_CXXFLAGS_to_specifiy_the_debug_flag.diff -p1
+topic/debian/VWR-8751-Build-with-a-shared-llmozlib2.diff -p1
+topic/debian/remove_as_needed.diff -p1
+topic/debian/trademark_compliance.diff -p1
+topic/debian/use_debian-included_fonts.diff -p1
+topic/debian/use_debian_channel.diff -p1
+topic/debian/viewericon.diff -p1
+topic/features/jira-backported/AvatarLoginList.diff -p1
+topic/features/jira-backported/VWR-11663_Save_Load_scripts.diff -p1
+topic/features/jira-backported/VWR-5082_set_bulk_inv_permissions.diff -p1
+topic/features/jira-backported/avatar_list.diff -p1
+topic/features/jira-sent/24_always_test_vectorize.diff -p1
+topic/features/jira-sent/openal_1.21.0.diff -p1
+topic/fixes/jira-backported/VWR-11068_fix_spill_over_menus_small_window.diff -p1
+topic/fixes/jira-backported/VWR-11103-FIx_local_ruler_on_linked_objects.diff -p1
+topic/fixes/jira-backported/VWR-11674_dont_download_muted_sounds.diff -p1
+topic/fixes/jira-backported/VWR-3766_llGetInventoryNumber_tooltip_missing_INVENTORY_ANIMATION.diff -p1
+topic/fixes/jira-backported/VWR5717_text_not_replaced_by_input_with_japanses_im.diff -p1
+topic/fixes/jira-backported/glh_linear.diff -p1
+topic/fixes/jira-sent/50_get_cpu_clock_count_for_more_than_just_i386.diff -p1
+topic/fixes/jira-sent/59_need_llpreprocessor_to_access_endian_macros.diff -p1
+topic/fixes/jira-sent/VWR-10759_delete_LLMediaImplGStreamer_mediaData_as_array.diff -p1
+topic/fixes/jira-sent/VWR-11128-Find_Python.diff -p1
+topic/fixes/jira-sent/VWR-11138_Develop_py_and_express_VS.diff -p1
+topic/fixes/jira-sent/VWR-1815_top_corner_fix.diff -p1
+topic/fixes/jira-sent/VWR-8194_clamp_outline_for_broken_nvidia.diff -p1
+topic/fixes/jira-sent/VWR-9557-EnableBuildWithNvidiaOrMesaHeaders.diff -p1
+topic/fixes/jira-sent/correctly_find_dbus_headers_on_standalone.diff -p1
+topic/fixes/jira-sent/dont_depend_on_artwork_to_build.diff -p1
+topic/fixes/jira-sent/gcc_warning_on_llwindowsdl_var_not_set.diff -p1
+topic/fixes/jira-sent/lltemplatemessagereader_memcpy.diff -p1
+topic/fixes/jira-sent/no_format_or_string_literal.diff -p1
+topic/fixes/jira-sent/use_c_locale_and_dont_spam_me_because_i_am_not_american.diff -p1
+topic/fixes/new/allow_compilation_when_GST_DISABLE_GST_DEBUG_is_defined.diff -p1
+topic/fixes/new/delete_LLImageTGA_mColorMap_as_array.diff -p1
+topic/fixes/thirdparty/0000_keep_statbars_from_overshooting.patch.diff -p1
+topic/fixes/thirdparty/0001_possible_crash_and_leak_llassetstorage.patch.diff -p1
+topic/fixes/thirdparty/0001_possible_crash_in_llviewerpartssim.diff -p1
+topic/fixes/thirdparty/1294_llworkerthread_when_terminating_program.patch.diff -p1
+topic/fixes/thirdparty/1857_apr_thread_mutex_nested.patch.diff -p1
+topic/fixes/thirdparty/2003_possible_crash_draganddrop.patch.diff -p1
+topic/fixes/thirdparty/2543_possible_crash_in_group_voting_propsals.patch.diff -p1
+topic/fixes/thirdparty/2683_possible_crash_update_speaker_list.patch.diff -p1
+topic/pandora/add_support_for_libcwd.diff -p1
+topic/pandora/aleric.diff -p1
diff --git a/debian/patches/topic/debian/71_use_debian_alternatives_for_www_browser.diff b/debian/patches/topic/debian/71_use_debian_alternatives_for_www_browser.diff
new file mode 100644
index 0000000..5a52a8d
--- /dev/null
+++ b/debian/patches/topic/debian/71_use_debian_alternatives_for_www_browser.diff
@@ -0,0 +1,39 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/debian/71_use_debian_alternatives_for_www_browser
+
+Fix the launch_url.sh script to use the debian system prefered browser choice.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/newview/linux_tools/launch_url.sh |    8 ++++++++
+ 1 files changed, 8 insertions(+), 0 deletions(-)
+
+diff --git a/indra/newview/linux_tools/launch_url.sh b/indra/newview/linux_tools/launch_url.sh
+index d2c8919..33cee0e 100755
+--- a/indra/newview/linux_tools/launch_url.sh
++++ b/indra/newview/linux_tools/launch_url.sh
+@@ -8,6 +8,7 @@
+ # On Unixoids we try, in order of decreasing priority:
+ # - $BROWSER if set (preferred)
+ # - kfmclient openURL
++# - gnome-open
+ # - x-www-browser
+ # - opera
+ # - firefox
+@@ -54,6 +55,13 @@ if which kfmclient >/dev/null; then
+     exit
+ fi
+ 
++# else gnome-open
++# (embodies gnome concept of 'preferred browser')
++if which gnome-open  >/dev/null; then
++    gnome-open "$URL" &
++    exit
++fi
++
+ # else x-www-browser
+ # (Debianesque idea of a working X browser)
+ if which x-www-browser >/dev/null; then
+-- 
+tg: (5426384..) topic/debian/71_use_debian_alternatives_for_www_browser (depends on: master)
diff --git a/debian/patches/topic/debian/Allow_CXXFLAGS_to_specifiy_the_debug_flag.diff b/debian/patches/topic/debian/Allow_CXXFLAGS_to_specifiy_the_debug_flag.diff
new file mode 100644
index 0000000..4ede347
--- /dev/null
+++ b/debian/patches/topic/debian/Allow_CXXFLAGS_to_specifiy_the_debug_flag.diff
@@ -0,0 +1,43 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/debian/Allow_CXXFLAGS_to_specifiy_the_debug_flag
+
+Modify 00-Common.cmake to allow custom CXXFLAGS to take effect
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/cmake/00-Common.cmake |    5 ++---
+ 1 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
+index bf2d2c3..0d1092b 100644
+--- a/indra/cmake/00-Common.cmake
++++ b/indra/cmake/00-Common.cmake
+@@ -11,7 +11,7 @@ set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -DLL_DEBUG=1")
+ set(CMAKE_CXX_FLAGS_RELEASE
+     "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -DNDEBUG")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO 
+-    "-DLL_RELEASE=1 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1")
++    "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DLL_RELEASE=1 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1")
+ 
+ 
+ # Don't bother with a MinSizeRel build.
+@@ -123,7 +123,6 @@ if (LINUX)
+       -fno-math-errno
+       -fno-strict-aliasing
+       -fsigned-char
+-      -g
+       -pthread
+       )
+ 
+@@ -158,7 +157,7 @@ if (LINUX)
+     endif (NOT STANDALONE)
+   endif (VIEWER)
+ 
+-  set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}")
++  set(CMAKE_CXX_FLAGS_DEBUG "-g -fno-inline ${CMAKE_CXX_FLAGS_DEBUG}")
+   set(CMAKE_CXX_FLAGS_RELEASE "-O2 ${CMAKE_CXX_FLAGS_RELEASE}")
+ endif (LINUX)
+ 
+-- 
+tg: (29cf69b..) topic/debian/Allow_CXXFLAGS_to_specifiy_the_debug_flag (depends on: master)
diff --git a/debian/patches/topic/debian/VWR-8751-Build-with-a-shared-llmozlib2.diff b/debian/patches/topic/debian/VWR-8751-Build-with-a-shared-llmozlib2.diff
new file mode 100644
index 0000000..42311a2
--- /dev/null
+++ b/debian/patches/topic/debian/VWR-8751-Build-with-a-shared-llmozlib2.diff
@@ -0,0 +1,32 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/debian/VWR-8751-Build-with-a-shared-llmozlib2
+
+This allows us to use a dynamic libllmozlib library.
+Upstream are not currently interested in this.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/cmake/Mozlib.cmake |    7 -------
+ 1 files changed, 0 insertions(+), 7 deletions(-)
+
+diff --git a/indra/cmake/Mozlib.cmake b/indra/cmake/Mozlib.cmake
+index e9555df..7073892 100644
+--- a/indra/cmake/Mozlib.cmake
++++ b/indra/cmake/Mozlib.cmake
+@@ -18,13 +18,6 @@ if (MOZLIB)
+         link_directories(${CMAKE_SOURCE_DIR}/newview/app_settings/mozilla-runtime-linux-${ARCH})
+         set(MOZLIB_LIBRARIES
+             llmozlib2
+-            mozjs
+-            nspr4
+-            plc4
+-            plds4
+-            xpcom
+-            xul
+-            profdirserviceprovider_s
+             )
+     elseif (WINDOWS)
+         if (MSVC71)
+-- 
+tg: (9ef371c..) topic/debian/VWR-8751-Build-with-a-shared-llmozlib2 (depends on: master)
diff --git a/debian/patches/topic/debian/remove_as_needed.diff b/debian/patches/topic/debian/remove_as_needed.diff
new file mode 100644
index 0000000..f959743
--- /dev/null
+++ b/debian/patches/topic/debian/remove_as_needed.diff
@@ -0,0 +1,39 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/debian/remove_as_needed
+
+This was needed to build on ubuntu, which i am keeping syncronised with as well.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/linux_crash_logger/CMakeLists.txt |    2 --
+ indra/newview/CMakeLists.txt            |    1 -
+ 2 files changed, 0 insertions(+), 3 deletions(-)
+
+diff --git a/indra/linux_crash_logger/CMakeLists.txt b/indra/linux_crash_logger/CMakeLists.txt
+index 6f6754e..0711791 100644
+--- a/indra/linux_crash_logger/CMakeLists.txt
++++ b/indra/linux_crash_logger/CMakeLists.txt
+@@ -38,8 +38,6 @@ list(APPEND linux_crash_logger_SOURCE_FILES
+      ${linux_crash_logger_HEADER_FILES}
+      )
+ 
+-list(APPEND CMAKE_EXE_LINKER_FLAGS -Wl,--as-needed)
+-
+ add_executable(linux-crash-logger ${linux_crash_logger_SOURCE_FILES})
+ 
+ target_link_libraries(linux-crash-logger
+diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
+index 7c49f72..5c3dcd7 100644
+--- a/indra/newview/CMakeLists.txt
++++ b/indra/newview/CMakeLists.txt
+@@ -878,7 +878,6 @@ endif (DARWIN)
+ if (LINUX)
+     LIST(APPEND viewer_SOURCE_FILES llappviewerlinux.cpp)
+     LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp)
+-    LIST(APPEND CMAKE_EXE_LINKER_FLAGS -Wl,--as-needed)
+ 
+     set(viewer_LIBRARIES
+         Xinerama
+-- 
+tg: (866d112..) topic/debian/remove_as_needed (depends on: master)
diff --git a/debian/patches/topic/debian/trademark_compliance.diff b/debian/patches/topic/debian/trademark_compliance.diff
new file mode 100644
index 0000000..176bff3
--- /dev/null
+++ b/debian/patches/topic/debian/trademark_compliance.diff
@@ -0,0 +1,35 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/debian/trademark_compliance
+
+Remove instances of Secondlife and replace with Omvviewer
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/newview/llappviewer.cpp |    4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
+index 63711ba..4650817 100644
+--- a/indra/newview/llappviewer.cpp
++++ b/indra/newview/llappviewer.cpp
+@@ -1871,7 +1871,7 @@ bool LLAppViewer::initConfiguration()
+     mYieldTime = gSavedSettings.getS32("YieldTime");
+              
+ 	// XUI:translate
+-	gSecondLife = "Second Life";
++	gSecondLife = "Open Metaverse Viewer";
+ 
+ 	// Read skin/branding settings if specified.
+ 	//if (! gDirUtilp->getSkinDir().empty() )
+@@ -2057,7 +2057,7 @@ bool LLAppViewer::initWindow()
+ 
+ 	// always start windowed
+ 	BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth");
+-	gViewerWindow = new LLViewerWindow(gWindowTitle, "Second Life",
++	gViewerWindow = new LLViewerWindow(gWindowTitle, "Open Metaverse Viewer",
+ 		gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"),
+ 		gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"),
+ 		FALSE, ignorePixelDepth);
+-- 
+tg: (fd964dd..) topic/debian/trademark_compliance (depends on: master)
diff --git a/debian/patches/topic/debian/use_debian-included_fonts.diff b/debian/patches/topic/debian/use_debian-included_fonts.diff
new file mode 100644
index 0000000..e514719
--- /dev/null
+++ b/debian/patches/topic/debian/use_debian-included_fonts.diff
@@ -0,0 +1,44 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/debian/use_debian-included_fonts
+
+Choose fonts that are included on a debian system.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/newview/app_settings/settings.xml |    6 +++---
+ 1 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
+index 688dcab..da697c1 100644
+--- a/indra/newview/app_settings/settings.xml
++++ b/indra/newview/app_settings/settings.xml
+@@ -3466,7 +3466,7 @@
+       <key>Type</key>
+       <string>String</string>
+       <key>Value</key>
+-      <string>profontwindows.ttf</string>
++      <string>/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf</string>
+     </map>
+     <key>FontSansSerif</key>
+     <map>
+@@ -3477,7 +3477,7 @@
+       <key>Type</key>
+       <string>String</string>
+       <key>Value</key>
+-      <string>MtBkLfRg.ttf</string>
++      <string>/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf</string>
+     </map>
+     <key>FontSansSerifBold</key>
+     <map>
+@@ -3488,7 +3488,7 @@
+       <key>Type</key>
+       <string>String</string>
+       <key>Value</key>
+-      <string>MtBdLfRg.ttf</string>
++      <string>/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf</string>
+     </map>
+     <key>FontSansSerifFallback</key>
+     <map>
+-- 
+tg: (3d7e8d6..) topic/debian/use_debian-included_fonts (depends on: master)
diff --git a/debian/patches/topic/debian/use_debian_channel.diff b/debian/patches/topic/debian/use_debian_channel.diff
new file mode 100644
index 0000000..a2bb926
--- /dev/null
+++ b/debian/patches/topic/debian/use_debian_channel.diff
@@ -0,0 +1,25 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/debian/use_debian_channel
+
+Patch to use a custom viewer channel to connect to the SecondLife servers
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llcommon/llversionviewer.h |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
+index 6cb7b87..394f16c 100644
+--- a/indra/llcommon/llversionviewer.h
++++ b/indra/llcommon/llversionviewer.h
+@@ -37,6 +37,6 @@ const S32 LL_VERSION_MINOR = 22;
+ const S32 LL_VERSION_PATCH = 5;
+ const S32 LL_VERSION_BUILD = 0;
+ 
+-const char * const LL_CHANNEL = "Second Life Release";
++const char * const LL_CHANNEL = "Open Metaverse Viewer";
+ 
+ #endif
+-- 
+tg: (128e7ee..) topic/debian/use_debian_channel (depends on: master)
diff --git a/debian/patches/topic/debian/viewericon.diff b/debian/patches/topic/debian/viewericon.diff
new file mode 100644
index 0000000..1e7e1cf
--- /dev/null
+++ b/debian/patches/topic/debian/viewericon.diff
@@ -0,0 +1,717 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/debian/viewericon
+
+Adds an XPM icon to the build.
+This should be removed and the icon should be added directly in debian/ and not applied as a patch.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/newview/res/viewericon.xpm |  697 ++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 697 insertions(+), 0 deletions(-)
+
+diff --git a/indra/newview/res/viewericon.xpm b/indra/newview/res/viewericon.xpm
+new file mode 100644
+index 0000000..7cf88ad
+--- /dev/null
++++ b/indra/newview/res/viewericon.xpm
+@@ -0,0 +1,697 @@
++/* XPM */
++static char * viewericon_xpm[] = {
++"32 32 662 2",
++"  	c None",
++". 	c #2594FF",
++"+ 	c #2693FF",
++"@ 	c #2894FF",
++"# 	c #2996FF",
++"$ 	c #2B98FF",
++"% 	c #2C9AFF",
++"& 	c #2E99FF",
++"* 	c #319AFF",
++"= 	c #319BFF",
++"- 	c #329CFF",
++"; 	c #339EFF",
++"> 	c #349EFF",
++", 	c #329DFF",
++"' 	c #3099FF",
++") 	c #2D99FF",
++"! 	c #2A97FF",
++"~ 	c #2191FF",
++"{ 	c #2692FF",
++"] 	c #2994FF",
++"^ 	c #2A96FF",
++"/ 	c #2B9AFF",
++"( 	c #329BFF",
++"_ 	c #359FFF",
++": 	c #35A0FF",
++"< 	c #36A0FF",
++"[ 	c #359EFF",
++"} 	c #2E98FF",
++"| 	c #2293FF",
++"1 	c #2995FF",
++"2 	c #339DFF",
++"3 	c #369FFF",
++"4 	c #2D9AFF",
++"5 	c #2394FF",
++"6 	c #2F98FF",
++"7 	c #38A2FF",
++"8 	c #39A2FF",
++"9 	c #3BA4FF",
++"0 	c #3AA3FF",
++"a 	c #38A1FF",
++"b 	c #37A1FF",
++"c 	c #309AFF",
++"d 	c #2593FF",
++"e 	c #2997FF",
++"f 	c #349FFF",
++"g 	c #3BA3FF",
++"h 	c #3CA4FF",
++"i 	c #3EA6FF",
++"j 	c #3EA7FF",
++"k 	c #3FA7FF",
++"l 	c #2D91FE",
++"m 	c #298BFC",
++"n 	c #298AFA",
++"o 	c #2989FA",
++"p 	c #2889FA",
++"q 	c #2688F8",
++"r 	c #2486F8",
++"s 	c #2386F8",
++"t 	c #2488FA",
++"u 	c #2E96FE",
++"v 	c #2893FF",
++"w 	c #3DA5FF",
++"x 	c #3FA8FF",
++"y 	c #2F96FE",
++"z 	c #1978F4",
++"A 	c #136DEE",
++"B 	c #126AEB",
++"C 	c #1269EA",
++"D 	c #116AE9",
++"E 	c #106AE8",
++"F 	c #1069E6",
++"G 	c #1068E6",
++"H 	c #116AEA",
++"I 	c #1C7BF7",
++"J 	c #2A94FF",
++"K 	c #3AA2FF",
++"L 	c #3DA6FF",
++"M 	c #40ADFF",
++"N 	c #41AEFF",
++"O 	c #43B0FF",
++"P 	c #2D95FD",
++"Q 	c #1472EF",
++"R 	c #0F69E6",
++"S 	c #0D67E2",
++"T 	c #0D66E1",
++"U 	c #0C65E0",
++"V 	c #0C64E0",
++"W 	c #0C63E0",
++"X 	c #0E64E2",
++"Y 	c #1874F2",
++"Z 	c #2C96FF",
++"` 	c #2E97FE",
++" .	c #2A91FE",
++"..	c #2C93FE",
++"+.	c #2F94FE",
++"@.	c #3097FE",
++"#.	c #3098FE",
++"$.	c #3197FE",
++"%.	c #359BFE",
++"&.	c #40ACFF",
++"*.	c #44B1FF",
++"=.	c #45B2FF",
++"-.	c #46B2FF",
++";.	c #47B3FF",
++">.	c #3098FD",
++",.	c #1475EE",
++"'.	c #0E6AE6",
++").	c #0C69E2",
++"!.	c #0C68E1",
++"~.	c #0C67E0",
++"{.	c #0C66E0",
++"].	c #0B63E0",
++"^.	c #0E65E2",
++"/.	c #1876F2",
++"(.	c #2C97FF",
++"_.	c #309BFF",
++":.	c #1473F6",
++"<.	c #1069F3",
++"[.	c #106CF3",
++"}.	c #1069F4",
++"|.	c #1068F8",
++"1.	c #106CF8",
++"2.	c #106DF6",
++"3.	c #116EF6",
++"4.	c #1475F8",
++"5.	c #39A3FE",
++"6.	c #3099FE",
++"7.	c #1478F0",
++"8.	c #0E6CE7",
++"9.	c #0C6AE4",
++"0.	c #0E67E2",
++"a.	c #1878F3",
++"b.	c #319BFE",
++"c.	c #116DF4",
++"d.	c #106AF3",
++"e.	c #106AF4",
++"f.	c #1067F7",
++"g.	c #106BF8",
++"h.	c #106DF8",
++"i.	c #106DF5",
++"j.	c #1271F7",
++"k.	c #1577F8",
++"l.	c #36A0FE",
++"m.	c #319AFE",
++"n.	c #147AF0",
++"o.	c #0E6EE8",
++"p.	c #0C6CE6",
++"q.	c #0C68E2",
++"r.	c #0E68E4",
++"s.	c #1A7BF4",
++"t.	c #2D97FF",
++"u.	c #329CFE",
++"v.	c #126EF4",
++"w.	c #1068F5",
++"x.	c #1069F8",
++"y.	c #106EF8",
++"z.	c #106EF4",
++"A.	c #1270F7",
++"B.	c #1477F8",
++"C.	c #1578F8",
++"D.	c #369FFE",
++"E.	c #319BFD",
++"F.	c #1479EF",
++"G.	c #0E6EE7",
++"H.	c #0C6BE5",
++"I.	c #0F6AE6",
++"J.	c #1B7CF5",
++"K.	c #1270F4",
++"L.	c #106BF3",
++"M.	c #1374F8",
++"N.	c #369EFE",
++"O.	c #3099FB",
++"P.	c #1272E8",
++"Q.	c #0C6ADF",
++"R.	c #0C6AE0",
++"S.	c #0C6CE4",
++"T.	c #0F6AE7",
++"U.	c #1C7CF5",
++"V.	c #3EA5FF",
++"W.	c #329DFE",
++"X.	c #106DF7",
++"Y.	c #106EF5",
++"Z.	c #1271F8",
++"`.	c #116DF0",
++" +	c #0D62DE",
++".+	c #0D60DB",
++"++	c #257DF0",
++"@+	c #318CF6",
++"#+	c #318EF9",
++"$+	c #328EF9",
++"%+	c #2079EA",
++"&+	c #0B5ACA",
++"*+	c #0857C6",
++"=+	c #0A61D3",
++"-+	c #0C6CE5",
++";+	c #1C7AF5",
++">+	c #3A91FA",
++",+	c #3D94FA",
++"'+	c #3A92FA",
++")+	c #1969EC",
++"!+	c #1761EE",
++"~+	c #1764F0",
++"{+	c #1767EE",
++"]+	c #1868ED",
++"^+	c #1A6AEE",
++"/+	c #0D48BD",
++"(+	c #0A42AC",
++"_+	c #0B40AB",
++":+	c #164DCE",
++"<+	c #1D54DB",
++"[+	c #1D54DC",
++"}+	c #134AC5",
++"|+	c #083B9F",
++"1+	c #083CA2",
++"2+	c #0C4BB6",
++"3+	c #1261D4",
++"4+	c #1465DD",
++"5+	c #1365DE",
++"6+	c #1564DE",
++"7+	c #1766E2",
++"8+	c #2476EF",
++"9+	c #4599FC",
++"0+	c #469BFC",
++"a+	c #3A93FC",
++"b+	c #5273EE",
++"c+	c #5574EE",
++"d+	c #5272EC",
++"e+	c #2F53D4",
++"f+	c #2C4ED6",
++"g+	c #2C52D7",
++"h+	c #2C52D5",
++"i+	c #2E54D6",
++"j+	c #3053D4",
++"k+	c #1E3BA8",
++"l+	c #1C38A3",
++"m+	c #1D38A3",
++"n+	c #2C40BC",
++"o+	c #3545C6",
++"p+	c #3544C6",
++"q+	c #283EB6",
++"r+	c #1A349B",
++"s+	c #193398",
++"t+	c #1E3AA3",
++"u+	c #2A4FC1",
++"v+	c #2C55CA",
++"w+	c #2B55CC",
++"x+	c #2C55CC",
++"y+	c #2C55CD",
++"z+	c #2F56CF",
++"A+	c #3E61DA",
++"B+	c #5C78F0",
++"C+	c #5E79F2",
++"D+	c #5272F5",
++"E+	c #5573EE",
++"F+	c #5271EC",
++"G+	c #2C4ED5",
++"H+	c #2D52D3",
++"I+	c #2E55D4",
++"J+	c #3154D3",
++"K+	c #1E3AA7",
++"L+	c #1C39A2",
++"M+	c #1C38A2",
++"N+	c #2C42BC",
++"O+	c #3444C4",
++"P+	c #3344C3",
++"Q+	c #2D42BF",
++"R+	c #203AA9",
++"S+	c #1C36A2",
++"T+	c #2440B0",
++"U+	c #385DD0",
++"V+	c #3C63D6",
++"W+	c #3B62D6",
++"X+	c #3C62D7",
++"Y+	c #3D64D8",
++"Z+	c #4C6FE4",
++"`+	c #5C78EE",
++" @	c #5170F2",
++".@	c #5272EB",
++"+@	c #5273EB",
++"@@	c #5172EA",
++"#@	c #385CD9",
++"$@	c #2E51D4",
++"%@	c #2E54D4",
++"&@	c #2F54D2",
++"*@	c #3056D4",
++"=@	c #3256D2",
++"-@	c #1E3AA6",
++";@	c #1D39A2",
++">@	c #1F3BA9",
++",@	c #2C43BE",
++"'@	c #3244C2",
++")@	c #3244C1",
++"!@	c #3247C5",
++"~@	c #314CCA",
++"{@	c #385AD4",
++"]@	c #557DEF",
++"^@	c #557EEF",
++"/@	c #547DEE",
++"(@	c #517EEE",
++"_@	c #507EEE",
++":@	c #4C7AEC",
++"<@	c #4C78EA",
++"[@	c #4770EE",
++"}@	c #5072E7",
++"|@	c #5173E7",
++"1@	c #5474E6",
++"2@	c #5574E7",
++"3@	c #5575E8",
++"4@	c #5776E8",
++"5@	c #5978E9",
++"6@	c #5B78EA",
++"7@	c #3147C2",
++"8@	c #2D42BD",
++"9@	c #2C42BE",
++"0@	c #3043BE",
++"a@	c #3144BE",
++"b@	c #3144BF",
++"c@	c #3153CC",
++"d@	c #3058CD",
++"e@	c #3661D5",
++"f@	c #4F7DEC",
++"g@	c #507EEC",
++"h@	c #4D7EEB",
++"i@	c #4C7EEB",
++"j@	c #4B7FEA",
++"k@	c #4B7FE9",
++"l@	c #4A7EEA",
++"m@	c #467BE9",
++"n@	c #467AE5",
++"o@	c #4370E8",
++"p@	c #4E72E2",
++"q@	c #4F72E2",
++"r@	c #5072E2",
++"s@	c #5574E2",
++"t@	c #5877E5",
++"u@	c #5878E5",
++"v@	c #5978E6",
++"w@	c #5C7DE8",
++"x@	c #5D7CE9",
++"y@	c #2F48C0",
++"z@	c #2A42BA",
++"A@	c #2D41BA",
++"B@	c #3042BA",
++"C@	c #3043BA",
++"D@	c #3043B9",
++"E@	c #3046BD",
++"F@	c #2E57C8",
++"G@	c #2E58C8",
++"H@	c #3460D0",
++"I@	c #4F7DE8",
++"J@	c #4C7EE6",
++"K@	c #4A7FE6",
++"L@	c #4A7FE5",
++"M@	c #4A7FE4",
++"N@	c #477CE4",
++"O@	c #457AE4",
++"P@	c #4478DE",
++"Q@	c #406FE4",
++"R@	c #4B70DE",
++"S@	c #4D72DE",
++"T@	c #4E72DE",
++"U@	c #5073DD",
++"V@	c #5675DF",
++"W@	c #5676E1",
++"X@	c #587AE2",
++"Y@	c #5A7CE4",
++"Z@	c #2E48BB",
++"`@	c #2942B6",
++" #	c #2A42B6",
++".#	c #2E42B5",
++"+#	c #2E43B5",
++"@#	c #2E42B4",
++"##	c #2D44B6",
++"$#	c #2C56C4",
++"%#	c #2C58C4",
++"&#	c #3260CC",
++"*#	c #4B7DE2",
++"=#	c #497DE0",
++"-#	c #477DE0",
++";#	c #487DE0",
++">#	c #467EE0",
++",#	c #467EDF",
++"'#	c #457DDE",
++")#	c #437ADD",
++"!#	c #4279DD",
++"~#	c #4177D9",
++"{#	c #3E6EDE",
++"]#	c #486ED8",
++"^#	c #4B71D9",
++"/#	c #4B72D9",
++"(#	c #4D72D8",
++"_#	c #5374DA",
++":#	c #5475DB",
++"<#	c #5578DC",
++"[#	c #567ADD",
++"}#	c #2C48B7",
++"|#	c #2742B1",
++"1#	c #2A42B1",
++"2#	c #2C42B1",
++"3#	c #2C42B0",
++"4#	c #2B44B2",
++"5#	c #2A56BF",
++"6#	c #2A57BF",
++"7#	c #315EC7",
++"8#	c #467CDC",
++"9#	c #457CDA",
++"0#	c #447CDA",
++"a#	c #437CDA",
++"b#	c #437CD8",
++"c#	c #427CD8",
++"d#	c #427AD8",
++"e#	c #4077D7",
++"f#	c #3F76D5",
++"g#	c #3F75D4",
++"h#	c #3C6FD8",
++"i#	c #466ED2",
++"j#	c #486ED4",
++"k#	c #4A70D4",
++"l#	c #4A70D3",
++"m#	c #4E72D4",
++"n#	c #5174D6",
++"o#	c #5074D6",
++"p#	c #5276D6",
++"q#	c #5277D6",
++"r#	c #2A46B2",
++"s#	c #2540AC",
++"t#	c #2840AC",
++"u#	c #2A42AC",
++"v#	c #2A41AC",
++"w#	c #2A44AE",
++"x#	c #2955BA",
++"y#	c #2856BA",
++"z#	c #2E5EC2",
++"A#	c #447AD6",
++"B#	c #437AD5",
++"C#	c #417AD4",
++"D#	c #407AD2",
++"E#	c #3F79D1",
++"F#	c #3E78D0",
++"G#	c #3E76D1",
++"H#	c #3E75D2",
++"I#	c #3C74CF",
++"J#	c #3B73CE",
++"K#	c #3A6FD5",
++"L#	c #436CCC",
++"M#	c #456ECE",
++"N#	c #466FCE",
++"O#	c #4A71CE",
++"P#	c #4E73D0",
++"Q#	c #4E74D0",
++"R#	c #4F74D0",
++"S#	c #4E74CF",
++"T#	c #2846AD",
++"U#	c #2440A8",
++"V#	c #2340A8",
++"W#	c #2640A7",
++"X#	c #2740A7",
++"Y#	c #2841A7",
++"Z#	c #2843A9",
++"`#	c #2652B5",
++" $	c #2552B5",
++".$	c #2B5CBC",
++"+$	c #417AD0",
++"@$	c #3F79CE",
++"#$	c #3E78CC",
++"$$	c #3C76CA",
++"%$	c #3B76C8",
++"&$	c #3B74C9",
++"*$	c #3B74CC",
++"=$	c #3A73CD",
++"-$	c #3871CA",
++";$	c #3870C9",
++">$	c #386ED0",
++",$	c #426CC7",
++"'$	c #426CC9",
++")$	c #446EC9",
++"!$	c #466FC9",
++"~$	c #4A72CA",
++"{$	c #4C73CC",
++"]$	c #4B72CB",
++"^$	c #2E4FB0",
++"/$	c #2340A4",
++"($	c #223FA4",
++"_$	c #223FA3",
++":$	c #233FA3",
++"<$	c #2442A5",
++"[$	c #224FB0",
++"}$	c #2350B2",
++"|$	c #2E62BC",
++"1$	c #3E79CB",
++"2$	c #3B77C8",
++"3$	c #3A76C5",
++"4$	c #3873C2",
++"5$	c #3771C2",
++"6$	c #3771C5",
++"7$	c #3771C8",
++"8$	c #3770C6",
++"9$	c #3670C5",
++"0$	c #366FC6",
++"a$	c #346CCD",
++"b$	c #3F6BC2",
++"c$	c #406BC2",
++"d$	c #426DC4",
++"e$	c #426EC4",
++"f$	c #456FC4",
++"g$	c #4A72C6",
++"h$	c #4A73C7",
++"i$	c #4A72C7",
++"j$	c #466EC3",
++"k$	c #3E65BC",
++"l$	c #4065BD",
++"m$	c #4166BD",
++"n$	c #4066BD",
++"o$	c #4066BC",
++"p$	c #3F66BD",
++"q$	c #346BBF",
++"r$	c #356DC0",
++"s$	c #3B76C6",
++"t$	c #3B78C4",
++"u$	c #3874C1",
++"v$	c #3672BE",
++"w$	c #3570BD",
++"x$	c #346EBF",
++"y$	c #346EC1",
++"z$	c #346DC1",
++"A$	c #346CC0",
++"B$	c #346DC0",
++"C$	c #346EC2",
++"D$	c #316AC9",
++"E$	c #3C6ABE",
++"F$	c #3D6BBE",
++"G$	c #3F6CC0",
++"H$	c #416CC0",
++"I$	c #426DC0",
++"J$	c #4570C0",
++"K$	c #4872C2",
++"L$	c #4A76C4",
++"M$	c #4E79C7",
++"N$	c #4F7AC7",
++"O$	c #507AC8",
++"P$	c #4E79C8",
++"Q$	c #3D79C4",
++"R$	c #3C7AC4",
++"S$	c #3A79C2",
++"T$	c #3776BF",
++"U$	c #3572BB",
++"V$	c #336FBA",
++"W$	c #326DBB",
++"X$	c #326CBD",
++"Y$	c #326ABD",
++"Z$	c #3169BB",
++"`$	c #3169BA",
++" %	c #316ABB",
++".%	c #2E66C3",
++"+%	c #396ABA",
++"@%	c #3C6BBA",
++"#%	c #3C6ABB",
++"$%	c #3E6CBD",
++"%%	c #406CBD",
++"&%	c #406DBD",
++"*%	c #426EBD",
++"=%	c #456FBD",
++"-%	c #4672BF",
++";%	c #4672C0",
++">%	c #4874C0",
++",%	c #4976C1",
++"'%	c #4B78C2",
++")%	c #4C78C3",
++"!%	c #4E78C3",
++"~%	c #4B78C3",
++"{%	c #3C78C1",
++"]%	c #3A79C1",
++"^%	c #3778BE",
++"/%	c #3673BA",
++"(%	c #326EB8",
++"_%	c #326DBA",
++":%	c #326BBB",
++"<%	c #316ABA",
++"[%	c #2F68B9",
++"}%	c #2E66B8",
++"|%	c #3067BB",
++"1%	c #2C63BF",
++"2%	c #3769B8",
++"3%	c #3969B8",
++"4%	c #3B6AB8",
++"5%	c #3C6AB8",
++"6%	c #3E6CBA",
++"7%	c #3F6DBA",
++"8%	c #416DBA",
++"9%	c #446FBB",
++"0%	c #4672BC",
++"a%	c #4672BD",
++"b%	c #4674BC",
++"c%	c #4674BD",
++"d%	c #4775BE",
++"e%	c #4575BE",
++"f%	c #3A76C0",
++"g%	c #3776BE",
++"h%	c #3573BB",
++"i%	c #326EB6",
++"j%	c #306CB7",
++"k%	c #316CBB",
++"l%	c #3068B8",
++"m%	c #2E66B9",
++"n%	c #2E66BA",
++"o%	c #3068BE",
++"p%	c #2B62C0",
++"q%	c #3769B6",
++"r%	c #3A68B6",
++"s%	c #3B69B6",
++"t%	c #406DBA",
++"u%	c #436EBA",
++"v%	c #4571BB",
++"w%	c #4372BC",
++"x%	c #3774BE",
++"y%	c #3875C3",
++"z%	c #316DB6",
++"A%	c #2F6BB5",
++"B%	c #306BB9",
++"C%	c #326ABB",
++"D%	c #3169BD",
++"E%	c #3169BF",
++"F%	c #3169C0",
++"G%	c #3067BE",
++"H%	c #2E66BC",
++"I%	c #285FBC",
++"J%	c #3667B5",
++"K%	c #3768B6",
++"L%	c #3C6BB9",
++"M%	c #416EBA",
++"N%	c #4470BA",
++"O%	c #4570BB",
++"P%	c #3873BD",
++"Q%	c #3A76C6",
++"R%	c #3974C3",
++"S%	c #336FBC",
++"T%	c #316CB9",
++"U%	c #326CBB",
++"V%	c #336CBD",
++"W%	c #346CC2",
++"X%	c #326AC2",
++"Y%	c #3068C1",
++"Z%	c #2B64B8",
++"`%	c #245AB6",
++" &	c #3466B5",
++".&	c #3668B5",
++"+&	c #3868B6",
++"@&	c #3F6CBA",
++"#&	c #426FBA",
++"$&	c #436FBA",
++"%&	c #4271BA",
++"&&	c #3772BB",
++"*&	c #3975C3",
++"=&	c #3974C4",
++"-&	c #3772C2",
++";&	c #346FBF",
++">&	c #326CBC",
++",&	c #3169BC",
++"'&	c #2D65BC",
++")&	c #2961B5",
++"!&	c #2861B4",
++"~&	c #2056B2",
++". . + @ # $ % % & * * * = - - ; ; > > ; , - - * * * ' ) % % ! ~ ",
++". { ] ^ / % ) ' * * ( , > > _ : < < < : : [ > ; - * * * } % % | ",
++"+ 1 ^ % % & * * ( 2 > 3 < < < < < < < < < < < 3 _ > - * * ' 4 5 ",
++"@ ^ % % 6 * * - > 3 < < < < 7 8 9 9 0 0 a b < < < < [ ; = * c d ",
++"e / % ' * * , f < < < 7 g h i j j j j j i i 9 8 b < < 3 > - * + ",
++"$ % & * * ; [ < < a 9 i j k k k k h l m n o p p q r s t u > - v ",
++"% ) * * , _ < < 8 w k k k k k k x y z A B C D E F G G H I [ > J ",
++"% ' * , [ < < K L k k k k x M N O P Q R S T U U V W W X Y > < Z ",
++"& * = `  . ...+. at .#.$.%.&.*.=.-.;.>.,.'.).!.~.{.U ].].^./.< < (.",
++"c * _.:.<.[.}.|.1.2.3.4.5.;.;.;.;.6.7.8.9.).).!.{.U V 0.a.8 b (.",
++"* ( b.c.d.e.f.g.h.i.j.k.l.;.;.;.;.m.n.o.p.p.9.).q.{.{.r.s.h b t.",
++"* , u.v.[.w.x.y.z.A.B.C.D.;.;.;.;.E.F.G.p.p.p.H.).q.~.I.J.w 9 } ",
++"* > u.K.L.f.1.2.3.M.C.C.N.;.;.;.;.O.P.Q.R.S.p.p.H.).).T.U.V.w 6 ",
++"- > W.K.w.|.X.Y.Z.`. +.+++ at +@+#+$+%+&+*+=+Q.-+p.p.9.).E ;+V.i - ",
++">+,+'+)+!+~+{+]+^+/+(+_+:+<+<+[+[+}+|+1+2+3+4+5+5+5+6+7+8+9+0+a+",
++"b+c+d+e+f+g+h+i+j+k+l+m+n+o+o+o+p+q+r+s+t+u+v+w+w+x+y+z+A+B+C+D+",
++"b+E+F+e+G+h+H+I+J+K+L+M+N+O+O+P+P+Q+R+S+T+U+V+V+W+W+X+Y+Z+`+`+ @",
++". at +@@@#@$@%@&@*@=@-@;@>@,@'@)@)@)@)@!@~@{@]@^@/@(@(@_ at _@_@:@<@[@",
++"}@|@|@1 at 2@3 at 4@5 at 6@7 at 8@9 at 0@a at a@a at a@b at c@d at e@f at g@h at i@j at j@k at l@m at n@o@",
++"p at q@r at s@t at u@v at w@x at y@z at A@B at C@D at D@D at E@F at G@H at I@J at K@L at L@L at M@N at O@P at Q@",
++"R at S@T at U@V at W@W at X@Y at Z@`@ #.#+#+#+#@###$#%#&#*#=#-#;#>#,#'#)#!#~#{#",
++"]#^#/#(#_#:#:#<#[#}#|#|#1#2#2#3#3#4#5#6#7#8#9#0#a#b#c#d#e#f#g#h#",
++"i#j#k#l#m#n#o#p#q#r#s#s#s#t#u#v#u#w#x#y#z#A#B#C#D#E#F#G#H#I#J#K#",
++"L#M#N#N#O#P#Q#R#S#T#U#U#V#V#W#X#Y#Z#`# $.$+$@$#$$$%$&$*$=$-$;$>$",
++",$'$)$)$!$~${${$]$^$/$($_$_$_$_$:$<$[$}$|$1$2$3$4$5$6$7$8$9$0$a$",
++"b$c$d$e$e$f$g$h$i$j$k$l$m$m$n$n$o$p$q$r$s$t$u$v$w$x$y$z$A$B$C$D$",
++"E$F$G$H$I$I$J$K$K$K$K$L$M$N$O$O$O$P$Q$R$S$T$U$V$W$X$Y$Z$`$ %Y$.%",
++"+%@%#%$%%%&%*%=%-%;%;%;%>%,%'%)%!%~%{%]%^%/%(%_%:%<%[%}%}%}%|%1%",
++"2%3%4%5%6%7%7%8%9%0%a%a%0%0%b%c%d%e%f%g%h%i%j%k%<%l%}%m%m%n%o%p%",
++"q%q%r%s%5%6%7%7%t%u%v%0%0%0%0%0%0%w%x%y%v$z%A%B%C%Z$D%E%F%G%H%I%",
++"J%q%K%s%s%L%6%7%7%7%M%N%O%0%0%0%0%w%P%Q%R%S%T%U%V%A$W%X%Y%H%Z%`%",
++" &.&q%+&s%s%5%6%@&7%7%t%t%#&$&N%N%%&&&*&=&-&;&>&C%,&o%'&)&!&!&~&"};
+-- 
+tg: (da3323c..) topic/debian/viewericon (depends on: master)
diff --git a/debian/patches/topic/features/jira-backported/AvatarLoginList.diff b/debian/patches/topic/features/jira-backported/AvatarLoginList.diff
new file mode 100644
index 0000000..b0bbd4a
--- /dev/null
+++ b/debian/patches/topic/features/jira-backported/AvatarLoginList.diff
@@ -0,0 +1,499 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/features/jira-backported/AvatarLoginList
+
+Add login choice for multiple avatars
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llui/llcombobox.cpp                          |    8 +++
+ indra/llui/llcombobox.h                            |    1 +
+ indra/newview/app_settings/settings.xml            |   44 +++++++++++++
+ indra/newview/llpanelgeneral.cpp                   |    8 ++-
+ indra/newview/llpanellogin.cpp                     |   64 +++++++++++++++++++
+ indra/newview/llpanellogin.h                       |    2 +
+ indra/newview/llstartup.cpp                        |   43 +++++++++++++
+ indra/newview/llviewercontrol.cpp                  |   28 ++++++++
+ .../skins/default/xui/en-us/panel_login.xml        |   12 ++--
+ .../xui/en-us/panel_preferences_general.xml        |   66 ++++++++++++--------
+ 10 files changed, 245 insertions(+), 31 deletions(-)
+
+diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
+index 3aec2ee..27c1ace 100644
+--- a/indra/llui/llcombobox.cpp
++++ b/indra/llui/llcombobox.cpp
+@@ -450,6 +450,14 @@ void LLComboBox::setButtonVisible(BOOL visible)
+ 	}
+ }
+ 
++void LLComboBox::setTextEntryVisible(BOOL visible)
++{
++	if (mTextEntry)
++	{
++		mTextEntry->setVisible(visible);
++	}
++}
++
+ void LLComboBox::draw()
+ {
+ 	mButton->setEnabled(getEnabled() /*&& !mList->isEmpty()*/);
+diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
+index efcb798..5eac287 100644
+--- a/indra/llui/llcombobox.h
++++ b/indra/llui/llcombobox.h
+@@ -173,6 +173,7 @@ public:
+ 	void			setTextEntryCallback( void (*cb)(LLLineEditor*, void*) ) { mTextEntryCallback = cb; }
+ 
+ 	void			setButtonVisible(BOOL visible);
++	void			setTextEntryVisible(BOOL visible);
+ 
+ 	static void		onButtonDown(void *userdata);
+ 	static void		onItemSelected(LLUICtrl* item, void *userdata);
+diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
+index 688dcab..b370177 100644
+--- a/indra/newview/app_settings/settings.xml
++++ b/indra/newview/app_settings/settings.xml
+@@ -4158,6 +4158,50 @@
+       <key>Value</key>
+       <integer>0</integer>
+     </map>
++    <key>LoginMRUClearPassword</key>
++    <map>
++      <key>Comment</key>
++      <string>Clear password upon changing the avatar name on the login screen</string>
++      <key>Persist</key>
++      <integer>1</integer>
++      <key>Type</key>
++      <string>Boolean</string>
++      <key>Value</key>
++      <integer>1</integer>
++    </map>
++    <key>LoginMRUEnabled</key>
++    <map>
++      <key>Comment</key>
++      <string>Allow saving a list of alternate avatar names upon login</string>
++      <key>Persist</key>
++      <integer>1</integer>
++      <key>Type</key>
++      <string>Boolean</string>
++      <key>Value</key>
++      <integer>0</integer>
++    </map>
++    <key>LoginMRUList</key>
++    <map>
++      <key>Comment</key>
++      <string>List of previous avatar names presented at login</string>
++      <key>Persist</key>
++      <integer>1</integer>
++      <key>Type</key>
++      <string>LLSD</string>
++      <key>Value</key>
++      <array/>
++    </map>
++    <key>LoginMRULength</key>
++    <map>
++      <key>Comment</key>
++      <string>Number of names to store in LoginMRUList</string>
++      <key>Persist</key>
++      <integer>1</integer>
++      <key>Type</key>
++      <string>S32</string>
++      <key>Value</key>
++      <integer>10</integer>
++    </map>
+     <key>LSLFindCaseInsensitivity</key>
+         <map>
+         <key>Comment</key>
+diff --git a/indra/newview/llpanelgeneral.cpp b/indra/newview/llpanelgeneral.cpp
+index f370116..0067369 100644
+--- a/indra/newview/llpanelgeneral.cpp
++++ b/indra/newview/llpanelgeneral.cpp
+@@ -40,6 +40,7 @@
+ #include "lluictrlfactory.h"
+ #include "llurlsimstring.h"
+ #include "llviewercontrol.h"
++#include "llstartup.h"
+ 
+ LLPanelGeneral::LLPanelGeneral()
+ {
+@@ -70,6 +71,9 @@ BOOL LLPanelGeneral::postBuild()
+ 	childSetValue("ui_scale_slider", gSavedSettings.getF32("UIScaleFactor"));
+ 	childSetValue("ui_auto_scale", gSavedSettings.getBOOL("UIAutoScale"));
+ 
++	childSetValue("save_names_checkbox", gSavedSettings.getBOOL("LoginMRUEnabled"));
++	childSetValue("clear_password_checkbox", gSavedSettings.getBOOL("LoginMRUClearPassword"));
++
+ 	LLComboBox* crash_behavior_combobox = getChild<LLComboBox>("crash_behavior_combobox");
+ 	crash_behavior_combobox->setCurrentByIndex(gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING));
+ 	
+@@ -87,7 +91,9 @@ void LLPanelGeneral::apply()
+ {
+ 	LLComboBox* fade_out_combobox = getChild<LLComboBox>("fade_out_combobox");
+ 	gSavedSettings.setS32("RenderName", fade_out_combobox->getCurrentIndex());
+-	
++
++	gSavedSettings.setBOOL("LoginMRUEnabled", childGetValue("save_names_checkbox"));
++	gSavedSettings.setBOOL("LoginMRUClearPassword", childGetValue("clear_password_checkbox"));
+ 	gSavedSettings.setBOOL("LoginLastLocation", childGetValue("default_start_location").asString() == "MyLastLocation");
+ 	gSavedSettings.setBOOL("ShowStartLocation", childGetValue("show_location_checkbox"));
+ 	gSavedSettings.setBOOL("RenderHideGroupTitleAll", childGetValue("show_all_title_checkbox"));
+diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
+index 64eecd6..4a0ba2b 100644
+--- a/indra/newview/llpanellogin.cpp
++++ b/indra/newview/llpanellogin.cpp
+@@ -393,6 +393,33 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
+ 	childSetPrevalidate("first_name_edit", LLLineEditor::prevalidatePrintableNoSpace);
+ 	childSetPrevalidate("last_name_edit", LLLineEditor::prevalidatePrintableNoSpace);
+ 
++	LLComboBox* name_combo = getChild<LLComboBox>("name_combo");
++	// Only works as intended with this combination of flags,
++	// and in this order of setting them, therefore overriding xui
++	name_combo->setAllowTextEntry(TRUE);
++	name_combo->setTextEntryVisible(FALSE);
++	// Send it down the line, or the invisible text entry covers up our normal
++	// input fields if placed after them in xui
++	sendChildToBack(getChildView("name_combo"));
++
++	bool mru_enabled = gSavedSettings.getBOOL("LoginMRUEnabled");
++	if (mru_enabled)
++	{
++		LLSD name_list = gSavedSettings.getLLSD("LoginMRUList");
++		if (name_list.isArray())
++		{
++			for (LLSD::array_iterator iter = name_list.endArray() - 1; iter != name_list.beginArray()-1; --iter)
++			{
++				if (iter->isMap() && iter->has("first") && iter->has("last"))
++				{
++					name_combo->add((*iter)["first"].asString() + " " + (*iter)["last"].asString(), *iter);
++				}
++			}
++		}
++		childSetCommitCallback("name_combo", onSelectLoginMRU, this);
++	}
++	setLoginMRUEnabled(mru_enabled);
++
+ 	childSetCommitCallback("password_edit", mungePassword);
+ 	childSetKeystrokeCallback("password_edit", onPassKey, this);
+ 	childSetUserData("password_edit", this);
+@@ -1214,3 +1241,40 @@ void LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe, void*)
+ 		onSelectServer(combo, NULL);	
+ 	}
+ }
++
++// static
++void LLPanelLogin::setLoginMRUEnabled(bool enabled)
++{
++	if (!sInstance)
++	{
++		return;
++	}
++
++	LLComboBox* combo = sInstance->getChild<LLComboBox>("name_combo");
++	if (!enabled) combo->removeall();
++	combo->setButtonVisible(enabled);
++	combo->setEnabled(enabled && combo->getItemCount() != 0);
++}
++
++//static
++void LLPanelLogin::onSelectLoginMRU(LLUICtrl* caller, void* user_data)
++{
++	LLPanelLogin* panel = (LLPanelLogin*) user_data;
++	LLComboBox* name_combo = (LLComboBox*) caller;
++	LLLineEditor* first_name_edit = panel->getChild<LLLineEditor>("first_name_edit");
++	LLLineEditor* last_name_edit = panel->getChild<LLLineEditor>("last_name_edit");
++	LLLineEditor* password_edit = panel->getChild<LLLineEditor>("password_edit");
++
++	LLSD selected_name = name_combo->getValue();
++	std::string first_name = selected_name["first"].asString();
++	std::string last_name = selected_name["last"].asString();
++
++	if (gSavedSettings.getBOOL("LoginMRUClearPassword")
++		&& (first_name_edit->getText() != first_name || last_name_edit->getText() != last_name))
++	{
++		password_edit->setText(LLStringUtil::null);
++	}
++	first_name_edit->setText(first_name);
++	last_name_edit->setText(last_name);
++	password_edit->setFocus(TRUE);
++}
+diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
+index dba6cf4..2de5dde 100644
+--- a/indra/newview/llpanellogin.h
++++ b/indra/newview/llpanellogin.h
+@@ -85,6 +85,7 @@ public:
+ 
+ 	static void setFields(const std::string& firstname, const std::string& lastname, 
+ 		const std::string& password, BOOL remember);
++	static void setLoginMRUEnabled(bool enabled);
+ 
+ 	static void addServer(const std::string& server, S32 domain_name);
+ 	static void refreshLocation( bool force_visible );
+@@ -115,6 +116,7 @@ private:
+ 	static void onPassKey(LLLineEditor* caller, void* user_data);
+ 	static void onSelectServer(LLUICtrl*, void*);
+ 	static void onServerComboLostFocus(LLFocusableElement*, void*);
++	static void onSelectLoginMRU(LLUICtrl*, void*);
+ 	
+ private:
+ 	LLPointer<LLUIImage> mLogoImage;
+diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
+index dd4b66c..b980e2e 100644
+--- a/indra/newview/llstartup.cpp
++++ b/indra/newview/llstartup.cpp
+@@ -1314,6 +1314,49 @@ bool idle_startup()
+ 			gSavedSettings.setString("FirstName", firstname);
+ 			gSavedSettings.setString("LastName", lastname);
+ 
++			if (gSavedSettings.getBOOL("LoginMRUEnabled"))
++			{
++				LLSD mru_list = gSavedSettings.getLLSD("LoginMRUList");
++				if (mru_list.isArray())
++				{
++					// Prepend the current login name to the MRU
++					LLSD login_entry(LLSD::emptyMap());
++					login_entry["first"] = firstname;
++					login_entry["last"] = lastname;
++					mru_list.insert(0, login_entry);
++
++					const S32 names_max = gSavedSettings.getS32("LoginMRULength");
++					for (S32 i = 1; i != mru_list.size(); )
++					{
++						// Trim excess entries
++						if (i >= names_max)
++						{
++							mru_list.erase(i);
++							continue;
++						}
++						// Remove any other instances of the current name
++						login_entry = mru_list[i];
++						if (login_entry.isMap() && login_entry.has("first") && login_entry.has("last"))
++						{
++							if (login_entry["first"].asString() == firstname
++								&& login_entry["last"].asString() == lastname)
++							{
++								mru_list.erase(i);
++							}
++							else
++							{
++								++i;
++							}
++						}
++					}
++					gSavedSettings.setLLSD("LoginMRUList", mru_list);
++				}
++			}
++			else
++			{
++				gSavedSettings.setLLSD("LoginMRUList", LLSD::emptyArray());
++			}
++
+ 			if (remember_password)
+ 			{
+ 				   save_password_to_disk(password.c_str());
+diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
+index cd9afeb..6615e35 100644
+--- a/indra/newview/llviewercontrol.cpp
++++ b/indra/newview/llviewercontrol.cpp
+@@ -70,6 +70,8 @@
+ #include "llvosurfacepatch.h"
+ #include "llvowlsky.h"
+ #include "llrender.h"
++#include "llstartup.h"
++#include "llpanellogin.h"
+ 
+ #ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+ BOOL 				gHackGodmode = FALSE;
+@@ -429,6 +431,31 @@ bool handleVoiceClientPrefsChanged(const LLSD& newvalue)
+ 	return true;
+ }
+ 
++bool handleLoginMRUPrefsChanged(const LLSD& newvalue)
++{
++	bool enabled = newvalue.asBoolean();
++	if (enabled)
++	{
++		// Initialize the list with the current name if logged in
++		if (LLStartUp::getStartupState() >= STATE_WORLD_INIT)
++		{
++			// list was previously empty, no need to go through sorting
++			LLSD names = LLSD::emptyArray();
++			names.append(LLSD::emptyMap());
++			names[0]["first"] = gSavedSettings.getString("FirstName");
++			names[0]["last"] = gSavedSettings.getString("LastName");
++			gSavedSettings.setLLSD("LoginMRUList", names);
++		}
++	}
++	else
++	{
++		// Clear the list of avatar names when disabled
++		gSavedSettings.setLLSD("LoginMRUList", LLSD::emptyArray());
++	}
++	LLPanelLogin::setLoginMRUEnabled(enabled);
++	return true;
++}
++
+ ////////////////////////////////////////////////////////////////////////////
+ 
+ void settings_setup_listeners()
+@@ -556,6 +583,7 @@ void settings_setup_listeners()
+ 	gSavedSettings.getControl("VoiceInputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
+ 	gSavedSettings.getControl("VoiceOutputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
+ 	gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));	
++	gSavedSettings.getControl("LoginMRUEnabled")->getSignal()->connect(boost::bind(&handleLoginMRUPrefsChanged, _1));	
+ }
+ 
+ template <> eControlType get_control_type<U32>(const U32& in, LLSD& out) 
+diff --git a/indra/newview/skins/default/xui/en-us/panel_login.xml b/indra/newview/skins/default/xui/en-us/panel_login.xml
+index 2122ee7..b048f94 100644
+--- a/indra/newview/skins/default/xui/en-us/panel_login.xml
++++ b/indra/newview/skins/default/xui/en-us/panel_login.xml
+@@ -11,26 +11,28 @@
+ 	<string name="forgot_password_url">
+ 		http://secondlife.com/account/request.php
+ 	</string>
++	<combo_box name="name_combo" allow_text_entry="true" follows="left|bottom"
++	     font="SansSerif" left="32" bottom="30" width="252" height="20" mouse_opaque="true"/>
+ 	<text bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
+ 	     bottom="54" drop_shadow_visible="true" follows="left|bottom"
+ 	     font="SansSerif" h_pad="0" halign="left" height="16"
+-	     left="32" mouse_opaque="true" name="first_name_text" v_pad="0" width="120">
++	     left="32" mouse_opaque="true" name="first_name_text" v_pad="0" width="114">
+ 		First Name:
+ 	</text>
+ 	<line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="-24"
+ 	     follows="left|bottom" font="SansSerif" handle_edit_keys_directly="true"
+ 	     height="20" left="32" max_length="31" mouse_opaque="true"
+-	     name="first_name_edit" select_all_on_focus_received="true" width="120" />
++	     name="first_name_edit" select_all_on_focus_received="true" width="118" />
+ 	<text bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
+ 	     bottom="54" drop_shadow_visible="true" follows="left|bottom"
+ 	     font="SansSerif" h_pad="0" halign="left" height="16"
+-	     left="164" mouse_opaque="true" name="last_name_text" v_pad="0" width="120">
++	     left_delta="117" mouse_opaque="true" name="last_name_text" v_pad="0" width="114">
+ 		Last Name:
+ 	</text>
+ 	<line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="-24"
+ 	     follows="left|bottom" font="SansSerif" handle_edit_keys_directly="true"
+-	     height="20" left="164" max_length="31" mouse_opaque="true"
+-	     name="last_name_edit" select_all_on_focus_received="true" width="120" />
++	     height="20" left_delta="0" max_length="31" mouse_opaque="true"
++	     name="last_name_edit" select_all_on_focus_received="true" width="114" />
+ 	<text bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
+ 	     bottom="54" drop_shadow_visible="true" follows="left|bottom"
+ 	     font="SansSerif" h_pad="0" halign="left" height="16"
+diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml
+index ea04dfc..8a19967 100644
+--- a/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml
++++ b/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml
+@@ -2,22 +2,49 @@
+ <panel border="true" bottom="-409" enabled="true" follows="left|top|right|bottom"
+      height="408" label="General" left="102" mouse_opaque="true"
+      name="general_panel" width="517">
+-  <radio_group bottom="-45" draw_border="false" follows="left|bottom" height="40" left="151"
++	<text type="string" length="1" bottom="-25" follows="left|top" font="SansSerifSmall" h_pad="0"
++	     halign="left" height="16" left="10" name="alt_avatars_textbox" v_pad="0"
++	     width="394">
++		Recent Logins:
++	</text>
++	<check_box name="save_names_checkbox" follows="left|top"
++	     left="151" bottom_delta="0" width="149" height="16"
++	     label="Save name list" initial_value="true"
++	     radio_style="false" font="SansSerifSmall"
++	     tool_tip="Save a list of recently used avatar names.\nYou may wish to turn this off if more than one person has access to this computer."/>
++	<check_box bottom_delta="0" follows="left|top"
++	     font="SansSerifSmall" height="16" initial_value="false"
++	     label="Clear password when selecting" left_delta="105" mouse_opaque="true"
++		 tool_tip="Clears the password entry box when selecting a different avatar name at login."
++	     name="clear_password_checkbox" radio_style="false" width="200" />
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	     bottom_delta="-22" drop_shadow_visible="true" enabled="true" follows="left|top"
++	     font="SansSerifSmall" h_pad="0" halign="left" height="10" left="10"
++	     mouse_opaque="true" name="start_location_textbox" v_pad="0" width="394">
++		Start Location:
++	</text>
++  <radio_group bottom_delta="-22" draw_border="false" follows="left|bottom" height="40" left="151"
+ 	     name="default_start_location" width="220">
+     <radio_item bottom="-20" height="20" left="0" name="MyHome" width="50"
+ 		  tool_tip="Log into my home location by default.">
+       My Home
+     </radio_item>
+-    <radio_item bottom="-20" height="20" left="100" name="MyLastLocation" width="50"
++    <radio_item bottom="-20" height="20" left="105" name="MyLastLocation" width="50"
+ 		  tool_tip="Log into my last location by default.">
+       My Last Location
+     </radio_item>
+   </radio_group>
+-  <check_box bottom="-44" enabled="true" follows="left|top"
++	<check_box bottom_delta="0" enabled="true" follows="left|top"
+        font="SansSerifSmall" height="16" initial_value="true"
+        label="Show Start Location on Login Screen" left="151" mouse_opaque="true"
+        name="show_location_checkbox" radio_style="false" width="256" />
+-	<combo_box bottom_delta="-25" follows="left|top" height="18" left="155"
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	     bottom_delta="-25" drop_shadow_visible="true" enabled="true" follows="left|top"
++	     font="SansSerifSmall" h_pad="0" halign="left" height="10" left="10"
++	     mouse_opaque="true" name="show_names_textbox" v_pad="0" width="394">
++		Show Name Tags:
++	</text>
++	<combo_box bottom_delta="-4" follows="left|top" height="18" left="155"
+ 	     mouse_opaque="true" name="fade_out_combobox" width="146">
+ 		<combo_item name="Never" value="Never">
+ 			Never
+@@ -30,13 +57,14 @@
+ 		</combo_item>
+ 	</combo_box>
+ 	<check_box bottom_delta="-25" follows="left|top"
+-	     font="SansSerifSmall" height="16" initial_value="true"
+-	     label="Small Avatar Names" left="151" name="small_avatar_names_checkbox"
+-	     width="200" />
+-	<check_box bottom_delta="-18" follows="left|top"
+ 	     font="SansSerifSmall" height="16" initial_value="false"
+ 	     label="Hide My Name On My Screen" left="151" name="show_my_name_checkbox"
++	     width="180" />
++	<check_box bottom_delta="0" follows="left|top"
++	     font="SansSerifSmall" height="16" initial_value="true"
++	     label="Small Avatar Names" left_delta="180" name="small_avatar_names_checkbox"
+ 	     width="200" />
++	     width="149" />
+ 	<text type="string" length="1" bottom_delta="-24" follows="left|top" font="SansSerifSmall" h_pad="0"
+ 	     halign="left" height="16" left="10" name="group_titles_textbox" v_pad="0"
+ 	     width="394">
+@@ -44,12 +72,12 @@
+ 	</text>
+ 	<check_box bottom_delta="0" follows="left|top"
+ 	     font="SansSerifSmall" height="16" initial_value="false"
+-	     label="Hide All Group Titles" left="151" mouse_opaque="true"
+-	     name="show_all_title_checkbox" radio_style="false" width="256" />
+-	<check_box bottom_delta="-18" follows="left|top"
+-	     font="SansSerifSmall" height="16" initial_value="false"
+ 	     label="Hide My Group Title" left="151" name="show_my_title_checkbox"
+-	     radio_style="false" width="256" />
++	     radio_style="false" width="149" />
++	<check_box bottom_delta="0" follows="left|top"
++	     font="SansSerifSmall" height="16" initial_value="false"
++	     label="Hide All Group Titles" left_delta="180" mouse_opaque="true"
++	     name="show_all_title_checkbox" radio_style="false" width="200" />
+ 	<color_swatch border_color="0.45098 0.517647 0.607843 1" bottom="-210"
+ 	     can_apply_immediately="false" color="1 1 1 1"
+ 	     enabled="true" follows="left|top" height="48" label="" left="153"
+@@ -94,18 +122,6 @@
+ 	     name="show_search_panel" radio_style="false"
+ 	     tool_tip="Display the embedded search panel." width="256" />
+ 	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
+-	     bottom="-20" drop_shadow_visible="true" enabled="true" follows="left|top"
+-	     font="SansSerifSmall" h_pad="0" halign="left" height="10" left="10"
+-	     mouse_opaque="true" name="start_location_textbox" v_pad="0" width="394">
+-		Start Location:
+-	</text>
+-	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
+-	     bottom="-64" drop_shadow_visible="true" enabled="true" follows="left|top"
+-	     font="SansSerifSmall" h_pad="0" halign="left" height="10" left="10"
+-	     mouse_opaque="true" name="show_names_textbox" v_pad="0" width="394">
+-		Show Names:
+-	</text>
+-	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
+ 	     bottom="-184" drop_shadow_visible="true" enabled="true" follows="left|top"
+ 	     font="SansSerifSmall" h_pad="0" halign="left" height="10" left="10"
+ 	     mouse_opaque="true" name="effects_color_textbox" v_pad="0" width="394">
+-- 
+tg: (fd717f3..) topic/features/jira-backported/AvatarLoginList (depends on: upstream)
diff --git a/debian/patches/topic/features/jira-backported/VWR-11663_Save_Load_scripts.diff b/debian/patches/topic/features/jira-backported/VWR-11663_Save_Load_scripts.diff
new file mode 100644
index 0000000..a5f32e4
--- /dev/null
+++ b/debian/patches/topic/features/jira-backported/VWR-11663_Save_Load_scripts.diff
@@ -0,0 +1,190 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/features/jira-backported/VWR-11663_Save_Load_scripts
+
+<patch description>
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/newview/llfilepicker.cpp                     |   17 +++++
+ indra/newview/llfilepicker.h                       |    3 +
+ indra/newview/llpreviewscript.cpp                  |   62 ++++++++++++++++++++
+ indra/newview/llpreviewscript.h                    |    2 +
+ .../default/xui/en-us/floater_script_ed_panel.xml  |    6 ++
+ 5 files changed, 90 insertions(+), 0 deletions(-)
+
+diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
+index f9616ba..9522930 100644
+--- a/indra/newview/llfilepicker.cpp
++++ b/indra/newview/llfilepicker.cpp
+@@ -58,6 +58,7 @@ LLFilePicker LLFilePicker::sInstance;
+ #define XML_FILTER L"XML files (*.xml)\0*.xml\0"
+ #define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
+ #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
++#define TEXT_FILTER L"Text files (*.txt; *.rtf)\0*.txt;*.rtf;*.lsl\0"
+ #endif
+ 
+ //
+@@ -160,6 +161,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
+ 		ANIM_FILTER \
+ 		L"\0";
+ 		break;
++	case FFLOAD_TEXT:
++		mOFN.lpstrFilter = TEXT_FILTER \
++			L"\0";
++		break;
+ 	case FFLOAD_WAV:
+ 		mOFN.lpstrFilter = SOUND_FILTER \
+ 			L"\0";
+@@ -327,6 +332,18 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
+ 			L"Targa, Bitmap Images (*.tga; *.bmp)\0*.tga;*.bmp\0" \
+ 			L"\0";
+ 		break;
++	case FFSAVE_TEXT:
++		if (filename.empty())
++		{
++			wcsncpy( mFilesW,L"untitled.txt", FILENAME_BUFFER_SIZE);	/*Flawfinder: ignore*/
++		}
++		mOFN.lpstrDefExt = L"txt";
++		mOFN.lpstrFilter = 
++			L"Text files (*.txt)\0*.txt\0"
++			L"RTF Files (*.rtf)\0*.rtf\0"
++			L"LSL Files (*.lsl)\0*.lsl\0"
++			L"\0";
++		break;
+ 	case FFSAVE_WAV:
+ 		if (filename.empty())
+ 		{
+diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
+index aea414a..3dc0301 100644
+--- a/indra/newview/llfilepicker.h
++++ b/indra/newview/llfilepicker.h
+@@ -90,6 +90,8 @@ public:
+ 		FFLOAD_XML = 6,
+ 		FFLOAD_SLOBJECT = 7,
+ 		FFLOAD_RAW = 8,
++		FFLOAD_TEXT = 9,
++
+ 	};
+ 
+ 	enum ESaveFilter
+@@ -109,6 +111,7 @@ public:
+ 		FFSAVE_J2C = 12,
+ 		FFSAVE_PNG = 13,
+ 		FFSAVE_JPEG = 14,
++		FFSAVE_TEXT = 15,
+ 	};
+ 
+ 	// open the dialog. This is a modal operation
+diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
+index af52a4b..a12369b 100644
+--- a/indra/newview/llpreviewscript.cpp
++++ b/indra/newview/llpreviewscript.cpp
+@@ -436,6 +436,14 @@ void LLScriptEdCore::initMenu()
+ 	menuItem->setMenuCallback(onBtnHelp, this);
+ 	menuItem->setEnabledCallback(NULL);
+ 
++	menuItem = getChild<LLMenuItemCallGL>("Load from Disc");
++	menuItem->setMenuCallback(onBtnLoadFromDisc, this);
++	menuItem->setEnabledCallback(NULL);
++
++	menuItem = getChild<LLMenuItemCallGL>("Save to Disc");
++	menuItem->setMenuCallback(onBtnSaveToDisc, this);
++	menuItem->setEnabledCallback(hasChanged);
++
+ 	menuItem = getChild<LLMenuItemCallGL>("LSL Wiki Help...");
+ 	menuItem->setMenuCallback(onBtnDynamicHelp, this);
+ 	menuItem->setEnabledCallback(NULL);
+@@ -823,6 +831,60 @@ void LLScriptEdCore::onBtnUndoChanges( void* userdata )
+ 	}
+ }
+ 
++void LLScriptEdCore::onBtnSaveToDisc( void* userdata )
++{
++
++	LLViewerStats::getInstance()->incStat( LLViewerStats::ST_LSL_SAVE_COUNT );
++
++   LLScriptEdCore* self = (LLScriptEdCore*) userdata;
++
++   if( self->mSaveCallback )
++   {
++      LLFilePicker& file_picker = LLFilePicker::instance();
++	if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_TEXT ) )
++	{
++		return;
++	}
++	
++		std::string filename = file_picker.getFirstFile();
++      std::string scriptText=self->mEditor->getText();
++	  std::ofstream fout(filename.c_str());
++      fout<<(scriptText);
++      fout.close();
++      self->mSaveCallback( self->mUserdata, FALSE );
++         
++   }
++	
++}
++void LLScriptEdCore::onBtnLoadFromDisc( void* data )
++{
++
++	LLScriptEdCore* self = (LLScriptEdCore*) data;
++	
++	LLFilePicker& file_picker = LLFilePicker::instance();
++	if( !file_picker.getOpenFile( LLFilePicker::FFLOAD_TEXT ) )
++	{
++		return;
++	}
++	
++	std::string filename = file_picker.getFirstFile();
++
++	std::ifstream fin(filename.c_str());
++	
++	std::string line;
++	std::string linetotal;
++	self->mEditor->clear();
++	while (!fin.eof())
++	{ 
++		getline(fin,line);
++		line=line+"\n";
++		self->mEditor->insertText(line);
++
++	}
++	fin.close();
++	
++}
++
+ void LLScriptEdCore::onSearchMenu(void* userdata)
+ {
+ 	LLScriptEdCore* sec = (LLScriptEdCore*)userdata;
+diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
+index 7026482..97e721d 100644
+--- a/indra/newview/llpreviewscript.h
++++ b/indra/newview/llpreviewscript.h
+@@ -95,6 +95,8 @@ public:
+ 	static void		doSave( void* userdata, BOOL close_after_save );
+ 	static void		onBtnSave(void*);
+ 	static void		onBtnUndoChanges(void*);
++	static void		onBtnSaveToDisc(void*);
++	static void		onBtnLoadFromDisc(void*);
+ 	static void		onSearchMenu(void* userdata);
+ 
+ 	static void		onUndoMenu(void* userdata);
+diff --git a/indra/newview/skins/default/xui/en-us/floater_script_ed_panel.xml b/indra/newview/skins/default/xui/en-us/floater_script_ed_panel.xml
+index b83a6df..154cb1c 100644
+--- a/indra/newview/skins/default/xui/en-us/floater_script_ed_panel.xml
++++ b/indra/newview/skins/default/xui/en-us/floater_script_ed_panel.xml
+@@ -35,6 +35,12 @@
+ 			     width="138" />
+ 			<menu_item_call bottom_delta="-58" height="20" label="Revert All Changes" left="0"
+ 			     mouse_opaque="true" name="Revert All Changes" width="138" />
++      <menu_item_separator bottom_delta="-66" height="8" left="0" mouse_opaque="true" name="separator"
++     width="138" />
++      <menu_item_call bottom_delta="-76" height="20" label="Save to Disc" left="0"
++     mouse_opaque="true" name="Save to Disc" width="138" />
++      <menu_item_call bottom_delta="-96" height="20" label="Load from Disc" left="0"
++     mouse_opaque="true" name="Load from Disc" width="138" />
+ 		</menu>
+ 		<menu bottom="665" drop_shadow="true" enabled="true" height="198"
+ 		     left="222" mouse_opaque="false" name="Edit" opaque="true" tear_off="false"
+-- 
+tg: (fd717f3..) topic/features/jira-backported/VWR-11663_Save_Load_scripts (depends on: upstream)
diff --git a/debian/patches/topic/features/jira-backported/VWR-5082_set_bulk_inv_permissions.diff b/debian/patches/topic/features/jira-backported/VWR-5082_set_bulk_inv_permissions.diff
new file mode 100644
index 0000000..3d5f499
--- /dev/null
+++ b/debian/patches/topic/features/jira-backported/VWR-5082_set_bulk_inv_permissions.diff
@@ -0,0 +1,965 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/features/jira-backported/VWR-5082_set_bulk_inv_permissions
+
+This is applied upstream (in a feature branch) and allows multiple object inventory items to have permissions set in one go.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/newview/CMakeLists.txt                       |    1 +
+ indra/newview/llfloaterbulkpermission.cpp          |  594 ++++++++++++++++++++
+ indra/newview/llfloaterbulkpermission.h            |  143 +++++
+ indra/newview/llviewermenu.cpp                     |   12 +
+ .../skins/default/xui/en-us/floater_bulk_perms.xml |  127 +++++
+ .../skins/default/xui/en-us/menu_viewer.xml        |    5 +
+ 6 files changed, 882 insertions(+), 0 deletions(-)
+
+diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
+index 7c49f72..3858064 100644
+--- a/indra/newview/CMakeLists.txt
++++ b/indra/newview/CMakeLists.txt
+@@ -126,6 +126,7 @@ set(viewer_SOURCE_FILES
+     llfloateravatartextures.cpp
+     llfloaterbeacons.cpp
+     llfloaterbuildoptions.cpp
++    llfloaterbulkpermission.cpp
+     llfloaterbump.cpp
+     llfloaterbuycontents.cpp
+     llfloaterbuy.cpp
+diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp
+new file mode 100644
+index 0000000..e66d1af
+--- /dev/null
++++ b/indra/newview/llfloaterbulkpermission.cpp
+@@ -0,0 +1,594 @@
++/** 
++ * @file llfloaterbulkpermissions.cpp
++ * @brief A floater which allows task inventory item's properties to be changed on mass.
++ *
++ * $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://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$
++ */
++
++/* Allow multiple task inventory properties to be set in one go, by Michelle2 Zenovka */
++
++/* TODO
++	
++	* Add in the option to select objects or task inventory
++s
++
++It would be nice to set the permissions on groups of prims as well as task inventory
++
++*/
++
++
++#include "llviewerprecompiledheaders.h"
++#include "llfloaterbulkpermission.h"
++#include "llagent.h"
++#include "llchat.h"
++#include "llviewerwindow.h"
++#include "llviewerobject.h"
++#include "llviewerobjectlist.h"
++#include "llviewerregion.h"
++#include "lscript_rt_interface.h"
++#include "llviewercontrol.h"
++#include "llviewerobject.h"
++#include "llviewerregion.h"
++#include "llresmgr.h"
++#include "llbutton.h"
++#include "lldir.h"
++#include "llfloaterchat.h"
++#include "llviewerstats.h"
++#include "lluictrlfactory.h"
++#include "llselectmgr.h"
++#include "llinventory.h"
++
++
++#include <algorithm>
++#include <functional>
++#include "llcachename.h"
++#include "lldbstrings.h"
++#include "llinventory.h"
++
++#include "llagent.h"
++#include "llbutton.h"
++#include "llcheckboxctrl.h"
++#include "llfloateravatarinfo.h"
++#include "llfloatergroupinfo.h"
++#include "llinventorymodel.h"
++#include "lllineeditor.h"
++#include "llradiogroup.h"
++#include "llresmgr.h"
++#include "roles_constants.h"
++#include "llselectmgr.h"
++#include "lltextbox.h"
++#include "lluiconstants.h"
++#include "llviewerinventory.h"
++#include "llviewerobjectlist.h"
++#include "llviewerregion.h"
++#include "llviewercontrol.h"
++
++#include "lluictrlfactory.h"
++
++
++const char* BULKPERM_QUEUE_TITLE = "Update Progress";
++const char* BULKPERM_START_STRING = "update";
++
++namespace
++{
++	struct BulkQueueObjects : public LLSelectedObjectFunctor
++	{
++		BOOL scripted;
++		BOOL modifiable;
++		LLFloaterBulkPermission* mQueue;
++		BulkQueueObjects(LLFloaterBulkPermission* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {}
++		virtual bool apply(LLViewerObject* obj)
++		{
++			scripted = obj->flagScripted();
++			modifiable = obj->permModify();
++
++			mQueue->addObject(obj->getID());
++			return false;
++			
++		}
++	};
++}
++
++///----------------------------------------------------------------------------
++/// Class LLFloaterBulkPermission
++///----------------------------------------------------------------------------
++
++// static
++LLMap<LLUUID, LLFloaterBulkPermission*> LLFloaterBulkPermission::sInstances;
++
++
++// Default constructor
++LLFloaterBulkPermission::LLFloaterBulkPermission(const std::string& name,
++											 const LLRect& rect,
++											 const char* title,
++											 const char* start_string) :
++	LLFloater(name, rect, title,
++			  RESIZE_YES, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT,
++			  DRAG_ON_TOP, MINIMIZE_YES, CLOSE_YES)
++{
++
++	req_perm_mask=0; // This should match the default state the checkboxes are set to
++	recurse=false;
++
++	LLUICtrlFactory::getInstance()->buildFloater(this,"floater_bulk_perms.xml");
++
++	childSetAction("Apply...",onApplyBtn,this);
++	childSetEnabled("Apply...",TRUE);
++
++	childSetCommitCallback("Modify",&onCommitPermissions, this);
++	childSetCommitCallback("Trans",&onCommitPermissions, this);
++	childSetCommitCallback("Copy",&onCommitPermissions, this);
++
++	//childSetCommitCallback("Recurse",&onRecurse, this);
++
++	childSetCommitCallback("Parent",&onParent, this);
++
++	childSetCommitCallback("objects",&InvSelection, this);
++	childSetCommitCallback("scripts",&InvSelection, this);
++	childSetCommitCallback("textures",&InvSelection, this);
++	childSetCommitCallback("sounds",&InvSelection, this);
++	childSetCommitCallback("animations",&InvSelection, this);
++	childSetCommitCallback("notecards",&InvSelection, this);
++	childSetCommitCallback("landmarks",&InvSelection, this);
++	childSetCommitCallback("bodyparts",&InvSelection, this);
++	childSetCommitCallback("clothing",&InvSelection, this);
++	childSetCommitCallback("gestures",&InvSelection, this);
++
++	//Set variable state to XUI default state consistancy
++	processObject=getChild<LLCheckBoxCtrl>("objects")->get();
++	processScript=getChild<LLCheckBoxCtrl>("scripts")->get();
++	processTexture=getChild<LLCheckBoxCtrl>("textures")->get();
++	processSound=getChild<LLCheckBoxCtrl>("sounds")->get();
++	processAnimation=getChild<LLCheckBoxCtrl>("animations")->get();
++	processNotecard=getChild<LLCheckBoxCtrl>("notecards")->get();
++	processGesture=getChild<LLCheckBoxCtrl>("gestures")->get();
++	processClothing=getChild<LLCheckBoxCtrl>("clothing")->get();
++	processBodypart=getChild<LLCheckBoxCtrl>("bodyparts")->get();
++	processLandmark=getChild<LLCheckBoxCtrl>("landmarks")->get();
++	parent=getChild<LLCheckBoxCtrl>("Parent")->get();
++
++
++	setTitle(title);
++	
++	if (!getHost())
++	{
++		LLRect curRect = getRect();
++		translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
++	}
++	
++	mStartString = start_string;
++	mDone = FALSE;
++	sInstances.addData(mID, this);
++
++}
++
++void LLFloaterBulkPermission::doApply()
++{
++	// Its alive now do the nasty work that the ScriptQueue and friends try to do in the menu code
++	// but first grab the user options
++
++	LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
++	list->deleteAllItems();
++
++	//Apply to selected objects if requested first
++
++	if(parent)
++	{
++		llinfos<< "Setting permission on parent items" << llendl;
++		LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_NEXT_OWNER,true, req_perm_mask);
++		LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_NEXT_OWNER,false, ~req_perm_mask); //How annoying need to set and unset
++	}
++
++
++	LLFloaterBulkPermission* q;
++	q=(LLFloaterBulkPermission*)this;
++
++	BulkQueueObjects func(q);
++	bool fail = LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func);
++	if(fail)
++	{
++		if ( !func.modifiable )
++		{
++			gViewerWindow->alertXml("NO MODIFY");
++		}
++		else
++		{
++			llwarns << "Bad logic. Are there actualy any items in that prim?" << llendl;
++		}
++	}
++	else
++	{
++		if (!q->start())
++		{
++			llwarns << "Unexpected failure attepmting to set permissions." << llendl;
++		}
++	}
++}
++
++// Destroys the object
++LLFloaterBulkPermission::~LLFloaterBulkPermission()
++{
++	sInstances.removeData(mID);
++}
++
++// find an instance by ID. Return NULL if it does not exist.
++// static
++LLFloaterBulkPermission* LLFloaterBulkPermission::findInstance(const LLUUID& id)
++{
++	if(sInstances.checkData(id))
++	{
++		return sInstances.getData(id);
++	}
++	return NULL;
++}
++
++
++// This is the callback method for the viewer object currently being
++// worked on.
++// NOT static, virtual!
++void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object,
++											 InventoryObjectList* inv,
++											 S32,
++											 void* q_id)
++{
++	llinfos << "LLFloaterBulkPermission::inventoryChanged() for  object "
++			<< viewer_object->getID() << llendl;
++
++	//Remove this listener from the object since its
++	//listener callback is now being executed.
++	
++	//We remove the listener here because the function
++	//removeVOInventoryListener removes the listener from a ViewerObject
++	//which it internally stores.
++	
++	//If we call this further down in the function, calls to handleInventory
++	//and nextObject may update the interally stored viewer object causing
++	//the removal of the incorrect listener from an incorrect object.
++	
++	//Fixes SL-6119:Recompile scripts fails to complete
++	removeVOInventoryListener();
++
++	if (viewer_object && inv && (viewer_object->getID() == mCurrentObjectID) )
++	{
++		handleInventory(viewer_object, inv);
++	}
++	else
++	{
++		// something went wrong...
++		// note that we're not working on this one, and move onto the
++		// next object in the list.
++		llwarns << "No inventory for " << mCurrentObjectID
++				<< llendl;
++		nextObject();
++	}
++}
++
++void LLFloaterBulkPermission::onApplyBtn(void* user_data)
++{
++	LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)user_data;
++	self->doApply();
++}
++
++
++// static
++void LLFloaterBulkPermission::InvSelection(LLUICtrl* ctrl, void* data)
++{
++	LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
++
++	self->processObject=self->getChild<LLCheckBoxCtrl>("objects")->get();
++	self->processScript=self->getChild<LLCheckBoxCtrl>("scripts")->get();
++	self->processTexture=self->getChild<LLCheckBoxCtrl>("textures")->get();
++	self->processSound=self->getChild<LLCheckBoxCtrl>("sounds")->get();
++	self->processAnimation=self->getChild<LLCheckBoxCtrl>("animations")->get();
++	self->processNotecard=self->getChild<LLCheckBoxCtrl>("notecards")->get();
++	self->processGesture=self->getChild<LLCheckBoxCtrl>("gestures")->get();
++	self->processClothing=self->getChild<LLCheckBoxCtrl>("clothing")->get();
++	self->processBodypart=self->getChild<LLCheckBoxCtrl>("bodyparts")->get();
++	self->processLandmark=self->getChild<LLCheckBoxCtrl>("landmarks")->get();
++
++
++}
++
++// static
++void LLFloaterBulkPermission::onParent(LLUICtrl* ctrl, void* data)
++{
++	LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
++	self->parent=self->getChild<LLCheckBoxCtrl>("Parent")->get();
++}
++
++// static
++void LLFloaterBulkPermission::onRecurse(LLUICtrl* ctrl, void* data)
++{
++	LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
++	self->recurse=self->getChild<LLCheckBoxCtrl>("Recurse")->get();
++}
++
++// static
++void LLFloaterBulkPermission::onCommitPermissions(LLUICtrl* ctrl, void* data)
++{
++	LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
++	LLCheckBoxCtrl* CheckModify = self->getChild<LLCheckBoxCtrl>("Modify");
++	LLCheckBoxCtrl* CheckCopy = self->getChild<LLCheckBoxCtrl>("Copy");
++	LLCheckBoxCtrl* CheckTrans = self->getChild<LLCheckBoxCtrl>("Trans");
++
++	self->req_perm_mask=0;
++
++	if(CheckModify->get())
++	{
++		self->req_perm_mask|=PERM_MODIFY;
++	}
++	else
++	{
++		self->req_perm_mask&=~PERM_MODIFY;
++	}
++
++	if(CheckCopy->get())
++	{
++		self->req_perm_mask|=PERM_COPY;
++	}
++	else
++	{
++		self->req_perm_mask&=~PERM_COPY;
++	}
++
++	if(CheckTrans->get())
++	{
++		self->req_perm_mask|=PERM_TRANSFER;
++	}
++	else
++	{
++		self->req_perm_mask&=~PERM_TRANSFER;
++	}
++
++
++}
++
++void LLFloaterBulkPermission::addObject(const LLUUID& id)
++{
++	mObjectIDs.put(id);
++}
++
++BOOL LLFloaterBulkPermission::start()
++{
++	llinfos << "LLFloaterBulkPermission::start()" << llendl;
++	char buffer[MAX_STRING]; 				/*Flawfinder: ignore*/
++	snprintf(buffer, sizeof(buffer), "Starting %s of %d items.", mStartString, mObjectIDs.count()); 		/* Flawfinder: ignore */
++
++	LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
++	list->addCommentText(buffer);
++
++	return nextObject();
++}
++
++BOOL LLFloaterBulkPermission::isDone() const
++{
++	return (mCurrentObjectID.isNull() || (mObjectIDs.count() == 0));
++}
++
++// go to the next object. If no objects left, it falls out silently
++// and waits to be killed by the window being closed.
++BOOL LLFloaterBulkPermission::nextObject()
++{
++	S32 count;
++	BOOL successful_start = FALSE;
++	do
++	{
++		count = mObjectIDs.count();
++		llinfos << "LLFloaterBulkPermission::nextObject() - " << count
++				<< " objects left to process." << llendl;
++		mCurrentObjectID.setNull();
++		if(count > 0)
++		{
++			successful_start = popNext();
++		}
++		llinfos << "LLFloaterBulkPermission::nextObject() "
++				<< (successful_start ? "successful" : "unsuccessful")
++				<< llendl; 
++	} while((mObjectIDs.count() > 0) && !successful_start);
++
++	if(isDone() && !mDone)
++	{
++		
++		LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
++		mDone = TRUE;
++		char buffer[MAX_STRING];		/*Flawfinder: ignore*/
++		snprintf(buffer, sizeof(buffer), "Done.");				/* Flawfinder: ignore */
++		list->addCommentText(buffer);
++
++	}
++	return successful_start;
++}
++
++// returns true if the queue has started, otherwise false.  This
++// method pops the top object off of the queue.
++BOOL LLFloaterBulkPermission::popNext()
++{
++	// get the first element off of the container, and attempt to get
++	// the inventory.
++	BOOL rv = FALSE;
++	S32 count = mObjectIDs.count();
++	if(mCurrentObjectID.isNull() && (count > 0))
++	{
++		mCurrentObjectID = mObjectIDs.get(0);
++		llinfos << "LLFloaterBulkPermission::popNext() - mCurrentID: "
++				<< mCurrentObjectID << llendl;
++		mObjectIDs.remove(0);
++		LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID);
++		if(obj)
++		{
++			llinfos << "LLFloaterBulkPermission::popNext() requesting inv for "
++					<< mCurrentObjectID << llendl;
++			LLUUID* id = new LLUUID(mID);
++
++			registerVOInventoryListener(obj,id);
++			requestVOInventory();
++			rv = TRUE;
++		}
++		else
++		{
++			llinfos<<"LLFloaterBulkPermission::popNext() returned a NULL LLViewerObject" <<llendl;
++			//Arrrg what do we do here?
++		}
++	}
++
++	return rv;
++}
++
++
++// static
++LLFloaterBulkPermission* LLFloaterBulkPermission::create()
++{
++	S32 left, top;
++	gFloaterView->getNewFloaterPosition(&left, &top);
++	LLRect rect = gSavedSettings.getRect("CompileOutputRect");
++	rect.translate(left - rect.mLeft, top - rect.mTop);
++	LLFloaterBulkPermission* new_queue = new LLFloaterBulkPermission("queue",rect,"Setting Bulk permissions","Results");
++	new_queue->open();	 /*Flawfinder: ignore*/
++	return new_queue;
++}
++
++
++void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, InventoryObjectList* inv)
++{
++	// find all of the lsl, leaving off duplicates. We'll remove
++	// all matching asset uuids on compilation success.
++
++	llinfos<<"handleInventory"<<llendl;
++
++	char buffer[MAX_STRING];		 /*Flawfinder: ignore*/
++	LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
++
++	InventoryObjectList::const_iterator it = inv->begin();
++	InventoryObjectList::const_iterator end = inv->end();
++	for ( ; it != end; ++it)
++	{
++		llinfos<<"Doing iterator of inventory"<<llendl;
++
++		if(  ( (*it)->getType() == LLAssetType::AT_LSL_TEXT && processScript) ||
++  		     ( (*it)->getType() == LLAssetType::AT_TEXTURE && processTexture) ||
++	             ( (*it)->getType() == LLAssetType::AT_SOUND && processSound) ||
++	             ( (*it)->getType() == LLAssetType::AT_LANDMARK && processLandmark) ||
++    		     ( (*it)->getType() == LLAssetType::AT_CLOTHING && processClothing) ||
++    		     ( (*it)->getType() == LLAssetType::AT_OBJECT && processObject) ||
++   		     ( (*it)->getType() == LLAssetType::AT_NOTECARD && processNotecard) ||
++   		     ( (*it)->getType() == LLAssetType::AT_BODYPART && processBodypart) ||
++   		     ( (*it)->getType() == LLAssetType::AT_ANIMATION && processAnimation) ||
++   		     ( (*it)->getType() == LLAssetType::AT_GESTURE && processGesture))
++		{
++
++			LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
++
++			if (object)
++			{
++				LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
++				LLViewerInventoryItem* new_item = (LLViewerInventoryItem*)item;
++				LLPermissions perm(new_item->getPermissions());
++
++				// chomp the inventory name so it fits in the scroll window nicely
++				// and the user can see the [OK]
++				std::string invname;
++				invname=item->getName().substr(0,item->getName().size() < 30 ? item->getName().size() : 30 );
++				
++				// My attempt at checking valid permissions, CHECK ME
++				// note its not actually bad to try to set permissions that are not allowed as the
++				// server will protect against this, but it will piss the user off if its wrong
++				if(
++				(perm.getCreator()==gAgentID) ||
++				(perm.getMaskOwner() & PERM_TRANSFER) && (perm.getMaskOwner() & PERM_MODIFY) || 
++				(gAgent.getGroupID()==perm.getGroup() && (perm.getMaskGroup() & PERM_TRANSFER) && (perm.getMaskGroup() & PERM_MODIFY))
++				){	
++					llinfos<<"Setting perms"<<llendl;
++					perm.setMaskNext(req_perm_mask);
++					new_item->setPermissions(perm);
++					updateInventory(object,new_item,TASK_INVENTORY_ITEM_KEY,FALSE);				
++					snprintf(buffer, sizeof(buffer), "Setting perms on '%s' [OK]", invname.c_str());		 	/* Flawfinder: ignore */
++				}
++				else
++				{
++					llinfos<<"NOT setting perms"<<llendl;
++					snprintf(buffer, sizeof(buffer), "Setting perms on '%s' [FAILED]", invname.c_str());		 	/* Flawfinder: ignore */
++
++				}
++				
++				list->addCommentText(buffer);
++
++				if(recurse &&  ( (*it)->getType() == LLAssetType::AT_OBJECT && processObject))
++				{
++					//Add this object back to the queue to be processed as it has inventory
++					snprintf(buffer, sizeof(buffer), "Queueing object '%s' for open", invname.c_str());
++					llwarns << "Queueing object "<<	invname.c_str() << " ID "<< (*it)->getUUID()<<llendl;
++					mObjectIDs.put((*it)->getUUID());
++					// This will not YET work. as this is not a viewer object the unpack will fail			
++				}
++
++			}
++		}
++	}
++
++	nextObject();	
++}
++
++
++// Avoid inventory callbacks etc by just fire and forgetting the message with the permissions update
++// we could do this via LLViewerObject::updateInventory but that uses inventory call backs and buggers
++// us up and we would have a dodgy item iterator
++
++void LLFloaterBulkPermission::updateInventory(
++	LLViewerObject* object,
++	LLViewerInventoryItem* item,
++	U8 key,
++	bool is_new)
++{
++	LLMemType mt(LLMemType::MTYPE_OBJECT);
++	
++
++	// This slices the object into what we're concerned about on the
++	// viewer. The simulator will take the permissions and transfer
++	// ownership.
++	LLPointer<LLViewerInventoryItem> task_item =
++		new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
++								  item->getAssetUUID(), item->getType(),
++								  item->getInventoryType(),
++								  item->getName(), item->getDescription(),
++								  item->getSaleInfo(),
++								  item->getFlags(),
++								  item->getCreationDate());
++	task_item->setTransactionID(item->getTransactionID());
++	LLMessageSystem* msg = gMessageSystem;
++	msg->newMessageFast(_PREHASH_UpdateTaskInventory);
++	msg->nextBlockFast(_PREHASH_AgentData);
++	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
++	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
++	msg->nextBlockFast(_PREHASH_UpdateData);
++	msg->addU32Fast(_PREHASH_LocalID, object->mLocalID);
++	msg->addU8Fast(_PREHASH_Key, key);
++	msg->nextBlockFast(_PREHASH_InventoryData);
++	task_item->packMessage(msg);
++	msg->sendReliable(object->getRegion()->getHost());
++
++}
++
+diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h
+new file mode 100644
+index 0000000..3de871b
+--- /dev/null
++++ b/indra/newview/llfloaterbulkpermission.h
+@@ -0,0 +1,143 @@
++/** 
++ * @file llfloaterbulkpermissions.h
++ * @brief A floater which allows task inventory item's properties to be changed on mass.
++ *
++ * $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://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$
++ */
++
++/* Allow multiple task inventory properties to be set in one go, by Michelle2 Zenovka */
++
++#ifndef LL_LLBULKPERMISSION_H
++#define LL_LLBULKPERMISSION_H
++
++#include "lldarray.h"
++#include "llinventory.h"
++#include "llviewerobject.h"
++#include "llvoinventorylistener.h"
++#include "llmap.h"
++#include "lluuid.h"
++
++#include "llfloater.h"
++#include "llscrolllistctrl.h"
++
++#include "llviewerinventory.h"
++
++class LLFloaterBulkPermission : public LLFloater, public LLVOInventoryListener
++{
++public:
++	// addObject() accepts an object id.
++	void addObject(const LLUUID& id);
++
++	// start() returns TRUE if the queue has started, otherwise FALSE.
++	BOOL start();
++
++	// Use this method to create a reset queue. Once created, it
++	// will be responsible for it's own destruction.
++	static LLFloaterBulkPermission * create();
++
++protected:
++	LLFloaterBulkPermission(const std::string& name, const LLRect& rect,
++						 const char* title, const char* start_string);
++	virtual ~LLFloaterBulkPermission();
++
++	// This is the callback method for the viewer object currently
++	// being worked on.
++	/*virtual*/ void inventoryChanged(LLViewerObject* obj,
++								 InventoryObjectList* inv,
++								 S32 serial_num,
++								 void* queue);
++	
++	// This is called by inventoryChanged
++	void handleInventory(LLViewerObject* viewer_obj,
++								InventoryObjectList* inv);
++
++
++	void updateInventory(LLViewerObject* object,
++								LLViewerInventoryItem* item,
++								U8 key,
++								bool is_new);
++
++
++	static void onCloseBtn(void* user_data);
++	static void onApplyBtn(void* user_data);
++	static void onCommitPermissions(LLUICtrl* ctrl, void* data);
++	static void InvSelection(LLUICtrl* ctrl, void* data);
++	static void onRecurse(LLUICtrl* ctrl, void* data);	
++	static void onParent(LLUICtrl* ctrl, void* data);
++
++	// returns true if this is done
++	BOOL isDone() const;
++
++	//Read the settings and Apply the permissions
++	void doApply();
++
++	// go to the next object. If no objects left, it falls out
++	// silently and waits to be killed by the deleteIfDone() callback.
++	BOOL nextObject();
++	BOOL popNext();
++
++	// Get this instances ID.
++	const LLUUID& getID() const { return mID; } 
++
++	// find an instance by ID. Return NULL if it does not exist.
++	static LLFloaterBulkPermission* findInstance(const LLUUID& id);
++
++	U32 req_perm_mask;
++
++	BOOL processObject;
++	BOOL processScript;
++	BOOL processTexture;
++	BOOL processSound;
++	BOOL processAnimation;
++	BOOL processCallingcard;
++	BOOL processNotecard;
++	BOOL processGesture;
++	BOOL processClothing;
++	BOOL processBodypart;
++	BOOL processLandmark;
++
++	BOOL recurse;
++	BOOL parent;
++
++protected:
++	// UI
++	LLScrollListCtrl* mMessages;
++	LLButton* mCloseBtn;
++
++	// Object Queue
++	LLDynamicArray<LLUUID> mObjectIDs;
++	LLUUID mCurrentObjectID;
++	BOOL mDone;
++
++	LLUUID mID;
++	static LLMap<LLUUID, LLFloaterBulkPermission*> sInstances;
++
++	const char* mStartString;
++
++};
++
++#endif
+diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
+index 2d64712..81a0e31 100644
+--- a/indra/newview/llviewermenu.cpp
++++ b/indra/newview/llviewermenu.cpp
+@@ -87,6 +87,7 @@
+ #include "llfloateravatartextures.h"
+ #include "llfloaterbeacons.h"
+ #include "llfloaterbuildoptions.h"
++#include "llfloaterbulkpermission.h"
+ #include "llfloaterbump.h"
+ #include "llfloaterbuy.h"
+ #include "llfloaterbuycontents.h"
+@@ -6022,6 +6023,16 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& noscriptmsg, cons
+ 	}
+ }
+ 
++class LLToolsSetBulkPerms : public view_listener_t
++{
++	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
++	{
++		LLFloaterBulkPermission* queue = NULL;
++		queue = LLFloaterBulkPermission::create();
++		return true;
++	}
++};
++
+ void handle_compile_queue(std::string to_lang)
+ {
+ 	LLFloaterCompileQueue* queue;
+@@ -7509,6 +7520,7 @@ void initialize_menus()
+ 	addMenu(new LLToolsSaveToInventory(), "Tools.SaveToInventory");
+ 	addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory");
+ 	addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction");
++	addMenu(new LLToolsSetBulkPerms(), "Tools.SetBulkPerms");
+ 
+ 	addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie");
+ 	addMenu(new LLToolsEnableLink(), "Tools.EnableLink");
+diff --git a/indra/newview/skins/default/xui/en-us/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en-us/floater_bulk_perms.xml
+new file mode 100644
+index 0000000..3dd838a
+--- /dev/null
++++ b/indra/newview/skins/default/xui/en-us/floater_bulk_perms.xml
+@@ -0,0 +1,127 @@
++<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
++<floater bottom="-554" can_close="true" can_drag_on_left="false" can_minimize="true"
++     can_resize="false" can_tear_off="false" enabled="true" height="420"
++     left="367" min_height="1000" min_width="460" mouse_opaque="true"
++     name="floaterrecursiveperms" title="Bulk permission settings"
++     width="460">
++
++<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++			     bottom="-40" drop_shadow_visible="true" enabled="true" follows="left|top"
++			     font="SansSerifSmall" h_pad="0" halign="left" height="10" left="10"
++			     mouse_opaque="true" name="applyto" v_pad="0" width="206">Apply to</text>
++
++<check_box bottom="-70" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Scripts" left="10" mouse_opaque="true"
++			     name="scripts" radio_style="false"
++			     tool_tip="Apply bulk permissions to scripts"
++			     width="219"/>
++
++<check_box bottom="-90" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Textures" left="10" mouse_opaque="true"
++			     name="textures" radio_style="false"
++			     tool_tip="Apply bulk permissions to textures"
++			     width="219"/>
++
++<check_box bottom="-110" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Animations" left="10" mouse_opaque="true"
++			     name="animations" radio_style="false"
++			     tool_tip="Apply bulk permissions to animations"
++			     width="219"/>
++
++<check_box bottom="-130" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Sounds" left="10" mouse_opaque="true"
++			     name="sounds" radio_style="false"
++			     tool_tip="Apply bulk permissions to sounds"
++			     width="219"/>
++
++<check_box bottom="-150" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Contained objects" left="10" mouse_opaque="true"
++			     name="objects" radio_style="false"
++			     tool_tip="Apply bulk permissions to objects inside inventory"
++			     width="219"/>
++
++<check_box bottom="-170" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Landmarks" left="10" mouse_opaque="true"
++			     name="landmarks" radio_style="false"
++			     tool_tip="Apply bulk permissions to landmarks"
++			     width="219"/>
++
++<check_box bottom="-190" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Notecards" left="10" mouse_opaque="true"
++			     name="notecards" radio_style="false"
++			     tool_tip="Apply bulk permissions to notecards"
++			     width="219"/>
++
++<check_box bottom="-210" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Gesture" left="10" mouse_opaque="true"
++			     name="gestures" radio_style="false"
++			     tool_tip="Apply bulk permissions to gestures"
++			     width="219"/>
++
++<check_box bottom="-230" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Clothing" left="10" mouse_opaque="true"
++			     name="clothing" radio_style="false"
++			     tool_tip="Apply bulk permissions to clothing"
++			     width="219"/>
++
++<check_box bottom="-250" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Bodypart" left="10" mouse_opaque="true"
++			     name="bodyparts" radio_style="false"
++			     tool_tip="Apply bulk permissions to bodyparts"
++			     width="219"/>
++
++<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++			     bottom="-40" drop_shadow_visible="true" enabled="true" follows="left|top"
++			     font="SansSerifSmall" h_pad="0" halign="left" height="10" left="200"
++			     mouse_opaque="true" name="applyto" v_pad="0" width="206">Permissions</text>
++
++
++<check_box bottom="-110" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Copy" left="200" mouse_opaque="true"
++			     name="Copy" radio_style="false"
++			     tool_tip="Next owner can copy"
++			     width="219"/>
++
++<check_box bottom="-130" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Modify" left="200" mouse_opaque="true"
++			     name="Modify" radio_style="false"
++			     tool_tip="Next owner can modify"
++			     width="219"/>
++
++<check_box bottom="-150" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Trans" left="200" mouse_opaque="true"
++			     name="Trans" radio_style="false"
++			     tool_tip="Next owner can transfer"
++			     width="219"/>
++
++<check_box bottom="-230" enabled="true" follows="left|top" font="SansSerifSmall"
++			     height="16" initial_value="false"
++			     label="Modify Parent Prims" left="200" mouse_opaque="true"
++			     name="Parent" radio_style="false"
++			     tool_tip="Modify parent prims not just inventory"
++			     width="219" default="true"/>
++
++<scroll_list background_visible="true" bottom="-410" column_padding="5" draw_border="true"
++	     draw_heading="false" draw_stripes="true" enabled="true"
++	     follows="left|top|right|bottom" height="140" left="10" mouse_opaque="true"
++	     multi_select="false" name="queue output" width="440" />
++
++<button bottom="-70" enabled="true" follows="left|top" font="SansSerif"
++			     halign="center" height="20" label="Apply..."
++			     label_selected="Apply..." left="295" mouse_opaque="true"
++			     name="Apply..." scale_image="true" width="145" />
++
++</floater>
+diff --git a/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/indra/newview/skins/default/xui/en-us/menu_viewer.xml
+index d2c4923..8b57505 100644
+--- a/indra/newview/skins/default/xui/en-us/menu_viewer.xml
++++ b/indra/newview/skins/default/xui/en-us/menu_viewer.xml
+@@ -704,6 +704,11 @@
+ 			<on_click function="Tools.SelectedScriptAction" userdata="stop" />
+ 			<on_enable function="EditableSelected" />
+ 		</menu_item_call>
++		<menu_item_call bottom="-468" enabled="false" height="19" label="Set permissions on selected task inventory"
++		     left="0" mouse_opaque="true" name="Set permissions on selected task inventory" width="250">
++			<on_click function="Tools.SetBulkPerms" userdata="" />
++			<on_enable function="EditableSelected" />
++		</menu_item_call>
+ 	</menu>
+ 	<menu bottom="219" create_jump_keys="true" drop_shadow="true" enabled="true"
+ 	     height="317" label="Help" left="227" mouse_opaque="false" name="Help"
+-- 
+tg: (fd717f3..) topic/features/jira-backported/VWR-5082_set_bulk_inv_permissions (depends on: upstream)
diff --git a/debian/patches/topic/features/jira-backported/avatar_list.diff b/debian/patches/topic/features/jira-backported/avatar_list.diff
new file mode 100644
index 0000000..44797a6
--- /dev/null
+++ b/debian/patches/topic/features/jira-backported/avatar_list.diff
@@ -0,0 +1,5211 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/features/jira-backported/avatar_list
+
+Dale Glass's avatar scanner as published on JIRA and rebased by Carjay
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llaudio/audioengine.h                        |    1 +
+ indra/llmessage/llmessagetemplate.h                |  111 +-
+ indra/llmessage/message.cpp                        |   28 +-
+ indra/llmessage/message.h                          |   18 +-
+ indra/llui/llscrolllistctrl.cpp                    |   41 +
+ indra/llui/llscrolllistctrl.h                      |    2 +
+ indra/newview/CMakeLists.txt                       |    3 +
+ indra/newview/app_settings/settings.xml            |   16 +
+ indra/newview/llagent.cpp                          |  121 +-
+ indra/newview/llagent.h                            |   14 +
+ indra/newview/llappviewer.cpp                      |    4 +
+ indra/newview/llchatbar.cpp                        |   34 +-
+ indra/newview/llfloateravatarlist.cpp              | 2187 ++++++++++++++++++++
+ indra/newview/llfloateravatarlist.h                |  868 ++++++++
+ indra/newview/llfloaterpreference.cpp              |    7 +
+ indra/newview/llfloaterpreference.h                |    2 +
+ indra/newview/llfloaterreporter.cpp                |   13 +-
+ indra/newview/llfloaterreporter.h                  |    2 +-
+ indra/newview/llpaneldatabase.cpp                  |  149 ++
+ indra/newview/llpaneldatabase.h                    |   65 +
+ indra/newview/llstartup.cpp                        |    2 +-
+ indra/newview/lltoolbar.cpp                        |    9 +
+ indra/newview/lltoolbar.h                          |    1 +
+ indra/newview/llviewermenu.cpp                     |   14 +
+ indra/newview/llviewermessage.cpp                  |    3 +
+ indra/newview/llviewerobject.h                     |    3 +-
+ indra/newview/llviewerwindow.cpp                   |    8 +-
+ indra/newview/llwebbrowserctrl.h                   |    2 +
+ indra/newview/pipeline.cpp                         |   42 +
+ indra/newview/skins/default/xui/en-us/alerts.xml   |  135 ++
+ .../default/xui/en-us/floater_avatar_scanner.xml   |  413 ++++
+ .../skins/default/xui/en-us/menu_viewer.xml        |   13 +
+ indra/newview/skins/default/xui/en-us/notify.xml   |    6 +
+ .../xui/en-us/panel_preferences_database.xml       |  166 ++
+ .../skins/default/xui/en-us/panel_toolbar.xml      |    7 +
+ 35 files changed, 4447 insertions(+), 63 deletions(-)
+
+diff --git a/indra/llaudio/audioengine.h b/indra/llaudio/audioengine.h
+index 0bd6327..da3a463 100644
+--- a/indra/llaudio/audioengine.h
++++ b/indra/llaudio/audioengine.h
+@@ -311,6 +311,7 @@ public:
+ 	BOOL setupChannel();
+ 	BOOL play(const LLUUID &audio_id);	// Start the audio source playing
+ 
++	const LLUUID &getOwnerID()		{ return mOwnerID; }
+ 	BOOL hasPendingPreloads() const;	// Has preloads that haven't been done yet
+ 
+ 	friend class LLAudioEngine;
+diff --git a/indra/llmessage/llmessagetemplate.h b/indra/llmessage/llmessagetemplate.h
+index 2390eea..6638a75 100644
+--- a/indra/llmessage/llmessagetemplate.h
++++ b/indra/llmessage/llmessagetemplate.h
+@@ -35,7 +35,11 @@
+ #include "lldarray.h"
+ #include "message.h" // TODO: babbage: Remove...
+ #include "llstat.h"
++#include "llmsgvariabletype.h"
+ #include "llstl.h"
++#include <list>
++#include <algorithm>
++#include <functional>
+ 
+ class LLMsgVarData
+ {
+@@ -270,6 +274,30 @@ enum EMsgDeprecation
+ 	MD_DEPRECATED
+ };
+ 
++class LLMessageTemplateHandlerEntry
++{
++public:
++	LLMessageTemplateHandlerEntry(message_handler_func_t handler, void **userdata = NULL) :
++		mHandlerFunc(handler), mUserData(userdata) {}
++
++	void call(LLMessageSystem *msgsystem) const { mHandlerFunc(msgsystem, mUserData); }
++
++	bool operator==(const LLMessageTemplateHandlerEntry&a) { return mHandlerFunc == a.mHandlerFunc; }
++private:
++	// message handler function (this is set by each application)
++	message_handler_func_t mHandlerFunc;
++	void **mUserData;	
++};
++
++class callHandler : public std::unary_function<LLMessageTemplateHandlerEntry, void>
++{
++public:
++	callHandler(LLMessageSystem *msg) : mMsg(msg) {}
++	void operator()(const LLMessageTemplateHandlerEntry& a) const { a.call(mMsg); }
++private:
++	LLMessageSystem *mMsg;
++};
++
+ class LLMessageTemplate
+ {
+ public:
+@@ -291,9 +319,7 @@ public:
+ 		mTotalDecodeTime(0.f),
+ 		mMaxDecodeTimePerMsg(0.f),
+ 		mBanFromTrusted(false),
+-		mBanFromUntrusted(false),
+-		mHandlerFunc(NULL), 
+-		mUserData(NULL)
++		mBanFromUntrusted(false)
+ 	{ 
+ 		mName = LLMessageStringTable::getInstance()->getString(name);
+ 	}
+@@ -361,21 +387,84 @@ public:
+ 		return mDeprecation;
+ 	}
+ 	
+-	void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
++	/**
++	 * @brief Adds a handler
++	 * This function adds a new handler to be called when the message arrives.
++	 * Repeated additions of the same handler function will be ignored.
++	 * @note delHandlerFunc() must be called to remove the registration
++	 * @param handler Function to call
++	 * @param user_data User specified data to pass to the function
++	 */
++	void addHandlerFunc(message_handler_func_t handler, void **user_data)	
++	{
++		LLMessageTemplateHandlerEntry h(handler, user_data);
++
++		if ( std::find(mHandlers.begin(), mHandlers.end(), h ) != mHandlers.end() )
++		{
++			return;
++		}
++
++		mHandlers.push_back( h );
++	}
++
++	/**
++	 * @brief Sets a handler
++	 * This function sets a handler to be called when the message arrives.
++	 * Any existing handlers are unregistered.
++	 * @note delHandlerFunc() must be called to remove the registration
++	 * @param handler Function to call
++	 * @param user_data User specified data to pass to the function
++	 */
++	void setHandlerFunc(message_handler_func_t handler, void **user_data)
++	{
++		mHandlers.clear();
++		if( handler )
++		{
++			addHandlerFunc(handler, user_data);
++		}
++		else
++		{
++			llwarns << "code has reset handler for \"" << mName << "\" by setting it to NULL." << llendl;
++		}
++	}
++
++	/**
++	 * @brief Removes a handler
++	 * Removes a handler from the list of handlers.
++	 * Attempts to remove handlers that aren't in the list are silently
++	 * ignored.
++	 * @param handler Function to remove
++	 */
++	void delHandlerFunc(message_handler_func_t handler)
+ 	{
+-		mHandlerFunc = handler_func;
+-		mUserData = user_data;
++		mHandlers.remove( LLMessageTemplateHandlerEntry(handler) );
+ 	}
+ 
+ 	BOOL callHandlerFunc(LLMessageSystem *msgsystem) const
+ 	{
+-		if (mHandlerFunc)
++		if ( mHandlers.empty() )
++		{
++			return FALSE;
++		}
++		/* 
++		 * Be on the safe side and use for_each only when necessary. There is Linden code ("ReplyPayPrice") that
++		 * does not take the multiple reply handlers into account and simply tries to unregister
++		 * by setting the handler function to 0, unfortunately from within the reply handler so in this case
++		 * the for_each iterator inside std_algo.h is invalidated leading to a crash if the memory is reused
++		 * in between.
++		 */
++		else if( mHandlers.size() == 1 )
+ 		{
+             LLPerfBlock msg_cb_time("msg_cb", mName);
+-			mHandlerFunc(msgsystem, mUserData);
++			mHandlers.begin()->call(msgsystem);
++			return TRUE;
++		}
++		else
++		{
++            LLPerfBlock msg_cb_time("msg_cb", mName);
++			std::for_each(mHandlers.begin(), mHandlers.end(), callHandler(msgsystem));
+ 			return TRUE;
+ 		}
+-		return FALSE;
+ 	}
+ 
+ 	bool isUdpBanned() const
+@@ -420,9 +509,7 @@ public:
+ 	bool									mBanFromUntrusted;
+ 
+ private:
+-	// message handler function (this is set by each application)
+-	void									(*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
+-	void									**mUserData;
++	std::list<LLMessageTemplateHandlerEntry> mHandlers;
+ };
+ 
+ #endif // LL_LLMESSAGETEMPLATE_H
+diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
+index ccc3d79..30d7676 100644
+--- a/indra/llmessage/message.cpp
++++ b/indra/llmessage/message.cpp
+@@ -2972,7 +2972,7 @@ void LLMessageSystem::addTemplate(LLMessageTemplate *templatep)
+ }
+ 
+ 
+-void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
++void LLMessageSystem::setHandlerFuncFast(const char *name, message_handler_func_t handler_func, void **user_data)
+ {
+ 	LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
+ 	if (msgtemplate)
+@@ -2985,6 +2985,32 @@ void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(
+ 	}
+ }
+ 
++void LLMessageSystem::addHandlerFuncFast(const char *name, message_handler_func_t handler_func, void **user_data)
++{
++	LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
++	if (msgtemplate)
++	{
++		msgtemplate->addHandlerFunc(handler_func, user_data);
++	}
++	else
++	{
++		llerrs << name << " is not a known message name!" << llendl;
++	}
++}
++
++void LLMessageSystem::delHandlerFuncFast(const char *name, message_handler_func_t handler_func)
++{
++	LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
++	if (msgtemplate)
++	{
++		msgtemplate->delHandlerFunc(handler_func);
++	}
++	else
++	{
++		llerrs << name << " is not a known message name!" << llendl;
++	}
++}
++
+ bool LLMessageSystem::callHandler(const char *name,
+ 		bool trustedSource, LLMessageSystem* msg)
+ {
+diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
+index c503a58..bace5a1 100644
+--- a/indra/llmessage/message.h
++++ b/indra/llmessage/message.h
+@@ -179,7 +179,7 @@ enum EMessageException
+ 	MX_WROTE_PAST_BUFFER_SIZE // wrote past buffer size in zero code expand
+ };
+ typedef void (*msg_exception_callback)(LLMessageSystem*,void*,EMessageException);
+-
++typedef void (*message_handler_func_t)(LLMessageSystem *msgsystem, void **user_data);
+ 
+ // message data pieces are used to collect the data called for by the message template
+ class LLMsgData;
+@@ -299,12 +299,24 @@ public:
+ 
+ 
+ 	// methods for building, sending, receiving, and handling messages
+-	void	setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL);
+-	void	setHandlerFunc(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL)
++	void	setHandlerFuncFast(const char *name, message_handler_func_t, void **user_data = NULL);
++	void	setHandlerFunc(const char *name, message_handler_func_t handler_func, void **user_data = NULL)
+ 	{
+ 		setHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func, user_data);
+ 	}
+ 
++	void	addHandlerFuncFast(const char *name, message_handler_func_t, void **user_data = NULL);
++	void	addHandlerFunc(const char *name, message_handler_func_t handler_func, void **user_data = NULL)
++	{
++		addHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func, user_data);
++	}
++
++	void	delHandlerFuncFast(const char *name, message_handler_func_t);
++	void	delHandlerFunc(const char *name, message_handler_func_t handler_func)
++	{
++		delHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func);
++	}
++
+ 	// Set a callback function for a message system exception.
+ 	void setExceptionFunc(EMessageException exception, msg_exception_callback func, void* data = NULL);
+ 	// Call the specified exception func, and return TRUE if a
+diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
+index 7dba55f..8cff81e 100644
+--- a/indra/llui/llscrolllistctrl.cpp
++++ b/indra/llui/llscrolllistctrl.cpp
+@@ -703,6 +703,29 @@ std::vector<LLScrollListItem*> LLScrollListCtrl::getAllSelected() const
+ 	return ret;
+ }
+ 
++/**
++ * Returns the selected IDs
++ * @returns List of selected IDs
++ * @author Dale Glass
++ */
++LLDynamicArray<LLUUID> LLScrollListCtrl::getSelectedIDs()
++{
++	LLUUID selected_id;
++	LLDynamicArray<LLUUID> ret;
++
++	item_list::const_iterator iter;
++	for(iter = mItemList.begin(); iter != mItemList.end(); iter++)
++	{
++		LLScrollListItem* item  = *iter;
++		if (item->getSelected())
++		{
++			ret.push_back(item->getUUID());
++		}
++	}
++	return ret;
++}
++
++
+ S32 LLScrollListCtrl::getFirstSelectedIndex() const
+ {
+ 	S32 CurSelectedIndex = 0;
+@@ -2534,6 +2557,23 @@ void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void
+ }
+ 
+ 
++/**
++ * Re-sorts the list
++ *
++ * This function allows to avoid multiple unnecessary sorts in the case where
++ * multiple elements will be added or removed at once.
++ * @author Dale Glass
++ */
++void LLScrollListCtrl::sort()
++{
++	// sort by column 0, in ascending order
++	std::stable_sort(
++		mItemList.begin(), 
++		mItemList.end(), 
++		SortScrollListItem(mSortColumns));
++}
++
++
+ void LLScrollListCtrl::sortByColumn(const std::string& name, BOOL ascending)
+ {
+ 	std::map<std::string, LLScrollListColumn>::iterator itor = mColumns.find(name);
+@@ -3851,3 +3891,4 @@ BOOL LLColumnHeader::canResize()
+ {
+ 	return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth);
+ }
++
+diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
+index f276562..859e6ae 100644
+--- a/indra/llui/llscrolllistctrl.h
++++ b/indra/llui/llscrolllistctrl.h
+@@ -421,6 +421,7 @@ public:
+ 	// Sets an array of column descriptors
+ 	void 	   		setColumnHeadings(LLSD headings);
+ 	void   			sortByColumnIndex(U32 column, BOOL ascending);
++	void            sort();
+ 	
+ 	// LLCtrlListInterface functions
+ 	virtual S32  getItemCount() const;
+@@ -518,6 +519,7 @@ public:
+ 	virtual S32			getFirstSelectedIndex() const;
+ 	std::vector<LLScrollListItem*> getAllSelected() const;
+ 	LLScrollListItem*	getLastSelectedItem() const { return mLastSelected; }
++ 	LLDynamicArray<LLUUID> 	getSelectedIDs();
+ 
+ 	// iterate over all items
+ 	LLScrollListItem*	getFirstData() const;
+diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
+index 7c49f72..7d8b306 100644
+--- a/indra/newview/CMakeLists.txt
++++ b/indra/newview/CMakeLists.txt
+@@ -122,6 +122,7 @@ set(viewer_SOURCE_FILES
+     llfloateranimpreview.cpp
+     llfloaterauction.cpp
+     llfloateravatarinfo.cpp
++    llfloateravatarlist.cpp
+     llfloateravatarpicker.cpp
+     llfloateravatartextures.cpp
+     llfloaterbeacons.cpp
+@@ -244,6 +245,7 @@ set(viewer_SOURCE_FILES
+     llpanelaudioprefs.cpp
+     llpanelaudiovolume.cpp
+     llpanelavatar.cpp
++    llpaneldatabase.cpp
+     llpanelclassified.cpp
+     llpanelcontents.cpp
+     llpaneldebug.cpp
+@@ -638,6 +640,7 @@ set(viewer_HEADER_FILES
+     llpanelaudioprefs.h
+     llpanelaudiovolume.h
+     llpanelavatar.h
++    llpaneldatabase.h
+     llpanelclassified.h
+     llpanelcontents.h
+     llpaneldebug.h
+diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
+index 688dcab..7f28ea4 100644
+--- a/indra/newview/app_settings/settings.xml
++++ b/indra/newview/app_settings/settings.xml
+@@ -2622,6 +2622,22 @@
+         <integer>0</integer>
+       </array>
+     </map>
++    <key>FloaterAvatarListRect</key>
++    <map>
++      <key>Comment</key>
++      <string>Rectangle avatar list window</string>
++      <key>Persist</key>
++      <integer>1</integer>
++      <key>Type</key>
++      <string>Rect</string>
++      <key>Value</key>
++      <array>
++        <integer>0</integer>
++        <integer>400</integer>
++        <integer>200</integer>
++        <integer>0</integer>
++      </array>
++    </map>
+     <key>FloaterAudioVolumeRect</key>
+     <map>
+       <key>Comment</key>
+diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
+index 301f00b..23982ee 100644
+--- a/indra/newview/llagent.cpp
++++ b/indra/newview/llagent.cpp
+@@ -67,6 +67,7 @@
+ #include "llfloater.h"
+ #include "llfloateractivespeakers.h"
+ #include "llfloateravatarinfo.h"
++#include "llfloateravatarlist.h"
+ #include "llfloaterbuildoptions.h"
+ #include "llfloatercamera.h"
+ #include "llfloaterchat.h"
+@@ -2747,7 +2748,18 @@ void LLAgent::startTyping()
+ 	{
+ 		sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START);
+ 	}
+-	gChatBar->sendChatFromViewer("", CHAT_TYPE_START, FALSE);
++	sendChat("", 0, CHAT_TYPE_START, false);
++
++	// Addition for avatar list support.
++	// Makes the fact that this avatar is typing appear in the list
++	if ( NULL != gFloaterAvatarList )
++	{
++		LLAvatarListEntry *ent = gFloaterAvatarList->getAvatarEntry(getID());
++		if ( NULL != ent )
++		{
++			ent->setActivity(ACTIVITY_TYPING);
++		}
++	}
+ }
+ 
+ //-----------------------------------------------------------------------------
+@@ -2759,7 +2771,7 @@ void LLAgent::stopTyping()
+ 	{
+ 		clearRenderState(AGENT_STATE_TYPING);
+ 		sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP);
+-		gChatBar->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);
++		sendChat("", 0, CHAT_TYPE_STOP, false);
+ 	}
+ }
+ 
+@@ -4585,10 +4597,16 @@ void LLAgent::heardChat(const LLUUID& id)
+ 	mChatTimer.reset();
+ }
+ 
++
++void LLAgent::lookAtLastChat()
++{
++	lookAtObject(mLastChatterID, CAMERA_POSITION_SELF);
++}
++
+ //-----------------------------------------------------------------------------
+ // lookAtLastChat()
+ //-----------------------------------------------------------------------------
+-void LLAgent::lookAtLastChat()
++void LLAgent::lookAtObject(LLUUID object_id, ECameraPosition camera_pos)
+ {
+ 	// Block if camera is animating or not in normal third person camera mode
+ 	if (mCameraAnimating || !cameraThirdPerson())
+@@ -4596,7 +4614,7 @@ void LLAgent::lookAtLastChat()
+ 		return;
+ 	}
+ 
+-	LLViewerObject *chatter = gObjectList.findObject(mLastChatterID);
++	LLViewerObject *chatter = gObjectList.findObject(object_id);
+ 	if (chatter)
+ 	{
+ 		LLVector3 delta_pos;
+@@ -4625,15 +4643,39 @@ void LLAgent::lookAtLastChat()
+ 			new_camera_pos -= delta_pos * 0.4f;
+ 			new_camera_pos += left * 0.3f;
+ 			new_camera_pos += up * 0.2f;
++
++			F32 radius = chatter_av->getVObjRadius();
++			LLVector3d view_dist(radius, radius, 0.0f);
++
+ 			if (chatter_av->mHeadp)
+ 			{
+-				setFocusGlobal(getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), mLastChatterID);
++				setFocusGlobal(getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), object_id);
+ 				mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition());
++
++				switch(camera_pos)
++				{
++					case CAMERA_POSITION_SELF:
++						mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition());
++						break;
++					case CAMERA_POSITION_OBJECT:
++						mCameraFocusOffsetTarget =  view_dist;
++						break;
++				}
+ 			}
+ 			else
+ 			{
+-				setFocusGlobal(chatter->getPositionGlobal(), mLastChatterID);
++				setFocusGlobal(chatter->getPositionGlobal(), object_id);
+ 				mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal();
++
++				switch(camera_pos)
++				{
++					case CAMERA_POSITION_SELF:
++						mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal();
++						break;
++					case CAMERA_POSITION_OBJECT:
++						mCameraFocusOffsetTarget = view_dist;
++						break;
++				}
+ 			}
+ 			setFocusOnAvatar(FALSE, TRUE);
+ 		}
+@@ -4655,8 +4697,20 @@ void LLAgent::lookAtLastChat()
+ 			new_camera_pos += left * 0.3f;
+ 			new_camera_pos += up * 0.2f;
+ 
+-			setFocusGlobal(chatter->getPositionGlobal(), mLastChatterID);
+-			mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal();
++			setFocusGlobal(chatter->getPositionGlobal(), object_id);
++
++			switch(camera_pos)
++			{
++				case CAMERA_POSITION_SELF:
++					mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal();
++					break;
++				case CAMERA_POSITION_OBJECT:
++					F32 radius = chatter->getVObjRadius();
++					LLVector3d view_dist(radius, radius, 0.0f);
++					mCameraFocusOffsetTarget = view_dist;
++					break;
++			}
++
+ 			setFocusOnAvatar(FALSE, TRUE);
+ 		}
+ 	}
+@@ -6012,6 +6066,57 @@ void LLAgent::setTeleportState(ETeleportState state)
+ 	}
+ }
+ 
++void LLAgent::sendChat(const std::string &text, S32 channel, EChatType type, bool animate)
++{
++
++	// Don't animate for chats people can't hear (chat to scripts)
++	if (animate && (channel == 0))
++	{
++		if (type == CHAT_TYPE_WHISPER)
++		{
++			lldebugs << "You whisper " << text << llendl;
++			sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START);
++		}
++		else if (type == CHAT_TYPE_NORMAL)
++		{
++			lldebugs << "You say " << text << llendl;
++			sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START);
++		}
++		else if (type == CHAT_TYPE_SHOUT)
++		{
++			lldebugs << "You shout " << text << llendl;
++			sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START);
++		}
++		else
++		{
++			llinfos << "send_chat_from_viewer() - invalid volume" << llendl;
++			return;
++		}
++	}
++	else
++	{
++		if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP)
++		{
++			lldebugs << "Channel chat: " << text << llendl;
++		}
++	}
++
++	LLMessageSystem* msg = gMessageSystem;
++
++	msg->newMessageFast(_PREHASH_ChatFromViewer);
++	msg->nextBlockFast(_PREHASH_AgentData);
++	msg->addUUIDFast(_PREHASH_AgentID, getID());
++	msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
++	msg->nextBlockFast(_PREHASH_ChatData);
++	msg->addStringFast(_PREHASH_Message, text);
++	msg->addU8Fast(_PREHASH_Type, type);
++	msg->addS32("Channel", channel);
++
++	gAgent.sendReliableMessage();
++
++	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT);
++}
++
+ void LLAgent::fidget()
+ {
+ 	if (!getAFK())
+diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
+index 3d3a94b..2b325f9 100644
+--- a/indra/newview/llagent.h
++++ b/indra/newview/llagent.h
+@@ -36,6 +36,7 @@
+ 
+ #include "indra_constants.h"
+ #include "llmath.h"
++#include "llchat.h"
+ #include "llcontrol.h"
+ #include "llcoordframe.h"
+ #include "llevent.h"
+@@ -80,6 +81,15 @@ typedef enum e_camera_modes
+ 	CAMERA_MODE_FOLLOW
+ } ECameraMode;
+ 
++/**
++ * @brief When looking at an object, where is the camera offset from
++ */
++typedef enum e_camera_position
++{
++	CAMERA_POSITION_SELF, /** Camera positioned at our position */
++	CAMERA_POSITION_OBJECT /** Camera positioned at observed object's position */
++} ECameraPosition;
++
+ typedef enum e_anim_request
+ {
+ 	ANIM_REQUEST_START,
+@@ -206,6 +216,7 @@ public:
+ 
+ 	void			heardChat(const LLUUID& id);
+ 	void			lookAtLastChat();
++	void			lookAtObject(LLUUID avatar_id, ECameraPosition camera_pos);
+ 	F32			getTypingTime() { return mTypingTimer.getElapsedTimeF32(); }
+ 
+ 	void			setAFK();
+@@ -479,6 +490,9 @@ public:
+ 
+ 	const std::string getTeleportSourceSLURL() const { return mTeleportSourceSLURL; }
+ 
++	void sendChat(const std::string &text, S32 channel = 0, EChatType type = CHAT_TYPE_NORMAL, bool animate = false);
++	void sendChat(const std::wstring &text, S32 channel = 0, EChatType type = CHAT_TYPE_NORMAL, bool animate = false)
++		{ sendChat(wstring_to_utf8str(text), channel, type, animate); }
+ 
+ 	// Setting the ability for this avatar to proxy for another avatar.
+ 	//static void processAddModifyAbility(LLMessageSystem* msg, void**);
+diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
+index 63711ba..04d8b48 100644
+--- a/indra/newview/llappviewer.cpp
++++ b/indra/newview/llappviewer.cpp
+@@ -33,6 +33,7 @@
+ #include "llviewerprecompiledheaders.h"
+ #include "llappviewer.h"
+ #include "llprimitive.h"
++#include "llfloateravatarlist.h"
+ 
+ #include "llversionviewer.h"
+ #include "llfeaturemanager.h"
+@@ -3160,6 +3161,9 @@ void LLAppViewer::idle()
+ 		}
+ 		gFrameStats.addFrameData();
+ 	}
++
++	// Update avatar list
++	gFloaterAvatarList->updateAvatarList();
+ 	
+ 	if (!gDisconnected)
+ 	{
+diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
+index 84ebf98..1678bc3 100644
+--- a/indra/newview/llchatbar.cpp
++++ b/indra/newview/llchatbar.cpp
+@@ -585,39 +585,7 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL
+ 		utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1);
+ 	}
+ 
+-	// Don't animate for chats people can't hear (chat to scripts)
+-	if (animate && (channel == 0))
+-	{
+-		if (type == CHAT_TYPE_WHISPER)
+-		{
+-			lldebugs << "You whisper " << utf8_text << llendl;
+-			gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START);
+-		}
+-		else if (type == CHAT_TYPE_NORMAL)
+-		{
+-			lldebugs << "You say " << utf8_text << llendl;
+-			gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START);
+-		}
+-		else if (type == CHAT_TYPE_SHOUT)
+-		{
+-			lldebugs << "You shout " << utf8_text << llendl;
+-			gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START);
+-		}
+-		else
+-		{
+-			llinfos << "send_chat_from_viewer() - invalid volume" << llendl;
+-			return;
+-		}
+-	}
+-	else
+-	{
+-		if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP)
+-		{
+-			lldebugs << "Channel chat: " << utf8_text << llendl;
+-		}
+-	}
+-
+-	send_chat_from_viewer(utf8_out_text, type, channel);
++	gAgent.sendChat(utf8_out_text, channel, type, animate);
+ }
+ 
+ void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)
+diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp
+new file mode 100644
+index 0000000..e1656eb
+--- /dev/null
++++ b/indra/newview/llfloateravatarlist.cpp
+@@ -0,0 +1,2187 @@
++/** 
++ * @file llfloatermute.cpp
++ * @brief Container for mute list
++ *
++ * @author Dale Glass <dale at daleglass.net>, (C) 2007
++ */
++
++#include "llviewerprecompiledheaders.h" // must be first include
++
++#include "llavatarconstants.h"
++#include "llfloateravatarlist.h"
++
++#include "lluictrlfactory.h" // builds floaters from XML
++#include "llviewerwindow.h"
++#include "llscrolllistctrl.h"
++
++#include "llvoavatar.h"
++#include "llimview.h"
++#include "llfloateravatarinfo.h"
++#include "llregionflags.h"
++#include "llfloaterreporter.h"
++#include "llagent.h"
++#include "llviewerregion.h"
++#include "lltracker.h"
++#include "llviewercontrol.h"
++#include "llviewerstats.h"
++#include "llerror.h"
++#include "llchat.h"
++#include "llviewermessage.h"
++#include "llweb.h"
++#include "llviewerobjectlist.h"
++#include "llmutelist.h"
++#include "llviewerimagelist.h"
++#include "llworld.h"
++#include "llcachename.h"
++#include "llviewercamera.h"
++
++#include <time.h>
++#include <string.h>
++
++#include <map>
++
++
++// Timeouts
++/**
++ * @brief How long to keep showing an activity, in seconds
++ */
++const F32 ACTIVITY_TIMEOUT = 1.0f;
++
++
++/**
++ * @brief How many seconds to wait between data requests
++ *
++ * This is intended to avoid flooding the server with requests
++ */
++const F32 MIN_REQUEST_INTERVAL   = 1.0f;
++
++/**
++ * @brief How long to wait for a request to arrive during the first try in seconds
++ */
++const F32 FIRST_REQUEST_TIMEOUT  = 16.0f;
++
++/**
++ * @brief Delay is doubled on each attempt. This is as high as it'll go
++ */
++const F32 MAX_REQUEST_TIMEOUT    = 2048.0f;
++ 
++/**
++ * How long to wait for a request to arrive before assuming failure
++ * and showing the failure icon in the list. This is just for the user's
++ * information, if a reply arrives after this interval we'll accept it anyway.
++ */
++const F32 REQUEST_FAIL_TIMEOUT   = 15.0f;
++
++/**
++ * How long to keep people who are gone in the list. After this time is reached,
++ * they're not shown in the list anymore, but still kept in memory until
++ * CLEANUP_TIMEOUT is reached.
++ */
++const F32 DEAD_KEEP_TIME = 10.0f;
++
++/**
++ * @brief How long to keep entries around before removing them.
++ *
++ * @note Longer term, data like birth and payment info should be cached on disk.
++ */
++const F32 CLEANUP_TIMEOUT = 3600.0f;
++
++
++/**
++ * @brief TrustNet channel
++ * This is fixed in the adapter script.
++ */
++const S32 TRUSTNET_CHANNEL = 0x44470002;
++
++
++extern U32 gFrameCount;
++
++
++LLAvListTrustNetScore::LLAvListTrustNetScore(std::string type, F32 score)
++{
++	Score = score;
++	Type = type;	
++}
++
++LLAvatarInfo::LLAvatarInfo()
++{
++}
++
++LLAvatarInfo::LLAvatarInfo(PAYMENT_TYPE payment, ACCOUNT_TYPE account, struct tm birth)
++{
++	Payment = payment;
++	Account = account;
++	BirthDate = birth;
++}
++
++S32 LLAvatarInfo::getAge()
++{
++	time_t birth = mktime(&BirthDate);
++	time_t now = time(NULL);
++	return(S32)(difftime(now,birth) / (60*60*24));
++}
++
++void LLAvatarListEntry::setPosition(LLVector3d position)
++{
++	if ( mPosition != position )
++	{
++		setActivity(ACTIVITY_MOVING);
++	}
++
++	mPosition = position;
++	mFrame = gFrameCount;
++	mUpdateTimer.start();
++}
++
++LLVector3d LLAvatarListEntry::getPosition()
++{
++	return mPosition;
++}
++
++U32 LLAvatarListEntry::getEntryAgeFrames()
++{
++	return (gFrameCount - mFrame);
++}
++
++F32 LLAvatarListEntry::getEntryEnteredSeconds()
++{
++	return mEnteredTimer.getElapsedTimeF32();
++}
++
++F32 LLAvatarListEntry::getEntryAgeSeconds()
++{
++	return mUpdateTimer.getElapsedTimeF32();
++}
++
++void LLAvatarListEntry::setName(std::string name)
++{
++	if ( name.empty() || (name.compare(" ") == 0))
++	{
++		llwarns << "Trying to set empty name" << llendl;
++	}
++	mName = name;
++}
++
++std::string LLAvatarListEntry::getName()
++{
++	return mName;
++}
++
++LLUUID LLAvatarListEntry::getID()
++{
++	return mID;
++}
++
++void LLAvatarListEntry::setID(LLUUID id)
++{
++	if ( id.isNull() )
++	{
++		llwarns << "Trying to set null id" << llendl;
++	}
++	mID = id;
++}
++
++BOOL LLAvatarListEntry::getIsLinden()
++{
++	// Are there any employees that are not a Linden?
++	// I suppose this is a bit redundant.
++	return ( mIsLinden || ( mAvatarInfo.getValue().Account == ACCOUNT_EMPLOYEE ) );
++}
++
++void LLAvatarListEntry::setAccountCustomTitle(std::string &title)
++{
++	mAccountTitle = title;
++	mAvatarInfo.getValue().Account = ACCOUNT_CUSTOM;
++}
++
++std::string LLAvatarListEntry::getAccountCustomTitle()
++{
++	return mAccountTitle;
++}
++
++
++
++void LLAvatarListEntry::setActivity(ACTIVITY_TYPE activity)
++{
++	if ( activity >= mActivityType || mActivityTimer.getElapsedTimeF32() > ACTIVITY_TIMEOUT )
++	{
++		mActivityType = activity;
++		mActivityTimer.start();
++	}
++}
++
++ACTIVITY_TYPE LLAvatarListEntry::getActivity()
++{
++	if ( mActivityTimer.getElapsedTimeF32() > ACTIVITY_TIMEOUT )
++	{
++		mActivityType = ACTIVITY_NONE;
++	}
++	
++	return mActivityType;
++}
++
++void LLAvatarListEntry::toggleMark()
++{
++	mMarked = !mMarked;
++}
++
++BOOL LLAvatarListEntry::isMarked()
++{
++	return mMarked;
++}
++
++BOOL LLAvatarListEntry::isDead()
++{
++	return getEntryAgeSeconds() > DEAD_KEEP_TIME;
++}
++
++// Avatar list is global
++LLFloaterAvatarList* gFloaterAvatarList = NULL;
++
++
++
++
++LLFloaterAvatarList::LLFloaterAvatarList() :  LLFloater("avatar list")
++{
++
++	// Default values
++	mTracking = FALSE;
++	mTrackByLocation = FALSE;
++	mARLastFrame = 0;
++
++	// Create interface from XML
++	LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_scanner.xml");
++
++	// Floater starts hidden	
++	setVisible(FALSE);
++
++	// Set callbacks
++	//childSetAction("refresh_btn", onClickRefresh, this);
++	childSetAction("profile_btn", onClickProfile, this);
++	childSetAction("im_btn", onClickIM, this);
++	childSetAction("track_btn", onClickTrack, this);
++	childSetAction("mark_btn", onClickMark, this);
++
++	childSetAction("gowarn_btn", onClickGohomerWarn, this);
++	childSetAction("goeject_btn", onClickGohomerEject, this);
++	childSetAction("goaway_btn", onClickGohomerSendAway, this);
++	childSetAction("gohome_btn", onClickGohomerSendHome, this);
++	childSetAction("gohomeoff_btn", onClickGohomerOff, this);
++	childSetAction("gokey_btn", onClickGohomerSendHomeByKey, this);
++
++	childSetAction("prev_in_list_btn", onClickPrevInList, this);
++	childSetAction("next_in_list_btn", onClickNextInList, this);
++	childSetAction("prev_marked_btn", onClickPrevMarked, this);
++	childSetAction("next_marked_btn", onClickNextMarked, this);
++	
++	childSetAction("get_key_btn", onClickGetKey, this);
++
++	childSetAction("tn_rate_btn", onClickTrustNetRate, this);
++	childSetAction("tn_explain_btn", onClickTrustNetExplain, this);
++	childSetAction("tn_website_btn", onClickTrustNetWebsite, this);
++	childSetAction("tn_password_btn", onClickTrustNetGetPassword, this);
++	childSetAction("tn_renew_btn", onClickTrustNetRenew, this);
++
++	childSetAction("freeze_btn", onClickFreeze, this);
++	childSetAction("eject_btn", onClickEject, this);
++//	childSetAction("ban_btn", onClickBan, this);
++//	childSetAction("unban_btn", onClickUnban, this);
++	childSetAction("mute_btn", onClickMute, this);
++//	childSetAction("unmute_btn", onClickUnmute, this);
++	childSetAction("ar_btn", onClickAR, this);
++	childSetAction("teleport_btn", onClickTeleport, this);
++	childSetAction("estate_eject_btn", onClickEjectFromEstate, this);
++
++	setDefaultBtn("refresh_btn");
++
++	// Get a pointer to the scroll list from the interface
++	mAvatarList = getChild<LLScrollListCtrl>("avatar_list");
++
++	mAvatarList->setCallbackUserData(this);
++	mAvatarList->setDoubleClickCallback(onDoubleClick);
++	mAvatarList->sortByColumn("distance", TRUE);
++	mDataRequestTimer.start();
++	refreshAvatarList();
++
++	LLMessageSystem *msg = gMessageSystem;
++	msg->addHandlerFunc("AvatarPropertiesReply", processAvatarPropertiesReply);
++}
++
++LLFloaterAvatarList::~LLFloaterAvatarList()
++{
++	LLMessageSystem *msg = gMessageSystem;
++	if ( msg )
++	{
++		msg->delHandlerFunc("AvatarPropertiesReply", processAvatarPropertiesReply);
++	}
++	std::map< LLUUID, LLPointer< LLHUDObject > >::iterator it = mHudObjectMap.begin();
++	for ( ; it != mHudObjectMap.end(); ++it )
++	{ // clean up list
++		it->second->markDead();
++	}
++
++}
++
++
++void LLFloaterAvatarList::show()
++{
++	// Make sure we make a noise.
++	open();
++}
++
++//static
++void LLFloaterAvatarList::toggle(void*) {
++	if (!gFloaterAvatarList) {
++		llinfos << "No avatar list!" << llendl;
++		return;
++	}
++
++	if (gFloaterAvatarList->getVisible())
++	{
++		gFloaterAvatarList->close();
++	}
++	else
++	{
++		gFloaterAvatarList->show();
++	}
++}
++
++//static
++BOOL LLFloaterAvatarList::visible(void*)
++{
++	return (gFloaterAvatarList && gFloaterAvatarList->getVisible());
++}
++
++void LLFloaterAvatarList::updateFromCoarse()
++{
++	/*
++	 * Walk through remaining list of coarse update avatars in all known regions
++	 * this will not give us an accurate height since it's mod 2048 and least possible
++	 * increment is 4 meter. Coarse Update information is accurate instantly while
++	 * the object list is filled one by one.
++	 *
++	 * This also works for neighbour sims which makes it really handy :)
++	 */
++	
++	// first wipe the list clean from coarse entries
++	std::map<LLUUID, LLAvatarListEntry>::iterator iter;
++	for(iter = mAvatars.begin(); iter != mAvatars.end();)
++	{
++		LLAvatarListEntry entry = iter->second;
++		if ( entry.getIsCoarse() )
++		{
++			mAvatars.erase( iter++ );
++		}
++		else
++		{
++			++iter;
++		}
++	}
++
++	LLWorld::region_list_t regions = LLWorld::getInstance()->getRegionList();
++	LLWorld::region_list_t::const_iterator it = regions.begin();
++	
++	for ( ; it != regions.end(); ++it )
++	{
++		LLViewerRegion const *region = *it;
++		if ( !region )
++		{
++			llwarns << "null region while parsing region list" << llendl;
++			continue;
++		}
++
++		for (int idx = 0; idx < region->mMapAvatarIDs.count(); ++idx)
++		{
++			LLUUID avid = region->mMapAvatarIDs.get( idx );
++
++			if ( avid.isNull() )
++			{
++				continue;
++			}
++
++			// we need to accomodate for avatars that are stuck in the
++			// object list while still accurately received in the coarse
++			// location list
++			U32 modpos = region->mMapAvatars.get( idx );
++			LLVector3 localpos;
++			localpos[0] = (modpos >> 16) & 0xff;
++			localpos[1] = (modpos >>  8) & 0xff;
++			// scale z-position
++			localpos[2] = (modpos        & 0xff) << 2;
++			LLVector3d position = region->getPosGlobalFromRegion( localpos );
++			
++			if ( ( mAvatars.count( avid ) > 0 ) && ( !mAvatars[ avid ].isDead() ) )
++			{
++				// Avatar already in list but could be one of these "perpetual motion" avatars
++				// which would overlay the real coordinates, so we check for the distance disregarding
++				// the z axis
++				LLVector3d coarsepos = position;
++				coarsepos[2]     = 0.0;
++				LLVector3d vopos = mAvatars[ avid ].mPosition;
++				vopos[2]         = 0.0;
++				LLVector3d dist  = coarsepos - vopos;
++				if ( dist.magVecSquared() > ( 50.0 * 50.0 ) )
++				{
++					// Avatar already in list, but position info is
++					// out of sync so use coarse info, we can safely overwrite
++					// the info here since we are called after the VOlist has
++					// already been parsed. The only issue is that this will now
++					// show the avatar as perpetually moving
++					mAvatars[ avid ].setPosition( coarsepos );
++				}
++				// Avatar already in list, active and
++				// close enough to coarse info, so skip
++				continue;
++			}
++
++			// Avatar not there yet, add it
++			std::string name;
++			BOOL isLinden = FALSE;
++			if ( !gCacheName->getFullName( avid, name ) )
++			{
++				continue; // wait for proper name
++			}
++			else
++			{
++				std::string first, last;
++				gCacheName->getName( avid, first, last );
++				if ( last == "Linden" )
++				{
++					isLinden = TRUE;
++				}
++			}
++
++			std::string regionname;
++			if ( gAgent.getRegion() && ( region->getName() != gAgent.getRegion()->getName() ) )
++			{
++				regionname = region->getName();
++			}
++
++			// add as coarse info
++			LLAvatarListEntry entry(avid, name, position, isLinden, TRUE, regionname);
++			mAvatars[avid] = entry;
++
++			//llinfos << "avatar list refresh from coarse: adding " << name << llendl;
++
++		}
++	}
++}
++
++
++void LLFloaterAvatarList::purgeAvatarHUDMap()
++{
++	std::map< LLUUID, LLPointer< LLHUDObject > >::iterator huditer = mHudObjectMap.begin();
++	while ( huditer != mHudObjectMap.end() )
++	{
++		if ( mAvatars.count( huditer->first ) == 0 )
++		{
++			huditer->second->markDead();
++			mHudObjectMap.erase( huditer++ );
++		}
++		else
++		{
++			++huditer;
++		}
++	}
++}
++
++
++void LLFloaterAvatarList::updateAvatarList()
++{
++//	LLVOAvatar *avatarp;
++
++	//llinfos << "avatar list refresh: updating map" << llendl;
++
++	// Check whether updates are enabled
++	LLCheckboxCtrl* check;
++	check = getChild<LLCheckBoxCtrl>("update_enabled_cb");
++
++	if ( !check->getValue() )
++	{
++		return;
++	}
++
++	
++	/*
++	 * Iterate over all the avatars known at the time
++	 * NOTE: Is this the right way to do that? It does appear that LLVOAvatar::isInstances contains
++	 * the list of avatars known to the client. This seems to do the task of tracking avatars without
++	 * any additional requests.
++	 *
++	 * BUG: It looks like avatars sometimes get stuck in this list, and keep perpetually
++	 * moving in the same direction. My current guess is that somewhere else the client
++	 * doesn't notice an avatar disappeared, and keeps updating its position. This should
++	 * be solved at the source of the problem.
++	 */
++	for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
++		iter != LLCharacter::sInstances.end(); ++iter)
++	{
++		LLVOAvatar* avatarp = (LLVOAvatar*) *iter;
++
++		// Skip if avatar is dead(what's that?)
++		// or if the avatar is ourselves.
++		if (avatarp->isDead() || avatarp->isSelf())
++		{
++			continue;
++		}
++
++		// Get avatar data
++		LLVector3d position = gAgent.getPosGlobalFromAgent(avatarp->getCharacterPosition());
++		LLUUID avid = avatarp->getID();
++		std::string name = avatarp->getFullname();
++
++		// Apparently, sometimes the name comes out empty, with a " " name. This is because
++		// getFullname concatenates first and last name with a " " in the middle.
++		// This code will avoid adding a nameless entry to the list until it acquires a name.
++		if (name.empty() || (name.compare(" ") == 0))
++		{
++			llinfos << "Name empty for avatar " << avid << llendl;
++			continue;
++		}
++
++		if (avid.isNull())
++		{
++			llinfos << "Key empty for avatar " << name << llendl;
++			continue;
++		}
++
++		if ( ( mAvatars.count( avid ) > 0 ) && !mAvatars[avid].getIsCoarse() )
++		{
++			// Avatar already in list, update position
++			mAvatars[avid].setPosition(position);
++		}
++		else
++		{
++			// Avatar not there yet or only from coarse list, add it properly
++			BOOL isLinden = ( std::string( avatarp->getNVPair("LastName")->getString() ) == "Linden" );
++
++			LLAvatarListEntry entry(avid, name, position, isLinden);
++			mAvatars[avid] = entry;
++
++			sendAvatarPropertiesRequest(avid);
++			llinfos << "avatar list refresh: adding " << name << llendl;
++
++		}
++
++	}
++
++	updateFromCoarse();
++
++//	llinfos << "avatar list refresh: done" << llendl;
++
++	expireAvatarList();
++	refreshAvatarList();
++	
++	purgeAvatarHUDMap();
++	
++	checkTrackingStatus();
++	processARQueue();
++}
++
++void LLFloaterAvatarList::processARQueue()
++{
++	if ( mARQueue.empty() ) return;
++
++	LLUUID avatar_id = mARQueue.front();
++
++	if ( 0 == mARLastFrame )
++	{
++		// Start of the process: Move the camera to the avatar. This happens gradually,
++		// so we'll give it a few frames
++		gAgent.lookAtObject(avatar_id, CAMERA_POSITION_OBJECT);
++		mARLastFrame = gFrameCount;
++		return;
++	}
++
++	if ( gFrameCount - mARLastFrame >= 10 )
++	{
++		// Camera should be in position, show AR screen now
++		LLFloaterReporter *report = LLFloaterReporter::showFromObject(avatar_id, false);
++		report->setMinimized(TRUE);
++
++		mARReporterQueue.push(report);
++
++		mARQueue.pop();
++		mARLastFrame = 0;
++
++		if ( mARQueue.empty() )
++		{
++			// Now that all reports are taken, open them.
++
++			while( !mARReporterQueue.empty() )
++			{
++				LLFloaterReporter *r = mARReporterQueue.front();
++				mARReporterQueue.pop();
++
++				r->open();
++				r->setMinimized(FALSE);
++			}
++		}
++	}
++}
++
++void LLFloaterAvatarList::expireAvatarList()
++{
++//	llinfos << "avatar list: expiring" << llendl;
++	std::map<LLUUID, LLAvatarListEntry>::iterator iter;
++	std::queue<LLUUID> delete_queue;
++
++	for(iter = mAvatars.begin(); iter != mAvatars.end(); iter++)
++	{
++		LLAvatarListEntry *ent = &iter->second;
++		
++		if ( ent->getEntryAgeFrames() >= 2 )
++		{
++			ent->setActivity(ACTIVITY_DEAD);
++		}
++
++
++		if ( ent->getEntryAgeSeconds() > CLEANUP_TIMEOUT )
++		{
++			llinfos << "avatar list: expiring avatar " << ent->getName() << llendl;
++			LLUUID av_id = ent->getID();
++			delete_queue.push(av_id);
++		}
++	}
++
++	while(!delete_queue.empty())
++	{
++		mAvatars.erase(delete_queue.front());
++		if ( mHudObjectMap.count(delete_queue.front()) )
++		{
++			mHudObjectMap[delete_queue.front()]->markDead();
++			mHudObjectMap.erase(delete_queue.front());
++		}
++		delete_queue.pop();
++	}
++}
++
++/**
++ * Redraws the avatar list
++ * Only does anything if the avatar list is visible.
++ * @author Dale Glass
++ */
++void LLFloaterAvatarList::refreshAvatarList() 
++{
++
++
++
++	// Don't update list when interface is hidden
++	if (!LLFloaterAvatarList::visible(NULL))
++	{
++		return;
++	}
++
++
++	LLCheckboxCtrl* fetch_data;
++	fetch_data = getChild<LLCheckBoxCtrl>("fetch_avdata_enabled_cb");
++
++	//BOOL db_enabled = gSavedSettings.getBOOL("DBEnabled");
++	//std::string db_avatar = gSavedPerAccountSettings.getString("DBAvatarName");
++	//if ( db_avatar.empty() )
++	//{
++	//	db_enabled = FALSE;
++	//}
++
++
++
++	// We rebuild the list fully each time it's refreshed
++	
++	// The assumption is that it's faster to refill it and sort than
++	// to rebuild the whole list.
++	LLDynamicArray<LLUUID> selected = mAvatarList->getSelectedIDs();
++	S32 scrollpos = mAvatarList->getScrollPos();
++
++	mAvatarList->deleteAllItems();
++
++	LLVector3d mypos = gAgent.getPositionGlobal();
++
++	unsigned int counter = 0;
++
++	std::map<LLUUID, LLAvatarListEntry>::iterator iter;
++	for(iter = mAvatars.begin(); iter != mAvatars.end(); iter++)
++	{
++		LLSD element;
++		LLUUID av_id;
++
++		
++		LLAvatarListEntry *ent = &iter->second;
++
++		// Skip if avatar hasn't been around
++		if ( ent->isDead() )
++		{
++			continue;
++		}
++
++		av_id = ent->getID();
++
++		// Get avatar name, position
++		LLAvatarInfo avinfo = ent->mAvatarInfo.getValue();
++		//LLAvListTrustNetScore avscore = ent->mTrustNetScore.getValue();
++
++		DATA_STATUS avinfo_status = ent->mAvatarInfo.getStatus();
++		//DATA_STATUS avscore_status = ent->mTrustNetScore.getStatus();
++
++		LLVector3d position = ent->getPosition();
++		LLVector3d delta = position - mypos;
++		F32 distance = (F32)delta.magVec();
++
++		std::string icon = "";
++
++		// HACK: Workaround for an apparent bug:
++		// sometimes avatar entries get stuck, and are registered
++		// by the client as perpetually moving in the same direction.
++		// this makes sure they get removed from the visible list eventually.
++		// for the coarse list this is not necessary since it is always accurate
++		if ( distance > 1024 && !ent->getIsCoarse() )
++		{
++			continue;
++		}
++
++		if ( av_id.isNull() )
++		{
++			llwarns << "Avatar with null key somehow got into the list!" << llendl;
++			continue;
++		}
++
++		counter++;
++
++		element["id"] = av_id;
++
++		element["columns"][LIST_AVATAR_ICON]["column"] = "avatar_icon";
++		element["columns"][LIST_AVATAR_ICON]["type"] = "text";
++		if ( !ent->isMarked() )
++		{ // show counter if not marked
++			element["columns"][LIST_AVATAR_ICON]["value"] = llformat("%d", counter);
++		}
++		else
++		{
++			element["columns"][LIST_AVATAR_ICON]["type"] = "icon";
++			const LLUUID flag_blue("e39cbfe7-c4e7-3bad-5e5f-958082d55046");
++			element["columns"][LIST_AVATAR_ICON]["value"] = flag_blue.asString();
++		}
++
++
++		if ( ent->getIsLinden() )
++		{
++			element["columns"][LIST_AVATAR_NAME]["font-style"] = "BOLD";
++		}
++
++		if ( ent->getIsCoarse() )
++		{
++			element["columns"][LIST_AVATAR_NAME]["color"] = LLColor4::grey4.getValue();
++		}
++
++		if ( ent->isFocused() )
++		{
++			element["columns"][LIST_AVATAR_NAME]["color"] = LLColor4::cyan.getValue();
++		}
++
++		//element["columns"][LIST_AVATAR_NAME]["font-color"] = getAvatarColor(ent, distance).getValue();
++		element["columns"][LIST_AVATAR_NAME]["column"] = "avatar_name";
++		element["columns"][LIST_AVATAR_NAME]["type"] = "text";
++		std::string agentname = ent->getName();
++		if ( !ent->getIsSameRegion() )
++		{
++			agentname += " (" + ent->getRegionName() + ")";
++		}
++		element["columns"][LIST_AVATAR_NAME]["value"] = agentname.c_str();
++
++		char temp[32];
++		snprintf(temp, sizeof(temp), "%.2f", distance);
++
++		element["columns"][LIST_DISTANCE]["column"] = "distance";
++		element["columns"][LIST_DISTANCE]["type"] = "text";
++		element["columns"][LIST_DISTANCE]["value"] = temp;
++		element["columns"][LIST_DISTANCE]["color"] = getAvatarColor(ent, distance, CT_DISTANCE).getValue();
++
++		
++		if ( avinfo_status == DATA_RETRIEVED )
++		{
++			element["columns"][LIST_AGE]["column"] = "age";
++			element["columns"][LIST_AGE]["type"] = "text";
++			element["columns"][LIST_AGE]["value"] = avinfo.getAge();
++			element["columns"][LIST_AGE]["color"] = getAvatarColor(ent, distance, CT_AGE).getValue();
++		}
++
++		const LLUUID info_error("bbda234c-c76e-8617-0a32-46cc15c5ec42");
++		const LLUUID info_fetching("1468fae4-2f47-6e75-d39f-3ccbd443d31c");
++		const LLUUID info_unknown("0f2d532a-1fc8-01bb-eed3-ef60e7943d1e");
++		const LLUUID payment_info_charter("07bef5d9-31b2-4cc5-999e-c2cd8b5d3a69");
++		const LLUUID payment_info_filled("9d61c4d5-e8f6-78ec-a64f-490e3a4c03d5");
++		const LLUUID payment_info_used("49ac7ef9-caaa-750a-6ec1-51358f0a1672");
++
++		/*
++		element["columns"][LIST_SCORE]["column"] = "score";
++		element["columns"][LIST_SCORE]["type"] = "text";
++
++		icon = "";
++		switch(avscore_status)
++		{
++			case DATA_UNKNOWN:
++				icon = info_unknown.asString();
++				break;
++			case DATA_REQUESTING:
++				icon = info_fetching.asString();
++				break;
++			case DATA_ERROR:
++				icon =  info_error.asString();
++			case DATA_RETRIEVED:
++				element["columns"][LIST_SCORE]["value"] = avscore.Score;
++				element["columns"][LIST_SCORE]["color"] = getAvatarColor(ent, distance, CT_SCORE).getValue();
++				break;
++		}
++		
++		if (!icon.empty() )
++		{	
++			element["columns"][LIST_SCORE].erase("color");
++			element["columns"][LIST_SCORE]["type"] = "icon";
++			element["columns"][LIST_SCORE]["value"] = icon;
++		}*/
++	
++
++		// Get an icon for the payment data
++		// These should be replaced with something proper instead of reusing whatever
++		// LL-provided images happened to fit
++		icon = "";
++
++		switch(avinfo_status)
++		{
++			case DATA_UNKNOWN:
++				icon = info_unknown.asString();
++				break;
++			case DATA_REQUESTING:
++				icon = info_fetching.asString();
++				break;
++			case DATA_ERROR:
++				icon = info_error.asString();
++				break;
++			case DATA_RETRIEVED:
++				switch(avinfo.Payment)
++				{
++					case PAYMENT_NONE:
++						break;
++					case PAYMENT_ON_FILE:
++						icon =  payment_info_filled.asString();
++						break;
++					case PAYMENT_USED:
++						icon =  payment_info_used.asString();
++						break;
++					case PAYMENT_LINDEN:
++						// confusingly named icon, maybe use something else
++						icon =  "icon_top_pick.tga";
++						break;
++				}
++				break;
++		}
++
++		element["columns"][LIST_PAYMENT]["column"] = "payment_data";
++		element["columns"][LIST_PAYMENT]["type"] = "text";
++
++		// TODO: Add icon for "unknown" status
++		//if ( PAYMENT_NONE != avinfo.Payment && DATA_UNKNOWN != avinfo_status )
++		if ( !icon.empty() )
++		{
++			element["columns"][LIST_PAYMENT].erase("color");
++			element["columns"][LIST_PAYMENT]["type"] = "icon";
++			element["columns"][LIST_PAYMENT]["value"] =  icon;
++			//llinfos << "Payment icon: " << payment_icon << llendl;
++		}
++
++		const LLUUID avatar_gone("db4592d5-c8a5-9336-019c-fcbd282d5f33");
++		const LLUUID avatar_new("33d4b23e-a29c-ac03-f7f6-c2fa197b13fe");
++		const LLUUID avatar_typing("6f083c3c-1e88-d184-6add-95402b3e108f");
++		/*<avatar_sound.tga value = "439836e2-29f5-c12f-71d4-aa59283296e1"/>
++		<flag_blue.tga value="e39cbfe7-c4e7-3bad-5e5f-958082d55046"/>
++		<flag_green.tga value="78952758-1bef-f968-d382-b39094f85aa1"/>
++		<flag_orange.tga value="c72ca7d9-42cd-02f1-ce32-ca1ea5d1c25d"/>
++		<flag_pink.tga value="a3419a89-b8d9-293c-693e-12982e574304"/>
++		<flag_purple.tga value="7982fbf8-457a-77ce-61e6-b3c7d9500d2f"/>
++		<flag_red.tga value="11ba32bf-44fe-666e-073b-00768785b4d0"/>
++		<flag_yellow.tga value="98a5a29e-e933-eeed-bdd9-4d461f557d34"/>*/
++		
++		ACTIVITY_TYPE activity = ent->getActivity();
++		icon = "";
++		switch( activity )
++		{
++			case ACTIVITY_NONE:
++				break;
++			case ACTIVITY_MOVING:
++				icon = "inv_item_animation.tga";
++				break;
++			case ACTIVITY_GESTURING:
++				icon = "inv_item_gesture.tga";
++				break;
++			case ACTIVITY_SOUND:
++				icon = "inv_item_sound.tga";
++				break;
++			case ACTIVITY_REZZING:
++				icon = "ff_edit_theirs.tga";
++				break;
++			case ACTIVITY_PARTICLES:
++				// TODO: Replace with something better
++				icon = "account_id_green.tga";
++				break;
++			case ACTIVITY_NEW:
++				icon = avatar_new.asString();
++				break;
++			case ACTIVITY_TYPING:
++				icon = avatar_typing.asString();
++				break;
++			case ACTIVITY_DEAD:
++				// TODO: Replace, icon is quite inappropiate
++				icon = avatar_gone.asString();
++				break;
++		}
++
++		element["columns"][LIST_ACTIVITY]["column"] = "activity";
++		element["columns"][LIST_ACTIVITY]["type"] = "text";
++
++		if (!icon.empty() )
++		{	
++			element["columns"][LIST_ACTIVITY]["type"] = "icon";
++			element["columns"][LIST_ACTIVITY]["value"] = icon;
++			//llinfos << "Activity icon: " << activity_icon << llendl;
++		}
++		
++		char tempentered[32];
++		F32 entered = ent->getEntryEnteredSeconds();
++		snprintf(tempentered, sizeof(tempentered), "%u", (unsigned int)(entered/60.0));
++		element["columns"][LIST_ENTERED]["column"] = "entered";
++		element["columns"][LIST_ENTERED]["type"] = "text";
++		element["columns"][LIST_ENTERED]["value"] = tempentered;
++		element["columns"][LIST_ENTERED]["color"] = getAvatarColor(ent, distance, CT_ENTERED).getValue();
++
++		// Add to list
++		mAvatarList->addElement(element, ADD_BOTTOM);
++
++		// Request data only if fetching avatar data is enabled
++		if ( fetch_data->getValue() && ent->mAvatarInfo.requestIfNeeded() )
++		{
++			sendAvatarPropertiesRequest(av_id);
++			llinfos << "Data for avatar " << ent->getName() << " didn't arrive yet, retrying" << llendl;
++		}
++
++		/*if ( ent->mTrustNetScore.requestIfNeeded() )
++		{
++			requestTrustNetScore(av_id, ent->getName(), "behavior");
++			llinfos << "Requesting TrustNet score for " << ent->getName() << llendl;
++		}*/
++		
++		//if ( db_enabled && ent->mMiscInfo.requestIfNeeded() )
++		//{
++		//	requestMiscInfo(av_id, ent->getName());
++		//	llinfos << "Requesting misc info for " << ent->getName() << llendl;
++		//}
++	}
++
++	// finish
++	mAvatarList->sort();
++	mAvatarList->selectMultiple(selected);
++	mAvatarList->setScrollPos(scrollpos);
++
++//	llinfos << "avatar list refresh: done" << llendl;
++
++}
++
++// static
++void LLFloaterAvatarList::onClickIM(void* userdata)
++{
++	//llinfos << "LLFloaterFriends::onClickIM()" << llendl;
++	LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
++
++	LLDynamicArray<LLUUID> ids = avlist->mAvatarList->getSelectedIDs();
++	if(ids.size() > 0)
++	{
++		if(ids.size() == 1)
++		{
++			// Single avatar
++			LLUUID agent_id = ids[0];
++
++			char buffer[MAX_STRING];
++			snprintf(buffer, MAX_STRING, "%s", avlist->mAvatars[agent_id].getName().c_str());
++			gIMMgr->setFloaterOpen(TRUE);
++			gIMMgr->addSession(
++				buffer,
++				IM_NOTHING_SPECIAL,
++				agent_id);
++		}
++		else
++		{
++			// Group IM
++			LLUUID session_id;
++			session_id.generate();
++			gIMMgr->setFloaterOpen(TRUE);
++			gIMMgr->addSession("Avatars Conference", IM_SESSION_CONFERENCE_START, ids[0], ids);
++		}
++	}
++}
++
++void LLFloaterAvatarList::onClickTrack(void *userdata)
++{
++	LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
++	
++ 	LLScrollListItem *item =   avlist->mAvatarList->getFirstSelected();
++	if (!item) return;
++
++	LLUUID agent_id = item->getUUID();
++
++	if ( avlist->mTracking && avlist->mTrackedAvatar == agent_id ) {
++		LLTracker::stopTracking(NULL);
++		avlist->mTracking = FALSE;
++	}
++	else
++	{
++		avlist->mTracking = TRUE;
++		avlist->mTrackByLocation = FALSE;
++		avlist->mTrackedAvatar = agent_id;
++		LLTracker::trackAvatar(agent_id, avlist->mAvatars[agent_id].getName());
++	}
++}
++
++void LLFloaterAvatarList::sendAvatarPropertiesRequest(LLUUID avid)
++{
++	
++
++	lldebugs << "LLPanelAvatar::sendAvatarPropertiesRequest()" << llendl; 
++	LLMessageSystem *msg = gMessageSystem;
++
++	msg->newMessageFast(_PREHASH_AvatarPropertiesRequest);
++	msg->nextBlockFast( _PREHASH_AgentData);
++	msg->addUUIDFast(   _PREHASH_AgentID, gAgent.getID() );
++	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
++	msg->addUUIDFast(   _PREHASH_AvatarID, avid);
++	gAgent.sendReliableMessage();
++
++	mAvatars[avid].mAvatarInfo.requestStarted();
++}
++
++// static
++void LLFloaterAvatarList::processAvatarPropertiesReply(LLMessageSystem *msg, void**)
++{
++
++	
++	LLFloaterAvatarList* self = NULL;
++	LLAvatarInfo avinfo;
++
++	BOOL	identified = FALSE;
++	BOOL	transacted = FALSE;
++
++	LLUUID	agent_id;	// your id
++	LLUUID	avatar_id;	// target of this panel
++	U32	flags = 0x0;
++	char	born_on[DB_BORN_BUF_SIZE];
++	S32	charter_member_size = 0;
++
++	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
++	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_id );
++
++	
++	self = gFloaterAvatarList;
++
++	// Verify that the avatar is in the list, if not, ignore.
++	if ( self->mAvatarList->getItemIndex(avatar_id) < 0 )
++	{
++		return;
++	}
++
++	LLAvatarListEntry *entry = &self->mAvatars[avatar_id];
++
++	msg->getStringFast(_PREHASH_PropertiesData, _PREHASH_BornOn, DB_BORN_BUF_SIZE, born_on);
++	msg->getU32Fast(_PREHASH_PropertiesData, _PREHASH_Flags, flags);
++
++	identified = (flags & AVATAR_IDENTIFIED);
++	transacted = (flags & AVATAR_TRANSACTED);
++
++	// What's this?
++	// Let's see if I understand correctly: CharterMember property is dual purpose:
++	// it either contains a number indicating an account type (usual value), or 
++	// it contains a string with a custom title. Probably that's where Philip Linden's
++	// "El Presidente" title comes from. Heh.
++	U8 caption_index = 0;
++	std::string caption_text;
++	charter_member_size = msg->getSize("PropertiesData", "CharterMember");
++
++	if(1 == charter_member_size)
++	{
++		msg->getBinaryData("PropertiesData", "CharterMember", &caption_index, 1);
++	}
++	else if(1 < charter_member_size)
++	{
++		char caption[MAX_STRING];
++		msg->getString("PropertiesData", "CharterMember", MAX_STRING, caption);
++
++		caption_text = caption;
++		entry->setAccountCustomTitle(caption_text);
++	}
++		
++
++	if(caption_text.empty())
++	{
++		
++		const enum ACCOUNT_TYPE ACCT_TYPE[] = {
++			ACCOUNT_RESIDENT,
++			ACCOUNT_TRIAL,
++			ACCOUNT_CHARTER_MEMBER,
++			ACCOUNT_EMPLOYEE
++		};
++
++		//enum ACCOUNT_TYPE acct =
++		avinfo.Account =  ACCT_TYPE[llclamp(caption_index, (U8)0, (U8)(sizeof(ACCT_TYPE)/sizeof(ACCT_TYPE[0])-1))];
++		//entry->setAccountType(acct);
++
++		
++		if ( avinfo.Account != ACCOUNT_EMPLOYEE )
++		{
++			if ( transacted )
++			{
++				avinfo.Payment = PAYMENT_USED;
++			}
++			else if ( identified )
++			{
++				avinfo.Payment = PAYMENT_ON_FILE;
++			}
++			else
++			{
++				avinfo.Payment = PAYMENT_NONE;
++			}
++		}
++		else
++		{
++			avinfo.Payment = PAYMENT_LINDEN;
++		}
++	}
++	
++	// Structure must be zeroed to have sane results, as we
++	// have an incomplete string for input
++	memset(&avinfo.BirthDate, 0, sizeof(avinfo.BirthDate));
++
++	int num_read = sscanf(born_on, "%d/%d/%d", &avinfo.BirthDate.tm_mon,
++	                                           &avinfo.BirthDate.tm_mday,
++	                                           &avinfo.BirthDate.tm_year);
++
++	if ( num_read == 3 && avinfo.BirthDate.tm_mon <= 12 )
++	{
++		avinfo.BirthDate.tm_year -= 1900;
++		avinfo.BirthDate.tm_mon--;
++	}
++	else
++	{
++		// Zero again to remove any partially read data
++		memset(&avinfo.BirthDate, 0, sizeof(avinfo.BirthDate));
++		llwarns << "Error parsing birth date: " << born_on << llendl;
++	}
++
++	entry->mAvatarInfo.setValue(avinfo);
++}
++
++void LLFloaterAvatarList::checkTrackingStatus()
++{
++
++	if ( mTracking && LLTracker::getTrackedPositionGlobal().isExactlyZero() )
++	{
++		// trying to track an avatar, but tracker stopped tracking		
++		if ( mAvatars.count( mTrackedAvatar ) > 0 && !mTrackByLocation )
++		{
++			llinfos << "Switching to location-based tracking" << llendl;
++			mTrackByLocation = TRUE;
++		}
++		else
++		{
++			// not found
++			llinfos << "Stopping tracking avatar, server-side didn't work, and not in list anymore." << llendl;
++			LLTracker::stopTracking(NULL);
++			mTracking = FALSE;
++		}
++	}
++
++	if ( mTracking && mTrackByLocation )
++	{
++		std::string name = mAvatars[mTrackedAvatar].getName();
++		std::string tooltip = "Tracking last known position";
++		name += " (near)";
++		LLTracker::trackLocation(mAvatars[mTrackedAvatar].getPosition(), name, tooltip);
++	}
++
++	//llinfos << "Tracking position: " << LLTracker::getTrackedPositionGlobal() << llendl;
++	
++}
++
++
++BOOL  LLFloaterAvatarList::avatarIsInList(LLUUID avatar)
++{
++	return ( mAvatars.count( avatar ) > 0 );
++}
++
++LLAvatarListEntry * LLFloaterAvatarList::getAvatarEntry(LLUUID avatar)
++{
++	if ( avatar.isNull() )
++	{
++		return NULL;
++	}
++
++	std::map<LLUUID, LLAvatarListEntry>::iterator iter;
++
++	iter = mAvatars.find(avatar);
++	if ( iter == mAvatars.end() )
++	{
++		return NULL;
++	}
++
++	return &iter->second;	
++	
++	//if ( mAvatars.count( avatar ) < 0 )
++	//{
++		//return NULL;
++	//}
++
++	//return &mAvatars[avatar];
++}
++
++void LLFloaterAvatarList::speakText(S32 channel, EChatType type, std::string text)
++{
++	LLMessageSystem* msg = gMessageSystem;
++
++	msg->newMessageFast(_PREHASH_ChatFromViewer);
++	msg->nextBlockFast(_PREHASH_AgentData);
++	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
++	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
++	msg->nextBlockFast(_PREHASH_ChatData);
++	msg->addStringFast(_PREHASH_Message, text);
++	msg->addU8Fast(_PREHASH_Type, type);
++	msg->addS32("Channel", channel);
++
++	gAgent.sendReliableMessage();
++
++	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT);
++}
++
++
++void LLFloaterAvatarList::requestTrustNetScore(LLUUID avatar, const std::string name, const std::string type)
++{
++	char *temp = new char[UUID_STR_LENGTH];
++	avatar.toString(temp);
++
++	std::string text = "GetScore|" + name + "|" + temp + "|" + type;
++	speakText(TRUSTNET_CHANNEL, CHAT_TYPE_WHISPER, text);
++}
++
++//static
++void LLFloaterAvatarList::replaceVars(std::string &str, LLUUID avatar, const std::string& name)
++{
++	char *temp = new char[UUID_STR_LENGTH];
++	avatar.toString(temp);
++
++	std::string vars[][2] = {
++		{"$NAME", name},
++		{"$KEY",  temp},
++	};
++
++	BOOL replaced = TRUE;
++
++	while( replaced )
++	{
++		replaced = FALSE;
++		for(U32 i=0;i<sizeof(vars)/sizeof(vars[0]);i++)
++		{
++			std::string::size_type pos = str.find(vars[i][0]);
++			if ( pos != std::string::npos )
++			{
++				str.replace(pos, vars[i][0].size(), vars[i][1]);
++				replaced = TRUE;
++			}
++		}
++	}
++
++}
++
++void LLFloaterAvatarList::requestMiscInfo(LLUUID avatar, const std::string name)
++{
++	//LLUUID   db_av_key;
++
++	//std::string message      = gSavedPerAccountSettings.getString("DBSendPattern");
++	//std::string db_av_name   = gSavedPerAccountSettings.getString("DBAvatarName");
++	//db_av_key.set(gSavedPerAccountSettings.getString("DBAvatarKey"));
++
++	
++	//llinfos << "Requesting info " << llendl;
++	//replaceVars(message, avatar, name);
++
++	//llinfos << "Request string: " << message << llendl;
++	//send_simple_im(db_av_key, message.c_str());
++ }
++
++//static
++BOOL LLFloaterAvatarList::handleIM(LLUUID from_id, const std::string message)
++{
++	LLUUID   db_av_key;
++	//db_av_key.set(gSavedPerAccountSettings.getString("DBAvatarKey"));
++
++	if ( db_av_key == from_id )
++	{
++		std::map<LLUUID, LLAvatarListEntry>::iterator iter;
++
++		for(iter = gFloaterAvatarList->mAvatars.begin(); iter != gFloaterAvatarList->mAvatars.end(); iter++)
++		{
++			LLAvatarListEntry *ent = &iter->second;
++		
++			// Check if the key, or the name are found in the reply.
++			// Name is only accepted if it's in the beginning of the message.
++			if ( message.find(ent->getID().asString()) != std::string::npos
++			     || message.find(ent->getName().c_str()) == 0 )
++			{
++				LLMiscDBInfo info;
++				info.data = message;
++
++				llinfos << "Database reply arrived for avatar " << ent->getName() << llendl;
++				ent->mMiscInfo.setValue(info);
++			}
++		}
++
++		return TRUE;
++	}
++	return FALSE;
++}
++
++//static
++void LLFloaterAvatarList::processTrustNetReply(char *reply)
++{
++	char *tokens[10];
++	char *tmp = &reply[0];
++	U32 count = 0;
++
++	llinfos << "TrustNet reply: " << reply << llendl;
++	
++
++	// Split into tokens
++	while( (NULL != (tmp = strtok(tmp, "|"))) && count < (sizeof(tokens)/sizeof(tokens[0])) )
++	{
++		tokens[count++] = tmp;
++		llinfos << "token: " << tmp << llendl;
++		tmp = NULL;
++	}
++
++	llinfos << "Got " << count << " tokens" << llendl;
++
++	if ( count >= 1 )
++	{
++		if (!strcmp(tokens[0], "Score") && count >= 4)
++		{
++			//format: key|type|score
++			LLUUID avatar(tokens[1]);
++			std::string type = tokens[2];
++			F32 score = (F32)strtod(tokens[3], NULL);
++			
++			LLAvatarListEntry *ent = gFloaterAvatarList->getAvatarEntry(avatar);
++			if ( ent != NULL )
++			{
++				LLAvListTrustNetScore s(type, score);
++				ent->mTrustNetScore.setValue(s);
++				llinfos << "Score arrived for avatar " << avatar << ": " << score << llendl;
++			}
++			else
++			{
++				llinfos << "Score arrived for avatar " << avatar << ", but it wasn't in the list anymore" << llendl;
++			}
++		}
++		else if (!strcmp(tokens[0], "WebAuthToken") && count >= 2)
++		{
++			std::string URL = LLWeb::escapeURL(llformat("http://trustnet.daleglass.net/?session=%s", tokens[1]));
++ 			LLWeb::loadURL(URL);
++		}
++		else if (!strcmp(tokens[0], "WebPassword") && count >= 2)
++		{
++			std::string password = tokens[1];
++			gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(password));
++		}
++		else
++		{
++			llwarns << "Unrecognized TrustNet reply " << tokens[0] << llendl;
++		}
++	}
++}
++
++void LLFloaterAvatarList::luskwoodCommand(std::string cmd)
++{
++	LLDynamicArray<LLUUID> ids = mAvatarList->getSelectedIDs();
++
++	for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
++	{
++		LLUUID avid = *itr;
++		LLAvatarListEntry *ent = getAvatarEntry(avid);
++		if ( ent != NULL )
++		{
++			//llinfos << "Would say: " << cmd << " " << ent->getName() << llendl;
++			// Use key got gokey, name for everything else
++			speakText(0, CHAT_TYPE_SHOUT, cmd + " " + ( cmd == "gokey" ? ent->getID().asString() :  ent->getName() ) );
++		}
++	}
++}
++
++//static
++void LLFloaterAvatarList::onClickMark(void *userdata)
++{
++	LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
++	LLDynamicArray<LLUUID> ids = avlist->mAvatarList->getSelectedIDs();
++
++	for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
++	{
++		LLUUID avid = *itr;
++		LLAvatarListEntry *ent = avlist->getAvatarEntry(avid);
++		if ( ent != NULL )
++		{
++			ent->toggleMark();
++		}
++	}
++}
++
++void LLFloaterAvatarList::handleLuskwoodDialog(S32 option, void* data)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
++	if ( 0 == option )
++	{
++		self->luskwoodCommand(self->mLuskwoodCommand);
++	}
++}
++
++void LLFloaterAvatarList::handleLuskwoodGohomerOffDialog(S32 option, void* data)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
++	if ( 0 == option )
++	{
++		self->speakText(0, CHAT_TYPE_SHOUT, "gohome off");
++	}
++}
++
++//static
++void LLFloaterAvatarList::onClickGohomerWarn(void *data)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
++
++	self->mLuskwoodCommand = "gowarn";
++	gViewerWindow->alertXml("LuskwoodGohomerWarn", handleLuskwoodDialog, self);
++
++}
++
++//static
++void LLFloaterAvatarList::onClickGohomerEject(void *data)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
++
++	self->mLuskwoodCommand = "goeject";
++	gViewerWindow->alertXml("LuskwoodGohomerEject", handleLuskwoodDialog, self);
++}
++
++//static
++void LLFloaterAvatarList::onClickGohomerSendAway(void *data)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
++
++	self->mLuskwoodCommand = "goaway";
++	gViewerWindow->alertXml("LuskwoodGohomerKeepAway", handleLuskwoodDialog, self);
++}
++
++//static
++void LLFloaterAvatarList::onClickGohomerSendHome(void *data)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
++
++	self->mLuskwoodCommand = "gohome";
++	gViewerWindow->alertXml("LuskwoodGohomerSendHome", handleLuskwoodDialog, self);
++}
++
++//static
++void LLFloaterAvatarList::onClickGohomerSendHomeByKey(void *data)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
++
++	self->mLuskwoodCommand = "gokey";
++	gViewerWindow->alertXml("LuskwoodGohomerSendHome", handleLuskwoodDialog, self);
++}
++
++
++//static
++void LLFloaterAvatarList::onClickGohomerOff(void *data)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
++
++	gViewerWindow->alertXml("LuskwoodGohomerOff", handleLuskwoodGohomerOffDialog, self);
++}
++
++LLColor4 LLFloaterAvatarList::getAvatarColor(LLAvatarListEntry *ent, F32 distance, e_coloring_type type)
++{
++ 	F32 r = 0.0f, g = 0.0f, b = 0.0f, a = 1.0f;
++
++	switch(type)
++	{
++		case CT_NONE:
++			return LLColor4::black;
++			break;
++		case CT_DISTANCE:
++			if ( distance <= 10.0f )
++			{
++				// whisper range
++				g = 0.7f - ( distance / 20.0f );
++			}
++			else if ( distance > 10.0f && distance <= 20.0f )
++			{
++				// talk range
++				g = 0.7f - ( (distance - 10.0f) / 20.0f );
++				b = g;
++			}
++			else if ( distance > 20.0f && distance <= 96.0f )
++			{
++				// shout range
++				r = 0.7f - ( (distance - 20.0f) / 192.0f );
++				b = r;
++			}
++			else
++			{
++				// unreachable by chat
++				r = 1.0;
++			}
++			break;
++		case CT_AGE:
++			if ( ent->mAvatarInfo.getStatus() == DATA_RETRIEVED )
++			{
++				S32 age = ent->mAvatarInfo.getValue().getAge();
++				if ( age < 14 )
++				{
++					r = 0.7f - ( age / 28 );
++				}
++				else if ( age > 14 && age <= 30 )
++				{
++					r = 0.7f - ( (age-14) / 32 );
++					g = r;
++				}
++				else if ( age > 30 && age < 90 )
++				{
++					g = 0.7f - ( (age-30) / 120 );
++				}
++				else
++				{
++					b = 1.0f;
++				}
++			}
++			break;
++		case CT_SCORE:
++			if ( ent->mTrustNetScore.getStatus() == DATA_RETRIEVED )
++			{
++				F32 score = ent->mTrustNetScore.getValue().Score;
++
++				if ( score == 0.0 )
++				{
++					b = 1.0f;
++				}
++				else if ( score == 10.0f )
++				{
++					g = 1.0f;
++				}
++				else if ( score == -10.0f )
++				{
++					r = 1.0f;
++				}
++				else if ( score > 0.0f )
++				{
++					g = 0.2f + ( score / 20.0f );
++				}
++				else if ( score < 0.0f )
++				{ 
++					r = 0.2f + ( score / 20.0f );
++				}
++			}
++			break;
++		case CT_PAYMENT:
++			break;
++		case CT_ENTERED:
++			F32 entered = ent->getEntryEnteredSeconds();
++			if (distance <= 20.0f)
++			{
++				if ( entered <= ( 5.0f * 60.0f ) )
++				{
++					r = 0.7f - ( entered / ( 4.0f * 5.0f * 60.0f ) );
++					b = 1.0f - ( ( ( 5.0f * 60.0f ) - entered) / ( 5.0f * 60.0f ) );
++				}
++				else
++				{
++					b = 1.0f;
++				}
++			}
++			else
++			{
++				r = g = b = 0.5f;
++			}
++			break;
++	}
++
++	return LLColor4(r,g,b,a);
++}
++
++void LLFloaterAvatarList::onDoubleClick(void *userdata)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++ 	LLScrollListItem *item =   self->mAvatarList->getFirstSelected();
++	LLUUID agent_id = item->getUUID();
++	LLAvatarListEntry *ent = 0;
++
++	if ( self->mAvatars.count( agent_id ) )
++	{
++		ent = &self->mAvatars[ agent_id ];
++	}
++
++	if ( ent && ent->getIsCoarse() )
++	{
++		// nothing to look at, manipulate camera directly
++		LLQuaternion rot;
++		
++		LLMatrix3 mat(rot);
++
++		LLVector3 pos( ent->getPosition() );
++
++		LLViewerCamera::getInstance()->setView(1.0);
++		LLViewerCamera::getInstance()->setOrigin( pos );
++		LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]);
++		LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]);
++		LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]);	}
++	else
++	{
++		gAgent.lookAtObject(agent_id, CAMERA_POSITION_OBJECT);
++	}
++}
++
++void LLFloaterAvatarList::removeFocusFromAll()
++{
++	std::map<LLUUID, LLAvatarListEntry>::iterator iter;
++
++	for(iter = mAvatars.begin(); iter != mAvatars.end(); iter++)
++	{
++		LLAvatarListEntry *ent = &iter->second;
++		ent->setFocus(FALSE);
++	}
++}
++
++void LLFloaterAvatarList::focusOnPrev(BOOL marked_only)
++{
++	std::map<LLUUID, LLAvatarListEntry>::iterator iter;
++	LLAvatarListEntry *prev = NULL;
++	LLAvatarListEntry *ent;
++
++	if ( mAvatars.size() == 0 )
++	{
++		return;
++	}
++
++	for(iter = mAvatars.begin(); iter != mAvatars.end(); iter++)
++	{
++		ent = &iter->second;
++
++		if ( ent->isDead() )
++			continue;
++
++		if ( (ent->getID() == mFocusedAvatar) && (prev != NULL)  )
++		{
++			removeFocusFromAll();
++			prev->setFocus(TRUE);
++			mFocusedAvatar = prev->getID();
++			gAgent.lookAtObject(mFocusedAvatar, CAMERA_POSITION_OBJECT);
++			return;
++		}
++
++		if ( (!marked_only) || ent->isMarked() )
++		{
++			prev = ent;
++		}
++	}
++
++	if (prev != NULL && ((!marked_only) || prev->isMarked()) )
++	{
++		removeFocusFromAll();
++		prev->setFocus(TRUE);
++		mFocusedAvatar = prev->getID();
++		gAgent.lookAtObject(mFocusedAvatar, CAMERA_POSITION_OBJECT);
++	}
++}
++
++void LLFloaterAvatarList::focusOnNext(BOOL marked_only)
++{
++
++	
++	std::map<LLUUID, LLAvatarListEntry>::iterator iter;
++	BOOL found = FALSE;
++	LLAvatarListEntry *first = NULL;
++	LLAvatarListEntry *ent;
++
++	if ( mAvatars.size() == 0 )
++	{
++		return;
++	}
++
++	for(iter = mAvatars.begin(); iter != mAvatars.end(); iter++)
++	{
++		ent = &iter->second;
++
++		if ( ent->isDead() )
++			continue;
++
++		if ( NULL == first && ((!marked_only) || ent->isMarked()))
++		{
++			first = ent;
++		}
++
++		if ( found && ((!marked_only) || ent->isMarked()) )
++		{
++			removeFocusFromAll();
++			ent->setFocus(TRUE);
++			mFocusedAvatar = ent->getID();
++			gAgent.lookAtObject(mFocusedAvatar, CAMERA_POSITION_OBJECT);
++			return;
++		}
++
++		if ( ent->getID() == mFocusedAvatar )
++		{
++			found = TRUE;
++		} 
++	}
++
++	if (first != NULL && ((!marked_only) || first->isMarked()))
++	{
++		removeFocusFromAll();
++		first->setFocus(TRUE);
++		mFocusedAvatar = first->getID();
++		gAgent.lookAtObject(mFocusedAvatar, CAMERA_POSITION_OBJECT);
++	}
++}
++//static
++void LLFloaterAvatarList::onClickPrevInList(void *userdata)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++	self->focusOnPrev(FALSE);
++}
++
++//static
++void LLFloaterAvatarList::onClickNextInList(void *userdata)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++	self->focusOnNext(FALSE);
++}
++
++//static
++void LLFloaterAvatarList::onClickPrevMarked(void *userdata)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++	self->focusOnPrev(TRUE);
++}
++
++//static
++void LLFloaterAvatarList::onClickNextMarked(void *userdata)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++	self->focusOnNext(TRUE);
++}
++
++//static
++void LLFloaterAvatarList::onClickTrustNetRate(void *userdata)
++{
++	// LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++	llinfos << "Ratings not implemented yet" << llendl;
++}
++
++//static
++void LLFloaterAvatarList::onClickTrustNetExplain(void *userdata)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++	LLScrollListItem *item =   self->mAvatarList->getFirstSelected();
++
++	if ( item != NULL )
++	{
++		LLAvatarListEntry *ent = self->getAvatarEntry(item->getUUID());
++		self->speakText(TRUSTNET_CHANNEL, CHAT_TYPE_WHISPER, "Explain|" + ent->getName() + "|" + ent->getID().asString());
++	}
++}
++
++//static
++void LLFloaterAvatarList::onClickTrustNetWebsite(void *userdata)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++
++	self->speakText(TRUSTNET_CHANNEL, CHAT_TYPE_WHISPER, "GetWebAuthToken");
++}
++
++//static
++void LLFloaterAvatarList::onClickTrustNetGetPassword(void *userdata)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++
++	self->speakText(TRUSTNET_CHANNEL, CHAT_TYPE_WHISPER, "GetWebPassword");
++}
++
++//static
++void LLFloaterAvatarList::onClickTrustNetRenew(void *userdata)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++	self->speakText(TRUSTNET_CHANNEL, CHAT_TYPE_WHISPER, "RenewSubscription");
++}
++
++//static
++void LLFloaterAvatarList::onClickGetKey(void *userdata)
++{
++	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
++ 	LLScrollListItem *item = self->mAvatarList->getFirstSelected();
++
++	if ( NULL == item ) return;
++
++	LLUUID agent_id = item->getUUID();
++
++	char buffer[UUID_STR_LENGTH];		/*Flawfinder: ignore*/
++	agent_id.toString(buffer);
++
++	gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
++}
++
++
++static void send_freeze(const LLUUID& avatar_id, bool freeze)
++{
++	U32 flags = 0x0;
++	if (!freeze)
++	{
++		// unfreeze
++		flags |= 0x1;
++	}
++
++	LLMessageSystem* msg = gMessageSystem;
++	LLViewerObject* avatar = gObjectList.findObject(avatar_id);
++
++	if (avatar)
++	{
++		msg->newMessage("FreezeUser");
++		msg->nextBlock("AgentData");
++		msg->addUUID("AgentID", gAgent.getID());
++		msg->addUUID("SessionID", gAgent.getSessionID());
++		msg->nextBlock("Data");
++		msg->addUUID("TargetID", avatar_id );
++		msg->addU32("Flags", flags );
++		msg->sendReliable( avatar->getRegion()->getHost() );
++	}
++}
++
++static void send_eject(const LLUUID& avatar_id, bool ban)
++{	
++	LLMessageSystem* msg = gMessageSystem;
++	LLViewerObject* avatar = gObjectList.findObject(avatar_id);
++
++	if (avatar)
++	{
++		U32 flags = 0x0;
++		if ( ban )
++		{
++			// eject and add to ban list
++			flags |= 0x1;
++		}
++
++		msg->newMessage("EjectUser");
++		msg->nextBlock("AgentData");
++		msg->addUUID("AgentID", gAgent.getID() );
++		msg->addUUID("SessionID", gAgent.getSessionID() );
++		msg->nextBlock("Data");
++		msg->addUUID("TargetID", avatar_id );
++		msg->addU32("Flags", flags );
++		msg->sendReliable( avatar->getRegion()->getHost() );
++	}
++}
++
++static void send_estate_message(
++	const char* request,
++	const LLUUID &target)
++{
++
++	LLMessageSystem* msg = gMessageSystem;
++	LLUUID invoice;
++
++	// This seems to provide an ID so that the sim can say which request it's
++	// replying to. I think this can be ignored for now.
++	invoice.generate();
++
++	llinfos << "Sending estate request '" << request << "'" << llendl;
++	msg->newMessage("EstateOwnerMessage");
++	msg->nextBlockFast(_PREHASH_AgentData);
++	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
++	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
++	msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
++	msg->nextBlock("MethodData");
++	msg->addString("Method", request);
++	msg->addUUID("Invoice", invoice);
++
++	// Agent id
++	msg->nextBlock("ParamList");
++	msg->addString("Parameter", gAgent.getID().asString().c_str());
++
++	// Target
++	msg->nextBlock("ParamList");
++	msg->addString("Parameter", target.asString().c_str());
++
++	msg->sendReliable(gAgent.getRegion()->getHost());
++}
++
++static void send_estate_ban(const LLUUID& agent)
++{
++	LLUUID invoice;
++	U32 flags = ESTATE_ACCESS_BANNED_AGENT_ADD;
++
++	invoice.generate();
++
++	LLMessageSystem* msg = gMessageSystem;
++	msg->newMessage("EstateOwnerMessage");
++	msg->nextBlockFast(_PREHASH_AgentData);
++	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
++	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
++	msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
++
++	msg->nextBlock("MethodData");
++	msg->addString("Method", "estateaccessdelta");
++	msg->addUUID("Invoice", invoice);
++
++	char buf[MAX_STRING];		/* Flawfinder: ignore*/
++	gAgent.getID().toString(buf);
++	msg->nextBlock("ParamList");
++	msg->addString("Parameter", buf);
++
++	snprintf(buf, MAX_STRING, "%u", flags);			/* Flawfinder: ignore */
++	msg->nextBlock("ParamList");
++	msg->addString("Parameter", buf);
++
++	agent.toString(buf);
++	msg->nextBlock("ParamList");
++	msg->addString("Parameter", buf);
++
++	gAgent.sendReliableMessage();
++}
++
++static void cmd_freeze(const LLUUID& avatar, const std::string &name)      { send_freeze(avatar, true); }
++static void cmd_unfreeze(const LLUUID& avatar, const std::string &name)    { send_freeze(avatar, false); }
++static void cmd_eject(const LLUUID& avatar, const std::string &name)       { send_eject(avatar, false); }
++static void cmd_ban(const LLUUID& avatar, const std::string &name)         { send_eject(avatar, true); }
++static void cmd_profile(const LLUUID& avatar, const std::string &name)     { LLFloaterAvatarInfo::showFromDirectory(avatar); }
++static void cmd_mute(const LLUUID&avatar, const std::string &name)         { LLMuteList::getInstance()->add(LLMute(avatar, name, LLMute::AGENT)); }
++static void cmd_unmute(const LLUUID&avatar, const std::string &name)       { LLMuteList::getInstance()->remove(LLMute(avatar, name, LLMute::AGENT)); }
++static void cmd_estate_eject(const LLUUID &avatar, const std::string &name){ send_estate_message("teleporthomeuser", avatar); }
++static void cmd_estate_ban(const LLUUID &avatar, const std::string &name)
++{
++	send_estate_message("teleporthomeuser", avatar); // Kick first, just to be sure
++	send_estate_ban(avatar);
++}
++
++void LLFloaterAvatarList::doCommand(void (*func)(const LLUUID &avatar, const std::string &name))
++{
++	LLDynamicArray<LLUUID> ids = mAvatarList->getSelectedIDs();
++
++	for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
++	{
++		LLUUID avid = *itr;
++		LLAvatarListEntry *ent = getAvatarEntry(avid);
++		if ( ent != NULL )
++		{
++			llinfos << "Executing command on " << ent->getName() << llendl;
++			func(avid, ent->getName());
++		}
++	}
++}
++
++std::string LLFloaterAvatarList::getSelectedNames(const std::string& separator)
++{
++	std::string ret = "";
++	
++	LLDynamicArray<LLUUID> ids = mAvatarList->getSelectedIDs();
++	for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
++	{
++		LLUUID avid = *itr;
++		LLAvatarListEntry *ent = getAvatarEntry(avid);
++		if ( ent != NULL )
++		{
++			if (!ret.empty()) ret += separator;
++			ret += ent->getName();
++		}
++	}
++
++	return ret;
++}
++
++//static 
++void LLFloaterAvatarList::callbackFreeze(S32 option, void *userdata) { 
++	LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
++
++	if ( option == 0 )
++	{
++		avlist->doCommand(cmd_freeze);
++	}
++	else if ( option == 1 )
++	{
++		avlist->doCommand(cmd_unfreeze);
++	}
++}
++
++//static 
++void LLFloaterAvatarList::callbackEject(S32 option, void *userdata) {
++	LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
++ 
++	if ( option == 0 )
++	{
++		avlist->doCommand(cmd_eject);
++	}
++	else if ( option == 1 )
++	{
++		avlist->doCommand(cmd_ban);
++	}
++}
++
++//static 
++void LLFloaterAvatarList::callbackMute(S32 option, void *userdata) {
++	LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
++
++	if ( option == 0 )
++	{
++		avlist->doCommand(cmd_mute);
++	} 
++	else if ( option == 1 )
++	{
++		avlist->doCommand(cmd_unmute);
++	}
++}
++
++//static 
++void LLFloaterAvatarList::callbackEjectFromEstate(S32 option, void *userdata) {
++	LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
++
++	if ( option == 0 )
++	{
++		avlist->doCommand(cmd_estate_eject);
++	} 
++	else if ( option == 1 )
++	{
++		avlist->doCommand(cmd_estate_ban);
++	}
++}
++
++//static
++void LLFloaterAvatarList::onClickFreeze(void *userdata)
++{
++	LLStringUtil::format_map_t args;
++	args["[NAMES]"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames();
++	gViewerWindow->alertXml("AvatarListFreezeAvatars", args, callbackFreeze, userdata);
++}
++
++//static
++void LLFloaterAvatarList::onClickEject(void *userdata)
++{
++	LLStringUtil::format_map_t args;
++	args["[NAMES]"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames();
++	gViewerWindow->alertXml("AvatarListEjectAvatars", args, callbackEject, userdata);
++}
++
++//static
++void LLFloaterAvatarList::onClickMute(void *userdata)
++{
++	LLStringUtil::format_map_t args;
++	args["[NAMES]"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames();
++	gViewerWindow->alertXml("AvatarListMuteAvatars", args, callbackMute, userdata);
++}
++
++//static
++void LLFloaterAvatarList::onClickEjectFromEstate(void *userdata)
++{
++	LLStringUtil::format_map_t args;
++	args["[NAMES]"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames();
++	gViewerWindow->alertXml("AvatarListEjectAvatarsFromEstate", args, callbackEjectFromEstate, userdata);
++}
++
++
++
++//static
++void LLFloaterAvatarList::onClickAR(void *userdata)
++{
++	LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
++	LLDynamicArray<LLUUID> ids = avlist->mAvatarList->getSelectedIDs();
++
++	for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
++	{
++		LLUUID avid = *itr;
++		llinfos << "Adding " << avid << " to AR queue" << llendl;
++		avlist->mARQueue.push( avid );
++	}
++}
++
++// static
++void LLFloaterAvatarList::onClickProfile(void* userdata)
++{
++	LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
++	avlist->doCommand(cmd_profile);
++}
++
++//static
++void LLFloaterAvatarList::onClickTeleport(void* userdata)
++{
++	LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
++ 	LLScrollListItem *item =   avlist->mAvatarList->getFirstSelected();
++
++	if ( item )
++	{
++		LLUUID agent_id = item->getUUID();
++		LLAvatarListEntry *ent = avlist->getAvatarEntry(agent_id);
++		
++		if ( ent )
++		{
++			llinfos << "Trying to teleport to " << ent->getName() << " at " << ent->getPosition() << llendl;
++			gAgent.teleportViaLocation( ent->getPosition() );
++		}
++	}
++}
++
++
++void LLFloaterAvatarList::renderDebugBeacons()
++{
++	LLFastTimer t(LLFastTimer::FTM_TEMP1);
++	std::map<LLUUID, LLAvatarListEntry>::iterator iter;
++	for(iter = mAvatars.begin(); iter != mAvatars.end(); ++iter)
++	{
++		LLAvatarListEntry entry = iter->second;
++		if ( entry.isDead() )
++		{ // remove HUD Object if it exists
++			if ( mHudObjectMap.count(entry.getID()) )
++			{
++				mHudObjectMap[entry.getID()]->markDead();
++				mHudObjectMap.erase(entry.getID());
++			}
++			continue;
++		}
++
++		std::string name = entry.getName();
++		LLVector3d avpos = entry.getPosition();
++		LLVector3d mypos = gAgent.getPositionGlobal();
++		LLVector3d delta = avpos - mypos;
++		F32 distance = (F32)delta.magVec();
++		
++		std::string info = llformat( "%s %.02fm", name.c_str(), distance );
++		LLVector3 agentpos = gAgent.getPosAgentFromGlobal( avpos );
++
++		// roll our own HUD text since the debug beacons are rendered too late (after HUD update)
++		if (mHudObjectMap.count(entry.getID()) == 0)
++		{
++			mHudObjectMap[entry.getID()] = LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
++		}
++		LLHUDText* hud_textp = (LLHUDText *)mHudObjectMap[entry.getID()].get(); // :-/
++		
++		hud_textp->setZCompare(FALSE);
++		hud_textp->setString(utf8str_to_wstring(info));
++		hud_textp->setColor(LLColor4::white);
++		hud_textp->setPositionAgent(agentpos);
++		hud_textp->setUseBubble(TRUE);
++		hud_textp->setMass(10.f);
++		hud_textp->setDoFade(FALSE);
++		//std::string posinfo = llformat("%f %f %f", agentpos[0], agentpos[1], agentpos[2]);
++		//hud_textp->setLabel(posinfo);
++
++		gObjectList.addDebugBeacon( agentpos, "", LLColor4(0.0f, 0.0f, 1.f, 0.5f), LLColor4::white, gSavedSettings.getS32("DebugBeaconLineWidth") );
++	}	
++}
++
++bool LLFloaterAvatarList::sRenderAvatarBeacons = true;
++
+diff --git a/indra/newview/llfloateravatarlist.h b/indra/newview/llfloateravatarlist.h
+new file mode 100644
+index 0000000..78df867
+--- /dev/null
++++ b/indra/newview/llfloateravatarlist.h
+@@ -0,0 +1,868 @@
++//
++// C++ Interface: llfloateravatarlist
++//
++// Description: 
++//
++//
++// Author: Dale Glass <dale at daleglass.net>, (C) 2007
++//
++// Copyright: See COPYING file that comes with this distribution
++//
++//
++#include "llfloater.h"
++#include "llfloaterreporter.h"
++#include "lluuid.h"
++#include "lltimer.h"
++#include "llchat.h"
++#include "llappviewer.h"
++#include "llscrolllistctrl.h"
++#include "llhudobject.h"
++
++#include <time.h>
++#include <map>
++
++class LLFloaterAvatarList;
++
++/**
++ * @brief Account type
++ */
++enum ACCOUNT_TYPE
++{
++	ACCOUNT_RESIDENT,         /** Normal resident */
++	ACCOUNT_TRIAL,            /** Trial account */
++	ACCOUNT_CHARTER_MEMBER,   /** Lifetime account obtained during beta */
++	ACCOUNT_EMPLOYEE,         /** Linden Lab employee */
++	ACCOUNT_CUSTOM            /** Custom account title specified. Seems to apply to Philip Linden */
++};
++
++/**
++ * @brief Payment data
++ */
++enum PAYMENT_TYPE
++{
++	PAYMENT_NONE,             /** No payment data on file */
++	PAYMENT_ON_FILE,          /** Payment data filled, but not used */
++	PAYMENT_USED,             /** Payment data used */
++	PAYMENT_LINDEN            /** Payment info doesn't apply (Linden, etc) */
++};
++
++
++/**
++ * @brief Activity
++ *
++ * This enum is ordered by priority, higher values have higher priority.
++ * Since we only have one column to show activity, priority decides what
++ * to show in case of conflict.
++ */
++enum ACTIVITY_TYPE
++{
++	ACTIVITY_NONE,           /** Avatar not doing anything */ 
++	ACTIVITY_MOVING,         /** Changing position */
++	ACTIVITY_GESTURING,	 /** Playing a gesture */
++	ACTIVITY_SOUND,          /** Playing a sound */
++	ACTIVITY_REZZING,        /** Rezzing objects */
++	ACTIVITY_PARTICLES,      /** Creating particles */
++	ACTIVITY_TYPING,         /** Typing */
++	ACTIVITY_NEW,            /** Avatar just appeared */
++	ACTIVITY_DEAD            /** Avatar isn't around anymore, and will be removed soon from the list */
++};
++
++enum DATA_STATUS
++{
++	DATA_UNKNOWN,
++	DATA_REQUESTING,
++	DATA_ERROR,
++	DATA_RETRIEVED
++};
++
++/**
++ * @brief How to color the user list
++ */
++enum e_coloring_type
++{
++	CT_NONE,
++	CT_DISTANCE,
++	CT_AGE,
++	CT_SCORE,
++	CT_PAYMENT,
++	CT_ENTERED
++};
++
++/**
++ * @brief Template class for a piece of data that must be retrieved
++ *
++ * This class handles the storage, retries and delays required to obtain a piece
++ * of data..
++ */
++template <class T> 
++class LLAvatarListDatum
++{
++public:
++	LLAvatarListDatum()
++	{
++		mMaxPending = 32;
++
++		mRetryDelay = 0.0f;
++		mRequestDelay = 1.0f;
++		mFirstRequestTimeout = 16.0f;
++		mMaxRequestTimeout = 8192.0f;
++
++		mRequestTimer.start();
++		mRequestDelayTimer.start();
++		mStatus = DATA_UNKNOWN;
++		
++	}
++
++	/**
++	 * @brief Determines whether a data re-request is needed
++	 * @returns TRUE if a re-request is needed
++	 *
++	 * This function takes the decision based on whether the data has
++	 * been already retrieved, the last data request was long enough ago,
++	 * and the request rate being low enough.
++	 *
++	 * A FALSE return value doesn't mean that everything is OK, only that
++	 * a retry shouldn't be made at this time.
++	 */
++	BOOL retryNeeded()
++	{
++		switch(mStatus)
++		{
++			case DATA_UNKNOWN:
++			case DATA_REQUESTING:
++			case DATA_ERROR:
++				// Don't request too many at once
++				if ( mPending >= mMaxPending )
++				{
++					return FALSE;
++				}
++
++				// Don't re-request if the requests would be made too fast
++				if ( mRequestDelayTimer.getElapsedTimeF32() < mRequestDelay )
++				{
++					return FALSE;
++				}
++
++				// Re-request if retry timeout was reached
++				return ( mRequestTimer.getElapsedTimeF32() > mRetryDelay );
++			case DATA_RETRIEVED:
++				return FALSE;
++		}
++
++		return FALSE;
++	}
++
++	/**
++	 * @brief Notifies the object that a request was started
++	 */
++	void requestStarted()
++	{
++
++		if ( mStatus != DATA_REQUESTING )
++		{
++			mPending++;
++			//llinfos << "Pe
++		}
++
++		mStatus = DATA_REQUESTING;
++
++		if ( mRetryDelay == 0 )
++		{
++			mRetryDelay = mFirstRequestTimeout;
++		}
++		else
++		{
++			if ( mRetryDelay < mMaxRequestTimeout )
++			{
++				mRetryDelay *= 2;
++			}
++		}
++
++		mRequestTimer.start();
++		mRequestDelayTimer.start();
++	}
++
++	/**
++	 * @brief retryNeeded and requestStarted combined
++	 * @returns TRUE if a re-request is needed
++	 */
++	BOOL requestIfNeeded()
++	{
++		BOOL ret = retryNeeded();
++		if ( ret )
++		{
++			requestStarted();
++		}
++
++		return ret;
++	}
++
++	/**
++	 * @brief Returns the request status
++	 */
++	DATA_STATUS getStatus()
++	{
++		if ( mStatus == DATA_REQUESTING 
++		     && mRequestTimer.getElapsedTimeF32() > mRetryDelay )
++		{
++			mStatus = DATA_ERROR;
++
++			// Consider this request failed, so the slot is free.
++			mPending--;
++		}
++
++		return mStatus;
++	}
++
++	T& getValue()
++	{
++		return mValue;
++	}
++
++	void setValue(T val)
++	{
++		if ( mStatus != DATA_RETRIEVED )
++		{
++			mPending--;
++		}
++
++		mValue = val;
++		mStatus = DATA_RETRIEVED;
++	}
++
++	void setRequestDelay(F32 delay)
++	{
++		mRequestDelay = delay;
++	}
++
++	void setMaxPending(U32 count)
++	{
++		mMaxPending = count;
++	}
++private:
++	friend class LLFloaterAvatarList;
++	T mValue;
++
++	DATA_STATUS mStatus;
++
++	
++	/**
++	 * @brief How long to wait before trying to re-request the data
++	 */
++	F32 mRetryDelay;
++
++	/**
++	 * @brief How long to wait on the first attempt to get data
++	 */
++	F32 mFirstRequestTimeout;
++
++	/**
++	 * @brief Maximum delay between retries
++	 *
++	 * On failure, timeout gets doubled until it reaches this value
++	 */
++	F32 mMaxRequestTimeout;
++
++	/**
++	 * @brief Timer for the current request
++	 */
++	LLTimer mRequestTimer;
++
++
++
++	/**
++	 * @brief Timer used to separate requests, to avoid flooding the server
++	 */
++	static LLTimer mRequestDelayTimer;
++
++	/**
++	 * @brief Amount of pending requests
++	 */
++	static U32 mPending;
++
++
++	/**
++	 * @brief Time between requests of the same type
++	 */
++	F32 mRequestDelay;
++
++	/**
++	 * @brief Maximum amount of pending requests
++	 */
++	U32 mMaxPending;
++};
++
++template <class T> LLTimer LLAvatarListDatum<T>::mRequestDelayTimer;
++template <class T> U32 LLAvatarListDatum<T>::mPending = 0;
++
++//template <class T> F32 LLAvatarListDatum<T>::mRequestDelay;
++
++
++
++/**
++ * @brief A TrustNet score
++ */
++struct LLAvListTrustNetScore
++{
++	F32 Score;
++	std::string Type;
++
++	LLAvListTrustNetScore(std::string type = "<uninitialized>", F32 score = 0.0f);
++};
++
++/**
++ * @brief Avatar payment information
++ */
++struct LLAvatarInfo
++{
++	PAYMENT_TYPE Payment;
++	ACCOUNT_TYPE Account;
++	struct tm    BirthDate;
++
++	LLAvatarInfo();
++	LLAvatarInfo(PAYMENT_TYPE payment, ACCOUNT_TYPE account, struct tm birth);
++	S32 getAge();
++};
++
++/**
++ * @brief Misc data about the avatar
++ * This class holds replies from third party databases. There's no fixed format,
++ * and interpretation is left to the end user.
++ */
++struct LLMiscDBInfo
++{
++	std::string data;
++
++	LLMiscDBInfo(std::string d)
++	{
++		data = d;
++	}
++
++	LLMiscDBInfo()
++	{
++		data = "";
++	}
++};
++
++
++/**
++ * @brief This class is used to hold data about avatars.
++ * We cache data about avatars to avoid repeating requests in this class.
++ * Instances are kept in a map<LLAvatarListEntry>. We keep track of the
++ * frame where the avatar was last seen. Avatars that are old enough are
++ * not added to the visible list, but still kept around to cache the account
++ * info data (like the birth date and the payment data)
++ */
++class LLAvatarListEntry {
++public:
++
++
++	/**
++	 * @brief Initializes a list entry
++	 * @param id Avatar's key
++	 * @param name Avatar's name
++	 * @param position Avatar's current position
++	 * @param isLinden TRUE if the avatar is a Linden
++	 * @param isCoarse TRUE if the avatar is only in the coarse location list
++	 * @param regionname if the region is not the same as the current agent region, else empty string
++	 */
++	LLAvatarListEntry(const LLUUID& id = LLUUID::null, const std::string &name = "", const LLVector3d &position = LLVector3d::zero, BOOL isLinden = FALSE, BOOL isCoarse = FALSE, std::string regionname = std::string() ) :
++		mID(id), mName(name), mPosition(position), mMarked(FALSE), mFocused(FALSE), mIsLinden(isLinden), mIsCoarse(isCoarse), mRegionName(regionname), mActivityType(ACTIVITY_NEW), mAccountTitle(""),
++		mUpdateTimer(), mActivityTimer(), mFrame(0)
++	{
++		mTrustNetScore.setRequestDelay(0.1f);
++		mTrustNetScore.setMaxPending(8);
++		mFrame = gFrameCount;
++		mEnteredTimer.start();
++	}
++
++	/**
++	 * Update world position.
++	 * Affects age.
++	 */	
++	void setPosition(LLVector3d position);
++
++	LLVector3d getPosition();
++
++	/**
++	 * @brief Returns the age of this entry in frames
++	 *
++	 * This is only used for determining whether the avatar is still around.
++	 * @see getEntryAgeSeconds
++	 */
++	U32 getEntryAgeFrames();
++
++	/**
++	 * @brief Returns the age of this entry in seconds
++	 */
++	F32 getEntryAgeSeconds();
++
++	/**
++	 * @brief Returns time when avatar entered the list
++	 */
++	F32 getEntryEnteredSeconds();
++
++	/**
++	 * @brief Returns the name of the avatar
++	 */
++	std::string getName();
++
++	void setName(std::string name);
++
++	LLUUID getID();
++
++	void setID(LLUUID id);
++
++	/**
++	 * @brief Whether the avatar is a Linden
++	 */
++	BOOL getIsLinden();
++
++	/**
++	 * @brief whether the avatar entry was taken from the coarse location update
++	 */
++	BOOL getIsCoarse() { return mIsCoarse; }
++
++	/**
++	 * @brief returns the agents region name or "" if same as main agent
++	 */
++	std::string &getRegionName() { return mRegionName; }
++
++	/**
++	 * @brief returns true if agent is on same region
++	 */
++	BOOL getIsSameRegion() { return mRegionName.empty(); }
++
++	/**
++	 * @brief returns reference to the HUDObject-pointer for this avatar if any
++	 */
++	LLPointer<LLHUDObject> &getHudObject() { return mHudObject; }
++
++	/**
++	 * @brief Sets a custom title for the account
++	 * @note Changes account type to ACCOUNT_CUSTOM
++	 */
++	void setAccountCustomTitle(std::string &title);
++
++	/**
++	 * @brief Gets the custom title for the account
++	 */
++	std::string getAccountCustomTitle();
++
++	/**
++	 * @brief Sets the activity type for this avatar
++	 *
++	 * Has no effect if the specified type is lower priority than the
++	 * current one.
++	 */
++	void setActivity(ACTIVITY_TYPE activity);
++
++	/**
++	 * @brief Returns the activity type
++	 */
++	ACTIVITY_TYPE getActivity();
++
++	/**
++	 * @brief Sets the 'focus' status on this entry (camera focused on this avatar)
++	 */
++	void setFocus(BOOL value) { mFocused = value; }
++
++	BOOL isFocused() { return mFocused; }
++
++
++	BOOL isMarked();
++
++	/**
++	 * @brief Returns whether the item is dead and shouldn't appear in the list
++	 * @returns TRUE if dead
++	 */
++	BOOL isDead();
++
++	void toggleMark();
++private:
++	friend class LLFloaterAvatarList;
++
++	LLUUID mID;
++	std::string mName;
++	LLVector3d mPosition;
++	BOOL mMarked;
++	BOOL mFocused;
++	BOOL mIsLinden;
++	BOOL mIsCoarse;
++	std::string mRegionName;
++	LLPointer<LLHUDObject> mHudObject; /* holds the text on screen, if we don't keep this it won't reach a stable position on-screen but gets recreated for each update */
++
++
++	ACTIVITY_TYPE mActivityType;
++
++	std::string mAccountTitle;
++
++	LLAvatarListDatum<LLAvListTrustNetScore> mTrustNetScore;
++	LLAvatarListDatum<LLAvatarInfo>   mAvatarInfo;
++	LLAvatarListDatum<LLMiscDBInfo> mMiscInfo;
++
++	/**
++	 * @brief Timer to keep track of whether avatars are still there
++	 */
++	LLTimer mUpdateTimer;
++
++	/**
++	 * @brief Timer for avatar activities
++	 */
++	LLTimer mActivityTimer;
++
++	/**
++	 * @brief Last frame when this avatar was updated
++	 */
++	U32 mFrame;
++	
++	/**
++	 * @brief Time when avatar entered the list
++	 */
++	LLTimer mEnteredTimer;
++};
++
++
++/**
++ * @brief Avatar List
++ * Implements an avatar scanner in the client.
++ *
++ * This is my first attempt to modify the SL source. This code is intended
++ * to have a dual purpose: doing the task, and providing an example of how
++ * to do it. For that reason, it's going to be commented as exhaustively
++ * as possible.
++ *
++ * Since I'm very new to C++ any suggestions on coding, style, etc are very
++ * welcome.
++ */
++class LLFloaterAvatarList : public LLFloater
++{
++public:
++	/**
++	 * @brief Creates and initializes the LLFloaterAvatarList
++	 * Here the interface is created, and callbacks are initialized.
++	 */
++	LLFloaterAvatarList();
++	~LLFloaterAvatarList();
++
++	void show();
++
++	/**
++	 * @brief Hide when user closes the list.
++	 */
++	virtual void onClose(bool app_quitting) { setVisible(FALSE); }
++
++	/**
++	 * @brief Toggles interface visibility
++	 * There is only one instance of the avatar scanner at any time.
++	 */
++	static void toggle(void*);
++
++	/**
++	 * @brief Returns floater visibility status
++	 */
++	static BOOL visible(void*);
++
++	/**
++	 * @brief Updates the internal avatar list with the currently present avatars.
++	 */
++	void updateAvatarList();
++
++	/**
++	 * @brief Refresh avatar list (display)
++	 */
++	void refreshAvatarList();
++
++	/**
++	 * @brief Process the reply to a request for avatar properties
++	 */
++	static void processAvatarPropertiesReply(LLMessageSystem *msg, void**);
++
++	/**
++	 * @brief Returns TRUE if the avatar is in the list of known avatars
++	 * @returns TRUE if the avatar is in the list
++	 */
++	BOOL avatarIsInList(LLUUID avatar);
++
++	/**
++	 * @brief Returns the entry for an avatar, if preset
++	 * @returns Pointer to avatar entry, NULL if not found.
++	 */
++	LLAvatarListEntry* getAvatarEntry(LLUUID avatar);
++
++	/**
++	 * @brief Requests a TrustNet score from the Adapter
++	 * @param avatar Avatar for which to request the score
++	 * @param name Avatar's name
++	 * @param type Score type ("behavior", etc)
++	 */
++	void requestTrustNetScore(LLUUID avatar, const std::string name, const std::string type);
++
++	/**
++	 * @brief Requests information about the avatar from the database
++	 * @param avatar Avatar about whom we need information
++	 * @param name Avatar's name
++	 */
++	void requestMiscInfo(LLUUID avatar, const std::string name);
++
++	/**
++	 * @brief Handles IM messages to process the ones that are replies to database requests
++	 * @param from_id Key of the avatar sending the message
++	 * @param message Content
++	 * @returns TRUE if the message was handled. This will suppress further processing in llviewermessage.cpp
++	 */
++	static BOOL handleIM(LLUUID from_id, const std::string message);
++
++	/**
++	 * @brief Process a reply from the TrustNet Adapter
++	 * This handles replies from the TrustNet adapter, such as score results.
++	 */
++	static void processTrustNetReply(char *reply);
++
++	/**
++	 * @brief Returns a string with the selected names in the list
++	 */
++	std::string getSelectedNames(const std::string& separator = ", ");
++
++	/** @brief render a debug beacon for the coarse avatars */
++	void renderDebugBeacons();
++
++	/** @brief if avatar beacons shall be rendered */
++	static bool getRenderAvatarBeacons(void *data) { return sRenderAvatarBeacons; }
++
++	/** @brief set if avatar beacons shall be rendered */
++	static void toggleRenderAvatarBeacons(void *data) { sRenderAvatarBeacons = !sRenderAvatarBeacons; }
++
++	/** @brief set if avatar beacons shall be rendered */
++	static void setRenderAvatarBeacons(bool do_render ) { sRenderAvatarBeacons = do_render; }
++
++private:
++	// when a line editor loses keyboard focus, it is committed.
++	// commit callbacks are named onCommitWidgetName by convention.
++	//void onCommitBaz(LLUICtrl* ctrl, void *userdata);
++	
++	enum AVATARS_COLUMN_ORDER
++	{
++		LIST_AVATAR_ICON,
++		LIST_AVATAR_NAME,
++		LIST_DISTANCE,
++		LIST_AGE,
++		/*LIST_SCORE,*/
++		LIST_PAYMENT,
++		LIST_ACTIVITY,
++		LIST_ENTERED,
++	};
++
++	typedef void (*avlist_command_t)(const LLUUID &avatar, const std::string &name);
++
++	void speakText(S32 channel, EChatType type, std::string text);
++
++	/**
++	 * @brief Removes focus status from all avatars in list
++	 */
++	void removeFocusFromAll();
++
++	/**
++	 * @brief Focus camera on previous avatar
++	 * @param marked_only Whether to choose only marked avatars
++	 */
++	void focusOnPrev(BOOL marked_only);
++
++	/**
++	 * @brief Focus camera on next avatar
++	 * @param marked_only Whether to choose only marked avatars
++	 */
++	void focusOnNext(BOOL marked_only);
++
++	/**
++	 * @brief Updates the internal avatar list from the coarse location list if not already present
++	 */
++	void updateFromCoarse();
++
++	/**
++	 * @brief Purge hud object map from entries no longer in the list
++	 */
++	void purgeAvatarHUDMap();
++
++	/**
++	 * @brief Handler for the "refresh" button click.
++	 * I am unsure whether this is actually necessary at the time.
++	 *
++	 * LL: By convention, button callbacks are named onClickButtonLabel
++	 * @param userdata Pointer to user data (LLFloaterAvatarList instance)
++	 */
++	//static void onClickRefresh(void* userdata);
++
++	static void onClickProfile(void *userdata);
++	static void onClickIM(void *userdata);
++	static void onClickTrack(void *userdata);
++	static void onClickMark(void *userdata);
++
++	static void onClickGohomerMark(void *userdata);
++	static void onClickGohomerWarn(void *userdata);
++	static void onClickGohomerEject(void *userdata);
++	static void onClickGohomerSendAway(void *userdata);
++	static void onClickGohomerSendHome(void *userdata);
++	static void onClickGohomerSendHomeByKey(void *userdata);
++
++	static void onClickGohomerOff(void *userdata);
++
++
++	static void onClickPrevInList(void *userdata);
++	static void onClickNextInList(void *userdata);
++	static void onClickPrevMarked(void *userdata);
++	static void onClickNextMarked(void *userdata);
++	static void onClickGetKey(void *userdata);
++
++	static void onClickTrustNetRate(void *userdata);
++	static void onClickTrustNetExplain(void *userdata);
++	static void onClickTrustNetWebsite(void *userdata);
++	static void onClickTrustNetGetPassword(void *userdata);
++	static void onClickTrustNetRenew(void *userdata);
++
++	static void onDoubleClick(void *userdata);
++
++	static void onClickFreeze(void *userdata);
++	static void onClickEject(void *userdata);
++//	static void onClickBan(void *userdata);
++//	static void onClickUnban(void *userdata);
++	static void onClickMute(void *userdata);
++//	static void onClickUnmute(void *userdata);
++	static void onClickAR(void *userdata);
++	static void onClickTeleport(void *userdata);
++	static void onClickEjectFromEstate(void *userdata);
++
++	static void callbackFreeze(S32 option, void *userdata);
++//	static void callbackUnfreeze(S32 option, void *userdata);
++	static void callbackEject(S32 option, void *userdata);
++//	static void callbackBan(S32 option, void *userdata);
++	static void callbackMute(S32 option, void *userdata);
++//	static void callbackUnmute(void *userdata);
++	static void callbackAR(void *userdata);
++	static void callbackEjectFromEstate(S32 option, void *userdata);
++
++	void doCommand(avlist_command_t cmd);
++
++	/**
++	 * @brief Cleanup avatar list, removing dead entries from it.
++	 * This lets dead entries remain for some time. This makes it possible
++	 * to keep people passing by in the list long enough that it's possible
++	 * to do something to them.
++	 */
++	void expireAvatarList();
++
++	/**
++	 * @brief Perform a Luskwood Gohomer command on the selected users
++	 * @param cmd Command (for example "gowarn")
++	 */
++	void luskwoodCommand(std::string cmd);
++
++	/**
++	 * @brief Handle the results of a gohomer confirmation dialog
++	 * @param option Option selected (0=ok, 1=cancel)
++	 * @param data this
++	 */
++	static void handleLuskwoodDialog(S32 option, void* data);
++
++	/**
++	 * @brief Handle the results of a gohomer turn off dialog
++	 * @param option Option selected (0=ok, 1=cancel)
++	 * @param data this
++	 */
++	static void handleLuskwoodGohomerOffDialog(S32 option, void* data);
++
++	/**
++	 * @brief Process the AR queue
++	 * This generates AR reports for the queued avatars
++	 */
++	void processARQueue();
++		
++private:
++	/**
++	 * @brief Pointer to the avatar scroll list
++	 */
++	LLScrollListCtrl*			mAvatarList;
++	std::map<LLUUID, LLAvatarListEntry>	mAvatars;
++
++	/**
++	 * @brief Queue of abuse reports
++	 */
++	std::queue<LLUUID> mARQueue;
++
++	/**
++	 * @brief List of AR screens opened
++	 * We don't open them on creation to capture a clean screenshot. They're
++	 * opened only after finishing the process.
++	 */
++	std::queue<LLFloaterReporter*> mARReporterQueue;
++
++	/**
++	 * @brief Last time during which an AR was submitted
++	 * Used to give the camera some time to move between avatars. Perhaps this way
++	 * of doing things isn't ideal, though.
++	 */
++	S32 mARLastFrame;
++	
++	
++	/**
++	 * @brief Request information about the specified avatar
++	 * @param avid Avatar id to request info about
++	 */
++	void sendAvatarPropertiesRequest(LLUUID avid);
++
++	void checkTrackingStatus();
++
++	/**
++	 * @brief Returns the color for the specified avatar entry
++	 * @param ent Avatar entry
++	 * @param distance Distance from the user
++	 */
++	//LLColor4 getAvatarColor(LLAvatarListEntry *ent, F32 distance);
++	LLColor4 getAvatarColor(LLAvatarListEntry *ent, F32 distance, e_coloring_type type);
++
++	/**
++	 * @brief Replace variables in string
++	 * @param str String to replace variables in
++	 * @param avatar Value for $KEY
++	 * @param name Value for $NAME
++	 */
++	static void replaceVars(std::string &str, LLUUID avatar, const std::string& name);
++
++	// tracking data
++	BOOL mTracking;             // tracking?
++	BOOL mTrackByLocation;      // TRUE if tracking by known position, FALSE for tracking a friend
++	LLUUID mTrackedAvatar;     // who we're tracking
++
++	/**
++	 * @brief Used to delay avatar data requests
++	 */
++	LLTimer mDataRequestTimer;
++
++	/**
++	 * @brief Used to delay trustnet requests
++	 */
++	LLTimer mTrustNetTimer;
++
++	/**
++	 * @brief Luskwood command to execute
++	 */
++	std::string mLuskwoodCommand;
++
++	/**
++	 * @brief Avatar the camera is focused on
++	 */
++	LLUUID mFocusedAvatar;
++
++	/** @brief holds state of avatar beacon render setup */
++	static bool sRenderAvatarBeacons;
++
++
++	std::map< LLUUID, LLPointer<LLHUDObject> > mHudObjectMap;
++};
++
++/**
++ * Pointer to global LLFloaterAvatarList instance.
++ * This is initialized in llviewerwindow.cpp
++ * @see llviewerwindow.cpp
++ */
++extern LLFloaterAvatarList* gFloaterAvatarList;
+diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
+index 5451ca0..754c839 100644
+--- a/indra/newview/llfloaterpreference.cpp
++++ b/indra/newview/llfloaterpreference.cpp
+@@ -60,6 +60,7 @@
+ #include "llpanelLCD.h"
+ #include "llpanelmsgs.h"
+ #include "llpanelweb.h"
++#include "llpaneldatabase.h"
+ #include "llpanelskins.h"
+ #include "llprefschat.h"
+ #include "llprefsvoice.h"
+@@ -190,6 +191,10 @@ LLPreferenceCore::LLPreferenceCore(LLTabContainer* tab_container, LLButton * def
+ 	mTabContainer->addTabPanel(mSkinsPanel, mSkinsPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
+ 	mSkinsPanel->setDefaultBtn(default_btn);
+ 
++	mDBPanel = new LLPanelDatabase();
++	mTabContainer->addTabPanel(mDBPanel, mDBPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
++	mDBPanel->setDefaultBtn(default_btn);
++
+ 	if (!mTabContainer->selectTab(gSavedSettings.getS32("LastPrefTab")))
+ 	{
+ 		mTabContainer->selectFirstTab();
+@@ -269,6 +274,7 @@ void LLPreferenceCore::apply()
+ 	LLFloaterHardwareSettings::instance()->apply();
+ 
+ 	mWebPanel->apply();
++	mDBPanel->apply();
+ #if LL_LCD_COMPILE
+ 	// only add this option if we actually have a logitech keyboard / speaker set
+ 	if (gLcdScreen->Enabled())
+@@ -297,6 +303,7 @@ void LLPreferenceCore::cancel()
+ 	LLFloaterHardwareSettings::instance()->cancel();
+ 
+ 	mWebPanel->cancel();
++	mDBPanel->cancel();
+ #if LL_LCD_COMPILE
+ 	// only add this option if we actually have a logitech keyboard / speaker set
+ 	if (gLcdScreen->Enabled())
+diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
+index bfa2499..e54b7f6 100644
+--- a/indra/newview/llfloaterpreference.h
++++ b/indra/newview/llfloaterpreference.h
+@@ -49,6 +49,7 @@ class LLPanelAudioPrefs;
+ class LLPanelDebug;
+ class LLPanelNetwork;
+ class LLPanelWeb;
++class LLPanelDatabase;
+ class LLMessageSystem;
+ class LLPrefsChat;
+ class LLPrefsVoice;
+@@ -91,6 +92,7 @@ private:
+ 	LLPanelWeb				*mWebPanel;
+ 	LLPanelMsgs				*mMsgPanel;
+ 	LLPanelLCD				*mLCDPanel;
++	LLPanelDatabase				*mDBPanel;
+ };
+ 
+ // Floater to control preferences (display, audio, bandwidth, general.
+diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
+index 7e9632d..23f9ec5 100644
+--- a/indra/newview/llfloaterreporter.cpp
++++ b/indra/newview/llfloaterreporter.cpp
+@@ -540,7 +540,7 @@ void LLFloaterReporter::showFromMenu(EReportType report_type)
+ 
+ 
+ // static
+-void LLFloaterReporter::showFromObject(const LLUUID& object_id)
++LLFloaterReporter* LLFloaterReporter::showFromObject(const LLUUID& object_id, bool show)
+ {
+ 	LLFloaterReporter* f = createNewAbuseReporter();
+ 	f->center();
+@@ -557,7 +557,16 @@ void LLFloaterReporter::showFromObject(const LLUUID& object_id)
+ 	// Need to deselect on close
+ 	f->mDeselectOnClose = TRUE;
+ 
+-	f->open();		/* Flawfinder: ignore */
++	if ( show )
++	{
++		f->open();		/* Flawfinder: ignore */
++	}
++	else
++	{
++		gDialogVisible = FALSE;
++	}
++
++	return f;
+ }
+ 
+ 
+diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h
+index ff7f112..1603dad 100644
+--- a/indra/newview/llfloaterreporter.h
++++ b/indra/newview/llfloaterreporter.h
+@@ -92,7 +92,7 @@ public:
+ 	// Enables all buttons
+ 	static void showFromMenu(EReportType report_type);
+ 
+-	static void showFromObject(const LLUUID& object_id);
++	static LLFloaterReporter* showFromObject(const LLUUID& object_id, bool show = true);
+ 
+ 	static void onClickSend			(void *userdata);
+ 	static void onClickCancel		(void *userdata);
+diff --git a/indra/newview/llpaneldatabase.cpp b/indra/newview/llpaneldatabase.cpp
+new file mode 100644
+index 0000000..f510130
+--- /dev/null
++++ b/indra/newview/llpaneldatabase.cpp
+@@ -0,0 +1,149 @@
++/** 
++ * @file llpaneldatabase.cpp
++ * @brief Database preferences panel
++ * @author Dale Glass
++ *
++ * Copyright (c) 2003-2007, Linden Research, Inc.
++ * 
++ * 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.
++ */
++
++#include "llviewerprecompiledheaders.h"
++
++#include "llpaneldatabase.h"
++
++#include "llscrolllistctrl.h"
++#include "llviewerwindow.h"
++#include "llviewercontrol.h"
++#include "lluictrlfactory.h"
++#include "llfloateravatarpicker.h"
++#include "llagentdata.h"
++#include "llnotify.h"
++
++//-----------------------------------------------------------------------------
++LLPanelDatabase::LLPanelDatabase() :
++	LLPanel("Messages Panel")
++{
++	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_database.xml");
++	childSetAction("change_avatar_btn", onClickChangeAvatar, this);
++};
++
++//-----------------------------------------------------------------------------
++// postBuild()
++//-----------------------------------------------------------------------------
++
++void LLPanelDatabase::refresh() 
++{
++	llinfos << "Loading settings" << llendl;
++	//mAvatarName      = gSavedPerAccountSettings.getString("DBAvatarName");
++	//mAvatarKey.set(gSavedPerAccountSettings.getString("DBAvatarKey"));
++	//mURL             = gSavedSettings.getString("DBURL");;
++	//mUsername        = gSavedSettings.getString("DBURLUsername");;
++	//mPassword        = gSavedSettings.getString("DBURLPassword");;
++	//mSendPattern     = gSavedSettings.getString("DBSendPattern");;
++	//mPositivePattern = gSavedSettings.getString("DBPositivePattern");;
++	//mNegativePattern = gSavedSettings.getString("DBNegativePattern");;
++	//mDeniedPattern   = gSavedSettings.getString("DBDeniedPattern");;
++
++}
++
++BOOL LLPanelDatabase::postBuild()
++{
++	refresh();
++
++	llinfos << "Setting settings in window" << llendl;
++	childSetText("db_avatar"       ,mAvatarName );
++	childSetText("db_url"          ,mURL );
++	childSetText("db_url_username" ,mUsername );
++	childSetText("db_url_password" ,mPassword );
++	childSetText("send_pattern"    ,mSendPattern );
++	childSetText("positive_pattern",mPositivePattern );
++	childSetText("negative_pattern",mNegativePattern );
++	childSetText("denied_pattern"  ,mDeniedPattern );
++
++	return TRUE;
++}
++
++
++void LLPanelDatabase::draw()
++{
++	LLPanel::draw();
++}
++
++void LLPanelDatabase::apply()
++{
++	//llinfos << "Saving settings" << llendl;
++
++	//gSavedPerAccountSettings.setString("DBAvatarName", childGetText("db_avatar").c_str());
++	//gSavedPerAccountSettings.setString("DBAvatarKey", mAvatarKey.asString());
++	//gSavedSettings.setString("DBURL", childGetText("db_url").c_str());
++	//gSavedSettings.setString("DBURLUsername", childGetText("db_url_username").c_str());
++	//gSavedSettings.setString("DBURLPassword", childGetText("db_url_password").c_str());
++
++	//gSavedSettings.setString("DBSendPattern", childGetText("send_pattern").c_str());
++	//gSavedSettings.setString("DBPositivePattern", childGetText("positive_pattern").c_str());
++	//gSavedSettings.setString("DBNegativePattern", childGetText("negative_pattern").c_str());
++	//gSavedSettings.setString("DBDeniedPattern", childGetText("denied_pattern").c_str());	
++
++
++}
++
++void LLPanelDatabase::cancel()
++{
++	
++}
++
++//static
++void LLPanelDatabase::onClickChangeAvatar(void *userdata)
++{
++	LLFloaterAvatarPicker::show(onPickAvatar, userdata, FALSE, TRUE);
++}
++
++//static
++void LLPanelDatabase::onPickAvatar(const std::vector<std::string>& names,
++                                   const std::vector<LLUUID>& ids,
++                                   void* user_data)
++{
++	if (names.empty()) return;
++	if (ids.empty()) return;
++
++	LLPanelDatabase *self = (LLPanelDatabase*)user_data;
++
++#ifndef LL_DEBUG
++	// TODO: LL_DEBUG isn't the right one, what is it?
++	//
++	// Using yourself as the database avatar should work, and be useful
++	// for debugging, but it's not something a normal user should be able
++	// to do.
++	
++//	if(ids[0] == gAgentID)
++//	{
++//		LLNotifyBox::showXml("AddSelfDatabase");
++//		return;
++//	}
++#endif
++
++	self->childSetText("db_avatar", names[0]);
++	self->mAvatarName = names[0];
++	self->mAvatarKey = ids[0];
++}
++
++
+diff --git a/indra/newview/llpaneldatabase.h b/indra/newview/llpaneldatabase.h
+new file mode 100644
+index 0000000..e08a453
+--- /dev/null
++++ b/indra/newview/llpaneldatabase.h
+@@ -0,0 +1,65 @@
++/** 
++ * @file llprefschat.h
++ * @brief Database preferences panel
++ *
++ * Copyright (c) 2003-2007, Linden Research, Inc.
++ * 
++ * 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.
++ */
++
++#ifndef LLPREFSDB_H
++#define LLPREFSDB_H
++
++#include "llpanel.h"
++
++class LLPanelDatabase : public LLPanel
++{
++public:
++	LLPanelDatabase();
++	virtual ~LLPanelDatabase() {};
++
++	virtual BOOL postBuild();
++	virtual void draw();
++	virtual void refresh();
++
++	void apply();
++	void cancel();
++
++	static void onClickChangeAvatar(void *userdata);
++	static void onPickAvatar(const std::vector<std::string>& names,
++                                 const std::vector<LLUUID>& ids,
++                                 void* user_data);
++
++protected:
++	std::string mAvatarName;
++	LLUUID   mAvatarKey;
++	std::string mURL;
++	std::string mUsername;
++	std::string mPassword;
++	std::string mSendPattern;
++	std::string mPositivePattern;
++	std::string mNegativePattern;
++	std::string mDeniedPattern;
++
++};
++
++
++#endif // LL_PREFSDB_H
+diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
+index dd4b66c..ee265af 100644
+--- a/indra/newview/llstartup.cpp
++++ b/indra/newview/llstartup.cpp
+@@ -3007,7 +3007,7 @@ void register_viewer_callbacks(LLMessageSystem* msg)
+ 	msg->setHandlerFunc("ParcelDwellReply",
+ 		LLViewerParcelMgr::processParcelDwellReply);
+ 
+-	msg->setHandlerFunc("AvatarPropertiesReply",
++	msg->addHandlerFunc("AvatarPropertiesReply",
+ 						LLPanelAvatar::processAvatarPropertiesReply);
+ 	msg->setHandlerFunc("AvatarInterestsReply",
+ 						LLPanelAvatar::processAvatarInterestsReply);
+diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp
+index 8202191..1d4c1b2 100644
+--- a/indra/newview/lltoolbar.cpp
++++ b/indra/newview/lltoolbar.cpp
+@@ -49,6 +49,7 @@
+ #include "llvoavatar.h"
+ #include "lltooldraganddrop.h"
+ #include "llinventoryview.h"
++#include "llfloateravatarlist.h"
+ #include "llfloaterchatterbox.h"
+ #include "llfloaterfriends.h"
+ #include "llfloatersnapshot.h"
+@@ -154,6 +155,9 @@ BOOL LLToolBar::postBuild()
+ 	childSetAction("inventory_btn", onClickInventory, this);
+ 	childSetControlName("inventory_btn", "ShowInventory");
+ 
++	childSetAction("avatar_list_btn", onClickAvatarList, this);
++	childSetControlName("inventory_btn", "ShowAvatarList");
++
+ 	for (child_list_const_iter_t child_iter = getChildList()->begin();
+ 		 child_iter != getChildList()->end(); ++child_iter)
+ 	{
+@@ -527,3 +531,8 @@ void LLToolBar::onClickInventory(void*)
+ 	handle_inventory(NULL);
+ }
+ 
++// static
++void LLToolBar::onClickAvatarList(void*)
++{
++	LLFloaterAvatarList::toggle(NULL);
++}
+diff --git a/indra/newview/lltoolbar.h b/indra/newview/lltoolbar.h
+index 720b9c0..b8f8c78 100644
+--- a/indra/newview/lltoolbar.h
++++ b/indra/newview/lltoolbar.h
+@@ -82,6 +82,7 @@ public:
+ 	static void onClickRadar(void* data);
+ 	static void onClickMap(void* data);
+ 	static void onClickInventory(void* data);
++	static void onClickAvatarList(void* data);
+ 
+ 	static F32 sInventoryAutoOpenTime;
+ 
+diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
+index 2d64712..18b253e 100644
+--- a/indra/newview/llviewermenu.cpp
++++ b/indra/newview/llviewermenu.cpp
+@@ -201,6 +201,7 @@
+ #include "pipeline.h"
+ #include "llappviewer.h"
+ #include "roles_constants.h"
++#include "llfloateravatarlist.h"
+ #include "llviewerjoystick.h"
+ #include "llwlanimator.h"
+ #include "llwlparammanager.h"
+@@ -5267,6 +5268,10 @@ class LLShowFloater : public view_listener_t
+ 		{
+ 			LLFloaterAbout::show(NULL);
+ 		}
++		else if (floater_name == "avatar list")
++		{
++			LLFloaterAvatarList::toggle(NULL);
++		}
+ 		else if (floater_name == "active speakers")
+ 		{
+ 			LLFloaterActiveSpeakers::toggleInstance(LLSD());
+@@ -7408,6 +7413,15 @@ static void addMenu(view_listener_t *menu, const std::string& name)
+ 	menu->registerListener(gMenuHolder, name);
+ }
+ 
++class LLViewAvatarList : public view_listener_t
++{
++	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
++	{
++		llinfos << "LLViewAvatarList::handleEvent()" << llendl;
++		return true;
++	}
++};
++
+ void initialize_menus()
+ {
+ 	// File menu
+diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
+index 461a598..03b0a97 100644
+--- a/indra/newview/llviewermessage.cpp
++++ b/indra/newview/llviewermessage.cpp
+@@ -135,6 +135,9 @@
+ #include "llviewerdisplay.h"
+ #include "llkeythrottle.h"
+ 
++#include "llpanelavatar.h"
++#include "llfloateravatarlist.h"
++
+ #include <boost/tokenizer.hpp>
+ 
+ #if LL_WINDOWS // For Windows specific error handler
+diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
+index 340f279..059a877 100644
+--- a/indra/newview/llviewerobject.h
++++ b/indra/newview/llviewerobject.h
+@@ -598,8 +598,9 @@ protected:
+ 	TPACKETID		mLatestRecvPacketID;			// Latest time stamp on message from simulator
+ 	// extra data sent from the sim...currently only used for tree species info
+ 	U8* mData;
+-
++public:
+ 	LLPointer<LLViewerPartSourceScript>		mPartSourcep;	// Particle source associated with this object.
++protected:
+ 	LLAudioSourceVO* mAudioSourcep;
+ 	F32				mAudioGain;
+ 	
+diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
+index 2f49b67..59c40b0 100644
+--- a/indra/newview/llviewerwindow.cpp
++++ b/indra/newview/llviewerwindow.cpp
+@@ -106,6 +106,7 @@
+ #include "llfloatersnapshot.h"
+ #include "llfloatertools.h"
+ #include "llfloaterworldmap.h"
++#include "llfloateravatarlist.h"
+ #include "llfocusmgr.h"
+ #include "llframestatview.h"
+ #include "llgesturemgr.h"
+@@ -1866,9 +1867,14 @@ void LLViewerWindow::initWorldUI()
+ 		gMorphView->setVisible(FALSE);
+ 
+ 		// *Note: this is where gFloaterMute used to be initialized.
+-
++		gFloaterAvatarList = NULL;
+ 		LLWorldMapView::initClass();
+ 
++		gFloaterAvatarList = new LLFloaterAvatarList();
++		gFloaterAvatarList->setVisible(FALSE);
++
++		LLWorldMapView::initClass();
++		
+ 		adjust_rect_centered_partial_zoom("FloaterWorldMapRect2", full_window);
+ 
+ 		gFloaterWorldMap = new LLFloaterWorldMap();
+diff --git a/indra/newview/llwebbrowserctrl.h b/indra/newview/llwebbrowserctrl.h
+index e4ecea7..13332cf 100644
+--- a/indra/newview/llwebbrowserctrl.h
++++ b/indra/newview/llwebbrowserctrl.h
+@@ -32,6 +32,8 @@
+ #ifndef LL_LLWEBBROWSERCTRL_H
+ #define LL_LLWEBBROWSERCTRL_H
+ 
++#include "lluictrlfactory.h"
++
+ ////////////////////////////////////////////////////////////////////////////////
+ // data class that is passed with an event
+ class LLWebBrowserCtrlEvent
+diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
+index 3fa9098..6d5285c 100644
+--- a/indra/newview/pipeline.cpp
++++ b/indra/newview/pipeline.cpp
+@@ -78,6 +78,7 @@
+ #include "llviewerimagelist.h"
+ #include "llviewerobject.h"
+ #include "llviewerobjectlist.h"
++#include "llviewerpartsource.h"
+ #include "llviewerparcelmgr.h"
+ #include "llviewerregion.h" // for audio debugging.
+ #include "llviewerwindow.h" // For getSpinAxis
+@@ -92,6 +93,7 @@
+ #include "llvopartgroup.h"
+ #include "llworld.h"
+ #include "llcubemap.h"
++#include "llfloateravatarlist.h"
+ #include "lldebugmessagebox.h"
+ #include "llviewershadermgr.h"
+ #include "llviewerjoystick.h"
+@@ -2009,6 +2011,27 @@ void renderSoundHighlights(LLDrawable* drawablep)
+ 	}
+ }
+ 
++/**
++ * @brief Add particle sources to avatar list
++ * This tells the avatar list floater who is emitting particles
++ */
++void addParticleSourcesToList(LLDrawable *drawablep)
++{
++	if ( NULL != gFloaterAvatarList )
++	{
++		LLViewerObject *vobj = drawablep->getVObj();
++		if (vobj && vobj->isParticleSource())
++		{
++			LLUUID id = vobj->mPartSourcep->getOwnerUUID();
++			LLAvatarListEntry *ent = gFloaterAvatarList->getAvatarEntry(id);
++			if ( NULL != ent )
++			{
++				ent->setActivity(ACTIVITY_PARTICLES);
++			}
++		}
++	}
++}
++
+ void LLPipeline::postSort(LLCamera& camera)
+ {
+ 	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+@@ -2109,6 +2132,8 @@ void LLPipeline::postSort(LLCamera& camera)
+ 		std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
+ 	}
+ 
++	forAllVisibleDrawables(addParticleSourcesToList);
++
+ 	// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
+ 	if (gSavedSettings.getBOOL("BeaconAlwaysOn"))
+ 	{
+@@ -2157,6 +2182,23 @@ void LLPipeline::postSort(LLCamera& camera)
+ 		}
+ 	}
+ 
++	// Avatar list support
++	if ( gFloaterAvatarList && gAudiop )
++	{
++		LLAudioEngine::source_map::iterator iter;
++		for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
++		{
++			LLAudioSource *sourcep = iter->second;
++			LLUUID uuid = sourcep->getOwnerID();
++			LLAvatarListEntry *ent = gFloaterAvatarList->getAvatarEntry(uuid);
++
++			if ( ent )
++			{
++				ent->setActivity(ACTIVITY_SOUND);
++			}
++		}
++	}
++
+ 	// If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
+ 	if (LLFloaterTelehub::renderBeacons())
+ 	{
+diff --git a/indra/newview/skins/default/xui/en-us/alerts.xml b/indra/newview/skins/default/xui/en-us/alerts.xml
+index ff7a99c..18c0f9c 100644
+--- a/indra/newview/skins/default/xui/en-us/alerts.xml
++++ b/indra/newview/skins/default/xui/en-us/alerts.xml
+@@ -1374,6 +1374,23 @@ chat, or interact with the world.
+ 			Cancel
+ 		</option>
+ 	</alert>
++	<alert modal="true" name="AvatarListFreezeAvatars">
++		<message name="message">
++			Freeze these avatars?
++			[NAMES]
++			They will temporarily be unable to move,
++			chat, or interact with the world.
++		</message>
++		<option name="Freeze">
++			Freeze
++		</option>
++		<option name="Unfreeze">
++			Unfreeze
++		</option>
++		<option name="Cancel">
++			Cancel
++		</option>
++	</alert>	
+ 	<alert modal="true" name="EjectAvatar">
+ 		<message name="message">
+ 			Eject this avatar from your land?
+@@ -1402,6 +1419,52 @@ chat, or interact with the world.
+ 			Cancel
+ 		</option>
+ 	</alert>
++	<alert modal="true" name="AvatarListEjectAvatars">
++		<message name="message">
++			Eject these avatars from your land?
++			[NAMES]
++		</message>
++		<option name="Eject">
++			Eject
++		</option>
++		<option name="EjectandBan">
++			Eject and Ban
++		</option>
++		<option name="Cancel">
++			Cancel
++		</option>
++	</alert>
++	<alert modal="true" name="AvatarListEjectAvatarsFromEstate">
++		<message name="message">
++			Eject these avatars from this estate?
++			[NAMES]
++		</message>
++		<option name="Eject">
++			Eject
++		</option>
++		<option name="EjectandBan">
++			Eject and Ban
++		</option>
++		<option name="Cancel">
++			Cancel
++		</option>
++	</alert>
++	
++	<alert modal="true" name="AvatarListMuteAvatars">
++		<message name="message">
++			Mute these avatars?
++			[NAMES]
++		</message>
++		<option name="Mute">
++			Mute
++		</option>
++		<option name="Unmute">
++			Unmute
++		</option>		
++		<option name="Cancel">
++			Cancel
++		</option>
++	</alert>	
+     <alert modal="true" name="EjectAvatarNoBan">
+         <message name="message">
+             Eject this avatar from your land?
+@@ -4911,6 +4974,78 @@ they are part of an attachment.
+ 			No
+ 		</option>
+ 	</alert>
++	<!-- Luskwood functionality -->
++	<alert modal="true" name="LuskwoodGohomerWarn">
++		<message name="message">
++			Warn this avatar?
++			
++			This will show them a dialog asking to confirm that they understand
++			their behavior was found to be undesirable, and that they face
++			ejection or banning if it continues.
++		</message>
++		<option name="Warn">
++			Warn
++		</option>
++		<option default="true" name="Cancel">
++			Cancel
++		</option>
++	</alert>
++	<alert modal="true" name="LuskwoodGohomerEject">
++		<message name="message">
++			Eject this avatar?
++			
++			This avatar will be ejected from the area, but will be able to
++			return immediately.
++		</message>
++		<option name="Eject">
++			Eject
++		</option>
++		<option default="true" name="Cancel">
++			Cancel
++		</option>
++	</alert>
++	<alert modal="true" name="LuskwoodGohomerKeepAway">
++		<message name="message">
++			Eject this avatar and ban them for 2 hours?
++			
++			This avatar will be ejected from the area, and will be added to
++			the parcel's ban list for 2 hours.
++		</message>
++		<option name="KeepAway">
++			Keep Away
++		</option>
++		<option default="true" name="Cancel">
++			Cancel
++		</option>
++	</alert>
++	<alert modal="true" name="LuskwoodGohomerSendHome">
++		<message name="message">
++			Send this avatar home and ban them for 4 hours?
++			
++			This avatar will be sent home, and will be added to the parcel's
++			ban list for 4 hours.
++		</message>
++		<option name="KeepAway">
++			Send Home
++		</option>
++		<option default="true" name="Cancel">
++			Cancel
++		</option>
++	</alert>
++	<alert modal="true" name="LuskwoodGohomerOff">
++		<message name="message">
++			Turn off the gohomer?
++			
++			This will make it stop trying to send the last ejected avatar home,
++			but won't remove them from the ban list.
++		</message>
++		<option name="TurnOff">
++			Turn Off
++		</option>
++		<option default="true" name="Cancel">
++			Cancel
++		</option>
++	</alert>	
+ 	<alert modal="true" name="BadURL">
+ 		<message name="message">
+ 			Second Life doesn&apos;t know how to handle the link:
+diff --git a/indra/newview/skins/default/xui/en-us/floater_avatar_scanner.xml b/indra/newview/skins/default/xui/en-us/floater_avatar_scanner.xml
+new file mode 100644
+index 0000000..7156aa4
+--- /dev/null
++++ b/indra/newview/skins/default/xui/en-us/floater_avatar_scanner.xml
+@@ -0,0 +1,413 @@
++<?xml version="1.0" encoding="utf-8" standalone="yes"?>
++<floater
++	name="avatar list"
++	title="Avatar List"
++	can_resize="true"
++	can_minimize="true"
++	can_close="true"
++	can_drag_on_left="false"
++	rect_control="FloaterAvatarListRect"
++	min_width="400"
++	min_height="300"
++	>
++	<!-- <text
++		  name="help_label"
++		  bottom="-30"
++		  left="15"
++		  font="SansSerifSmall"
++		  follows="top|left"
++		  >
++	</text> -->
++	
++	<scroll_list
++		    name="avatar_list"
++		    left="10"
++		    right="-10"
++		    top="-20"
++		    bottom="150"
++		    column_padding="0"
++		    can_resize="true"
++		    follows="left|top|bottom|right"
++		    draw_heading="true"
++		    multi_select="true"
++		    search_column="1"
++		    tool_tip="Hold shift or control while clicking to select multiple avatars"
++		    >
++		<!-- Icons relating to the avatar, currently: tracking, and marked -->
++		<column name="avatar_icon" label="Icon" width="20" />
++		<column name="avatar_name" label="Name" dynamicwidth="true" />
++		<column name="distance" label="Distance" width="70"/>
++		<column name="age" label="Age" width="50"/>
++		<!-- <column name="payment_data" label="Payment" width="80"/> -->
++		<!-- TrustNet Score -->
++		<!-- <column name="score" label="Score" width="10"/> -->
++		<!-- Payment data icons -->
++		<column name="payment_data" label="" width="20" />
++		<!-- What the avatar is doing: producing sounds, rezzing, particles, etc -->
++		<column name="activity" label="" width="20" />
++		<!-- Time when avatar entered -->
++		<column name="entered" label="Entered" width="60"/>
++	</scroll_list>
++<!--	<panel 
++	       name="scanner_options"
++	       left="10"
++	       right="-10"	
++	       height="45"
++	       bottom="140"	
++	       border="true"
++	       mouse_opaque="true"
++	       bevel_style="in"
++	       background_visible="true"
++	       background_opaque="true"
++	       follows="left|right|bottom"
++	       bg_opaque_color="0,0,0,0.3"
++	       bg_alpha_color="blue"
++	       can_resize="false"
++	>
++	
++	</panel> -->
++	
++	<tab_container border="false" bottom_delta="-130" height="120" left="10" mouse_opaque="false"
++		       name="actions_tab_container" tab_position="top" follows="left|right|bottom">
++		<panel border="true" bottom_delta="-130" follows="left|top|right|bottom" height="255"
++		       label="Avatar" left="1" mouse_opaque="true"
++		     name="actions_tab" width="398">
++			<!-- upper row -->
++			<button
++			       name="profile_btn"
++			       label="Profile"
++			       tool_tip="Show picture, groups, and other information"
++			       left="10"
++			       bottom_delta="-190"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="im_btn"
++			       label="IM"
++			       tool_tip="Open Instant Message session"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			
++
++			<!--middle row -->
++			<button
++			       name="track_btn"
++			       label="Track"
++			       tool_tip="Track this avatar's position"
++			       left="10"
++			       bottom_delta="-24"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="mark_btn"
++			       label="Mark"
++			       tool_tip="Mark this avatar in the list"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="get_key_btn"
++			       label="Get Key"
++			       tool_tip="Copies avatar's key to the clipboard"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="teleport_btn"
++			       label="Teleport"
++			       tool_tip="Teleport to avatar's position"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />			
++			<!-- lower row-->
++			<button
++			       name="prev_in_list_btn"
++			       label="Prev"
++			       tool_tip="Focus camera on previous avatar in list"
++			       left="10"
++			       bottom_delta="-24"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="next_in_list_btn"
++			       label="Next"
++			       tool_tip="Focus camera on next avatar in list"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="prev_marked_btn"
++			       label="Prev Marked"
++			       tool_tip="Focus camera on previous marked avatar"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="next_marked_btn"
++			       label="Next Marked"
++			       tool_tip="Focus camera on next marked avatar"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++
++		</panel>
++		<panel border="true" bottom_delta="-130" follows="left|top|right|bottom" height="255"
++		       label="Moderation" left="1" mouse_opaque="true"
++		       name="land_tab" width="398">
++			
++			<!-- Upper row -->
++			<button
++			       name="freeze_btn"
++			       label="Freeze"
++			       tool_tip="Freeze the avatar, preventing it from moving"
++			       left="10"
++			       bottom_delta="-190"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="eject_btn"
++			       label="Eject"
++			       tool_tip="Eject the avatar from the parcel"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			
++			<button
++			       name="mute_btn"
++			       label="Mute"
++			       tool_tip="Mute this avatar"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			
++
++			<button
++			       name="ar_btn"
++			       label="AR"
++			       tool_tip="Report abuse on this avatar"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++
++			<!-- middle row -->
++			<button
++			       name="estate_eject_btn"
++			       label="Eject from estate"
++			       tool_tip="Eject this avatar from the estate"
++			       left="10"
++			       bottom_delta="-24"
++			       width="170"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++		</panel>
++		
++		<panel border="true" bottom_delta="-130" follows="left|top|right|bottom" height="255"
++		       label="TrustNet" left="1" mouse_opaque="true"
++		       name="trustnet_tab" width="398">
++			<!--TrustNet tools -->
++			<!-- upper row -->
++			<button
++			       name="tn_rate_btn"
++			       label="Rate"
++			       tool_tip="Give a TrustNet rating to this avatar"
++			       left="10"
++			       bottom_delta="-190"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="tn_explain_btn"
++			       label="Explain"
++			       tool_tip="Explain this avatar's score"
++			       left="100"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<!--lower row-->
++			<button
++			       name="tn_website_btn"
++			       label="Web"
++			       tool_tip="Open a web browser with the TrustNet website"
++			       left="10"
++			       bottom_delta="-24"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="tn_password_btn"
++			       label="Password"
++			       tool_tip="Get a password for the TrustNet website. A new password is generated every time."
++			       left="100"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="tn_renew_btn"
++			       label="Renew"
++			       tool_tip="Renew the TrustNet subscription"
++			       left="190"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			
++		</panel>
++		<panel border="true" bottom_delta="-130" follows="left|top|right|bottom" height="255"
++		       label="Luskwood" left="1" mouse_opaque="true"
++		     name="luskwood_tab" width="398">
++			<!--Luskwood tools, upper row-->
++			<button
++			       name="gowarn_btn"
++			       label="Warn"
++			       tool_tip="Give a warning to this avatar"
++			       left="10"
++			       bottom_delta="-190"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="goeject_btn"
++			       label="Eject"
++			       tool_tip="Eject this avatar"
++			       left="100"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="goaway_btn"
++			       label="Keep away"
++			       tool_tip="Eject, and keep this avatar away for 2 hours"
++			       left="190"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="gohome_btn"
++			       label="Send home"
++			       tool_tip="Send home, and keep this avatar away for 4 hours"
++			       left="280"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<!-- Middle row -->
++			<button
++			       name="gokey_btn"
++			       label="Ban by key"
++			       tool_tip="Turn off the send home function"
++			       left="10"
++			       bottom_delta="-24"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />
++			<button
++			       name="gohomeoff_btn"
++			       label="Off"
++			       tool_tip="Turn off the send home function"
++			       left_delta="90"
++			       bottom_delta="0"
++			       width="80"
++			       height="20"
++			       font="SansSerifSmall"
++			       follows="bottom|left"
++			       />			
++		</panel>
++		<panel border="true" bottom_delta="-150" follows="left|top|right|bottom" height="255"
++		       label="Options" left="1" mouse_opaque="true"
++		     name="options_tab" width="398">
++			<check_box height="16" label="Update"
++				   left="10" bottom_delta="-190" name="update_enabled_cb" 
++				   width="200" follows="bottom|left"
++				   hidden="false" mouse_opaque="true" font="SansSerifSmall"
++				   initial_value="true" enabled="true" radio_style="false" 
++				   tool_tip="Set whether the avatar list should update" />
++			
++			<check_box height="16" label="Get avatar info"
++				   left="20" bottom_delta="-21" name="fetch_avdata_enabled_cb" 
++				   width="200" follows="bottom|left"
++				   hidden="false" mouse_opaque="true" font="SansSerifSmall"
++				   initial_value="true" enabled="true" radio_style="false" 
++			   tool_tip="Set whether avatar information should be retrieved" />			
++		</panel>
++	</tab_container>
++
++</floater>
+diff --git a/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/indra/newview/skins/default/xui/en-us/menu_viewer.xml
+index d2c4923..9971454 100644
+--- a/indra/newview/skins/default/xui/en-us/menu_viewer.xml
++++ b/indra/newview/skins/default/xui/en-us/menu_viewer.xml
+@@ -221,6 +221,13 @@
+ 		     mouse_opaque="true" name="Preferences..." shortcut="control|P" width="153">
+ 			<on_click function="ShowFloater" userdata="preferences" />
+ 		</menu_item_call>
++		<menu_item_separator bottom="-46" enabled="true" height="8" hidden="false" label="-----------"
++		     left="0" mouse_opaque="true" name="separator6" width="211" />
++		<menu_item_check bottom="-65" enabled="true" height="19" hidden="false" label="Avatar List" left="0" mouse_opaque="true" name="Avatar List" width="211">
++			<on_click function="ShowFloater" userdata="avatar list" />
++			<on_check function="FloaterVisible" userdata="avatar list" />
++		</menu_item_check>
++
+ 	</menu>
+ 	<menu bottom="-1" create_jump_keys="true" drop_shadow="true" enabled="true"
+ 	     height="537" label="View" left="80" mouse_opaque="false" name="View"
+@@ -398,6 +405,12 @@
+ 		     mouse_opaque="true" name="Set UI Size to Default" width="188">
+ 			<on_click function="View.DefaultUISize" userdata="" />
+ 		</menu_item_call>
++		<menu_item_separator bottom="-46" enabled="true" height="8" hidden="false" label="-----------"
++		     left="0" mouse_opaque="true" name="separator6" width="211" />
++		<menu_item_check bottom="-65" enabled="true" height="19" hidden="false" label="Avatar List" left="0" mouse_opaque="true" name="Avatar List" width="211">
++			<on_click function="ShowFloater" userdata="avatar list" />
++			<on_check function="FloaterVisible" userdata="avatar list" />
++		</menu_item_check>
+ 	</menu>
+ 	<menu bottom="-18" create_jump_keys="true" drop_shadow="true" enabled="true"
+ 	     height="339" label="World" left="0" mouse_opaque="false" name="World"
+diff --git a/indra/newview/skins/default/xui/en-us/notify.xml b/indra/newview/skins/default/xui/en-us/notify.xml
+index 63396af..cf0056b 100644
+--- a/indra/newview/skins/default/xui/en-us/notify.xml
++++ b/indra/newview/skins/default/xui/en-us/notify.xml
+@@ -915,6 +915,12 @@ You can find example sculpted textures in the inventory library.
+ from this list.
+ 		</message>
+ 	</notify>
++	<!--Database preferences panel -->
++	<notify name="AddSelfDatabase" tip="false">
++		<message name="message">
++			You cannot use yourself as the database avatar.
++		</message>
++	</notify>	
+ 	<notify name="VoiceInviteP2P" tip="false" unique="true">
+ 		<message name="message">
+ 			[NAME] is inviting you to a Voice Chat call. 
+diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_database.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_database.xml
+new file mode 100644
+index 0000000..314b02d
+--- /dev/null
++++ b/indra/newview/skins/default/xui/en-us/panel_preferences_database.xml
+@@ -0,0 +1,166 @@
++<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
++<panel border="true" bottom="-409" enabled="true" follows="left|top|right|bottom"
++       height="408" hidden="false" label="Database" left="102" mouse_opaque="true"
++       name="avatar_db" width="517">
++	
++	<!-- Options section -->
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	      bottom="-30" drop_shadow_visible="true" enabled="true" follows="left|top"
++	      font="SansSerifSmall" h_pad="0" halign="left" height="10" hidden="false"
++	      left="12" mouse_opaque="false" name="text_box" v_pad="0" width="300">
++		Options:
++	</text>
++
++	<check_box bottom_delta="0" control_name="DBEnabled" enabled="true"
++		   follows="left|top" font="SansSerifSmall" height="16" hidden="false"
++		   initial_value="false" label="Database enabled" left="148"
++		   mouse_opaque="true" name="database_enabled_cb" radio_style="false"
++	     width="256" />
++	
++	<radio_group bottom_delta="-110" control_name="DBRetrievalMode" draw_border="true" enabled="true"
++		     follows="left|top" height="100" hidden="false" left="148"
++		     mouse_opaque="true" name="Database access type" width="321">
++		<radio_item type="string" length="1" bottom="-20" enabled="true" follows="left|top" height="16" hidden="false"
++			    left="3" mouse_opaque="true" name="UseAvatar" width="315">
++			Avatar:
++		</radio_item>
++		<radio_item type="string" length="1" bottom_delta="-10" enabled="false" follows="left|top" height="16" hidden="false"
++			    left="3" mouse_opaque="true" name="UseURL" width="315">
++			URL:
++		</radio_item>
++	</radio_group>
++	
++	<!-- HACK: apparently line_editor can't go inside a radio_group, so we make it appear
++	     inside while not actually being in there -->
++	<button bottom_delta="78" follows="right|bottom" font="SansSerif" halign="center"
++		height="20" label="Change Avatar" label_selected="Change Avatar" left="260"
++	     mouse_opaque="true" name="change_avatar_btn" width="100" />
++	
++	<line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="0"
++		     follows="left|top|right" font="SansSerifSmall" height="16" hidden="false"
++		     left="348" max_length="254" mouse_opaque="true" name="db_avatar"
++		     select_on_focus="false" width="130" control_name="DBAvatar" enabled="false"/>
++	
++	<line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="-20"
++		     follows="left|top|right" font="SansSerifSmall" height="16" hidden="false"
++		     left="248" max_length="254" mouse_opaque="true" name="db_url"
++		     select_on_focus="false" width="230" enabled="false" control_name="DBURL" />	
++
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	      bottom_delta="-20" drop_shadow_visible="true" enabled="true" follows="left|top"
++	      font="SansSerifSmall" h_pad="0" halign="left" height="10" hidden="false"
++	      left="170" mouse_opaque="false" name="text_box" v_pad="0" width="300">
++		Username:
++	</text>	
++
++	<line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="0"
++		     follows="left|top|right" font="SansSerifSmall" height="16" hidden="false"
++		     left="248" max_length="254" mouse_opaque="true" name="db_url_username"
++		     select_on_focus="false" width="230" enabled="false" control_name="DBURLUsername" />
++	
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	      bottom_delta="-20" drop_shadow_visible="true" enabled="true" follows="left|top"
++	      font="SansSerifSmall" h_pad="0" halign="left" height="10" hidden="false"
++	      left="170" mouse_opaque="false" name="text_box" v_pad="0" width="300">
++		Password:
++	</text>	
++
++	<line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="0"
++		     follows="left|top|right" font="SansSerifSmall" height="16" hidden="false"
++		     left="248" max_length="254" mouse_opaque="true" name="db_url_password"
++		     select_on_focus="false" width="230" enabled="false" control_name="DBURLPassword" />
++
++	
++	<!--Patterns section-->
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	      bottom_delta="-30" drop_shadow_visible="true" enabled="true" follows="left|top"
++	      font="SansSerifSmall" h_pad="0" halign="left" height="10" hidden="false"
++	      left="12" mouse_opaque="false" name="text_box" v_pad="0" width="300">
++		Patterns:
++	</text>
++	
++
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	      bottom_delta="-20" drop_shadow_visible="true" enabled="true" follows="left|top"
++	      font="SansSerifSmall" h_pad="0" halign="left" height="10" hidden="false"
++	      left="148" mouse_opaque="false" name="text_box2" v_pad="0" width="300">
++		Send:
++	</text>
++	
++	<line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="0"
++		     follows="left|top|right" font="SansSerifSmall" height="16" hidden="false"
++		     left="248" max_length="254" mouse_opaque="true" name="send_pattern"
++		     select_on_focus="false" width="230" control_name="DBSendPattern" >
++		$NAME
++	</line_editor>
++
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	      bottom_delta="-20" drop_shadow_visible="true" enabled="true" follows="left|top"
++	      font="SansSerifSmall" h_pad="0" halign="left" height="10" hidden="false"
++	      left="148" mouse_opaque="false" name="text_box2" v_pad="0" width="300">
++		Positive contains:
++	</text>
++	
++	<line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="0"
++		     follows="left|top|right" font="SansSerifSmall" height="16" hidden="false"
++		     left="248" max_length="254" mouse_opaque="true" name="positive_pattern"
++		     select_on_focus="false" width="230"  control_name="DBPositivePattern" />
++	
++	
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	      bottom_delta="-20" drop_shadow_visible="true" enabled="true" follows="left|top"
++	      font="SansSerifSmall" h_pad="0" halign="left" height="10" hidden="false"
++	      left="148" mouse_opaque="false" name="text_box2" v_pad="0" width="300">
++		Negative contains:
++	</text>
++	
++	<line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="0"
++		     follows="left|top|right" font="SansSerifSmall" height="16" hidden="false"
++		     left="248" max_length="254" mouse_opaque="true" name="negative_pattern"
++		     select_on_focus="false" width="230"  control_name="DBNegativePattern" />
++	
++	
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	      bottom_delta="-20" drop_shadow_visible="true" enabled="true" follows="left|top"
++	      font="SansSerifSmall" h_pad="0" halign="left" height="10" hidden="false"
++	      left="148" mouse_opaque="false" name="text_box2" v_pad="0" width="300">
++		Denied contains:
++	</text>
++	
++	<line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="0"
++		     follows="left|top|right" font="SansSerifSmall" height="16" hidden="false"
++		     left="248" max_length="254" mouse_opaque="true" name="denied_pattern"
++		     select_on_focus="false" width="230"  control_name="DBDeniedPattern" />
++	
++	<!--Timeouts section-->
++	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
++	      bottom_delta="-30" drop_shadow_visible="true" enabled="true" follows="left|top"
++	      font="SansSerifSmall" h_pad="0" halign="left" height="10" hidden="false"
++	      left="12" mouse_opaque="false" name="text_box" v_pad="0" width="300">
++		Timeouts:
++	</text>
++		
++	<spinner bottom_delta="-20" control_name="DBMaxConcurrentRequests" decimal_digits="0" enabled="true"
++		 follows="left|top" height="16" hidden="false" increment="1"
++		 initial_val="4" label="Max concurrent requests:" label_width="138" left="148"
++		 max_val="32" min_val="1" mouse_opaque="true" name="max_concurrent_requests"
++		 width="202" />
++
++	<spinner bottom_delta="-20" control_name="DBDelayBetweenRequests" decimal_digits="0" enabled="true"
++		 follows="left|top" height="16" hidden="false" increment="1"
++		 initial_val="1" label="Delay between requests:" label_width="138" left="148"
++		 max_val="32" min_val="0" mouse_opaque="true" name="delay_between_requests"
++		 width="202" />
++	
++	<spinner bottom_delta="-20" control_name="DBRequestTimeout" decimal_digits="0" enabled="true"
++		 follows="left|top" height="16" hidden="false" increment="4"
++		 initial_val="64" label="Request timeout:" label_width="138" left="148"
++		 max_val="65536" min_val="16" mouse_opaque="true" name="request_timeout"
++		 width="202" />
++	
++	<spinner bottom_delta="-20" control_name="DBGiveUpAfter" decimal_digits="0" enabled="true"
++		 follows="left|top" height="16" hidden="false" increment="64"
++		 initial_val="4096" label="Give up after:" label_width="138" left="148"
++		 max_val="65536" min_val="64" mouse_opaque="true" name="give_up_after"
++		 width="202" />
++</panel>
+\ No newline at end of file
+diff --git a/indra/newview/skins/default/xui/en-us/panel_toolbar.xml b/indra/newview/skins/default/xui/en-us/panel_toolbar.xml
+index 9c57be0..b264e6e 100644
+--- a/indra/newview/skins/default/xui/en-us/panel_toolbar.xml
++++ b/indra/newview/skins/default/xui/en-us/panel_toolbar.xml
+@@ -18,6 +18,12 @@
+ 	       list_position="above"
+ 	       width="50" follows="left|right" user_resize="false"/>
+     <icon image_name="spacer24.tga" width="2" height="2" follows="left|right" auto_resize="false" color="0,0,0,0"/>
++ 	<button bottom="0" font="SansSerif" height="24" label="Avatars" left="0"
++ 	     name="avatar_list_btn" tool_tip="List of nearby avatars" width="50" 
++         image_selected="toolbar_btn_selected.tga" 
++         image_unselected="toolbar_btn_enabled.tga" scale_image="true"
++		 follows="left|right" user_resize="false" />	
++    <icon image_name="spacer24.tga" width="2" height="2" follows="left|right" auto_resize="false" color="0,0,0,0"/>
+     <button bottom="0" font="SansSerif" height="24" label="Fly"
+         image_overlay="icn_toolbar_fly.tga" image_overlay_alignment="left"
+                         image_selected="toolbar_btn_selected.tga"
+@@ -68,3 +74,4 @@
+   </layout_stack>
+ 
+ </panel>
++
+-- 
+tg: (fd964dd..) topic/features/jira-backported/avatar_list (depends on: master)
diff --git a/debian/patches/topic/features/jira-sent/24_always_test_vectorize.diff b/debian/patches/topic/features/jira-sent/24_always_test_vectorize.diff
new file mode 100644
index 0000000..f6343ec
--- /dev/null
+++ b/debian/patches/topic/features/jira-sent/24_always_test_vectorize.diff
@@ -0,0 +1,39 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/features/jira-sent/24_always_test_vectorize
+
+Always test to see if CPU has sse/altivect expernsions, regardless of compile host.
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/newview/llappviewer.cpp |    8 --------
+ 1 files changed, 0 insertions(+), 8 deletions(-)
+
+diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
+index 63711ba..1755f39 100644
+--- a/indra/newview/llappviewer.cpp
++++ b/indra/newview/llappviewer.cpp
+@@ -416,7 +416,6 @@ static void settings_modify()
+ 	gDebugGL = gSavedSettings.getBOOL("RenderDebugGL");
+ 	gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
+ 	
+-#if LL_VECTORIZE
+ 	if (gSysCPU.hasAltivec())
+ 	{
+ 		gSavedSettings.setBOOL("VectorizeEnable", TRUE );
+@@ -442,13 +441,6 @@ static void settings_modify()
+ 		gSavedSettings.setU32("VectorizeProcessor", 0 );
+ 		gSavedSettings.setBOOL("VectorizeSkin", FALSE);
+ 	}
+-#else
+-	// This build target doesn't support SSE, don't test/run.
+-	gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
+-	gSavedSettings.setBOOL("VectorizeEnable", FALSE );
+-	gSavedSettings.setU32("VectorizeProcessor", 0 );
+-	gSavedSettings.setBOOL("VectorizeSkin", FALSE);
+-#endif
+ }
+ 
+ void LLAppViewer::initGridChoice()
+-- 
+tg: (fd717f3..) topic/features/jira-sent/24_always_test_vectorize (depends on: upstream)
diff --git a/debian/patches/topic/features/jira-sent/openal_1.21.0.diff b/debian/patches/topic/features/jira-sent/openal_1.21.0.diff
new file mode 100644
index 0000000..0932a77
--- /dev/null
+++ b/debian/patches/topic/features/jira-sent/openal_1.21.0.diff
@@ -0,0 +1,1085 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/features/jira-sent/openal_1.21.0
+
+My version of openal and gstreamer patches.
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/cmake/LLAudio.cmake            |   10 +-
+ indra/cmake/OPENAL.cmake             |   14 +
+ indra/llaudio/CMakeLists.txt         |   18 +
+ indra/llaudio/audioengine.cpp        |    6 +
+ indra/llaudio/audioengine.h          |    4 +
+ indra/llaudio/audioengine_openal.cpp |  618 ++++++++++++++++++++++++++++++++++
+ indra/llaudio/audioengine_openal.h   |  123 +++++++
+ indra/llaudio/listener_openal.cpp    |   95 ++++++
+ indra/llaudio/listener_openal.h      |    4 +
+ indra/newview/CMakeLists.txt         |    6 +
+ indra/newview/llstartup.cpp          |   14 +-
+ 11 files changed, 908 insertions(+), 4 deletions(-)
+
+diff --git a/indra/cmake/LLAudio.cmake b/indra/cmake/LLAudio.cmake
+index eff643d..124067b 100644
+--- a/indra/cmake/LLAudio.cmake
++++ b/indra/cmake/LLAudio.cmake
+@@ -6,4 +6,12 @@ set(LLAUDIO_INCLUDE_DIRS
+     ${LIBS_OPEN_DIR}/llaudio
+     )
+ 
+-set(LLAUDIO_LIBRARIES llaudio)
++set(LLAUDIO_LIBRARIES
++    llaudio
++    ${VORBISENC_LIBRARIES}
++    ${VORBISFILE_LIBRARIES}
++    ${VORBIS_LIBRARIES}
++    ${OGG_LIBRARIES}
++    ${OPENAL_LIBRARIES}
++    )
++
+diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake
+new file mode 100644
+index 0000000..ad0ebfc
+--- /dev/null
++++ b/indra/cmake/OPENAL.cmake
+@@ -0,0 +1,14 @@
++
++set(OPENAL OFF CACHE BOOL "Enable OpenAL")
++
++
++if (OPENAL)
++	include(FindPkgConfig)
++	pkg_check_modules(OPENAL_LIB REQUIRED openal)
++	pkg_check_modules(FREEAULT_LIB REQUIRED freealut)
++	set(OPENAL_LIBRARIES 
++		openal
++		alut
++	)
++		
++endif (OPENAL)
+diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
+index ebedcab..ed008ae 100644
+--- a/indra/llaudio/CMakeLists.txt
++++ b/indra/llaudio/CMakeLists.txt
+@@ -9,6 +9,7 @@ include(LLCommon)
+ include(LLMath)
+ include(LLMessage)
+ include(LLVFS)
++include(LLMedia)
+ 
+ include_directories(
+     ${FMOD_INCLUDE_DIR}
+@@ -20,6 +21,10 @@ include_directories(
+     ${VORBISENC_INCLUDE_DIRS}
+     ${VORBISFILE_INCLUDE_DIRS}
+     ${VORBIS_INCLUDE_DIRS}
++    ${OPENAL_LIB_INCLUDE_DIRS}
++    ${FREEAULT_LIB_INCLUDE_DIRS}
++    ${LLMEDIA_INCLUDE_DIRS}
++    ${GSTREAMER_INCLUDE_DIRS}
+     )
+ 
+ set(llaudio_SOURCE_FILES
+@@ -59,6 +64,19 @@ if (FMOD)
+     endif (LINUX)
+ endif (FMOD)
+ 
++if (OPENAL)
++	list(APPEND llaudio_SOURCE_FILES
++	audioengine_openal.cpp
++	listener_openal.cpp
++	)
++
++	list(APPEND llaudio_HEADER_FILES
++	audioengine_openal.h
++	listener_openal.h
++	)
++  	
++endif (OPENAL)
++
+ set_source_files_properties(${llaudio_HEADER_FILES}
+                             PROPERTIES HEADER_FILE_ONLY TRUE)
+ 
+diff --git a/indra/llaudio/audioengine.cpp b/indra/llaudio/audioengine.cpp
+index 81536cf..4e05077 100644
+--- a/indra/llaudio/audioengine.cpp
++++ b/indra/llaudio/audioengine.cpp
+@@ -114,6 +114,8 @@ BOOL LLAudioEngine::init(const S32 num_channels, void* userdata)
+ 	// Initialize the decode manager
+ 	gAudioDecodeMgrp = new LLAudioDecodeMgr;
+ 
++	llinfos << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl;
++
+ 	return TRUE;
+ }
+ 
+@@ -1353,7 +1355,11 @@ BOOL LLAudioSource::play(const LLUUID &audio_uuid)
+ BOOL LLAudioSource::isDone()
+ {
+ 	const F32 MAX_AGE = 60.f;
++#if LL_OPENAL
++	const F32 MAX_UNPLAYED_AGE = 30.f;
++#else
+ 	const F32 MAX_UNPLAYED_AGE = 15.f;
++#endif
+ 	if (isLoop())
+ 	{
+ 		// Looped sources never die on their own.
+diff --git a/indra/llaudio/audioengine.h b/indra/llaudio/audioengine.h
+index 0bd6327..d7ca446 100644
+--- a/indra/llaudio/audioengine.h
++++ b/indra/llaudio/audioengine.h
+@@ -173,6 +173,10 @@ public:
+ 	static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status);
+ 
+ 
++	#if LL_OPENAL
++		virtual void InitStreamer() = 0;
++	#endif
++
+ 	friend class LLPipeline; // For debugging
+ public:
+ 	F32 mMaxWindGain; // Hack.  Public to set before fade in?
+diff --git a/indra/llaudio/audioengine_openal.cpp b/indra/llaudio/audioengine_openal.cpp
+new file mode 100644
+index 0000000..d6a2f12
+--- /dev/null
++++ b/indra/llaudio/audioengine_openal.cpp
+@@ -0,0 +1,618 @@
++/**
++ * @file audioengine_openal.cpp
++ * @brief implementation of audio engine using OpenAL
++ * support as a OpenAL 3D implementation
++ *
++ * Copyright (c) 2002-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.
++ */
++
++#include "linden_common.h"
++
++#include "audioengine_openal.h"
++#include "listener_openal.h"
++
++
++#if LL_OPENAL_WIND
++// Variables and definitions for Wind
++#define NO_WIND_BUFFERS 20
++static ALuint wind_buffers[NO_WIND_BUFFERS];
++static ALuint wind_sources[1];
++static S16 *winddata=NULL;
++
++static BOOL first_wind=TRUE;
++
++ALfloat source0Vel[]={ 0.0, 0.0, 0.0};
++
++// These globals for the wind filter.  Blech!
++F64 gbuf0 = 0.0;
++F64 gbuf1 = 0.0;
++F64 gbuf2 = 0.0;
++F64 gbuf3 = 0.0;
++F64 gbuf4 = 0.0;
++F64 gbuf5 = 0.0;
++F64 gY0 = 0.0;
++F64 gY1 = 0.0;
++
++F32 gTargetGain = 0.f;
++F32 gCurrentGain = 0.f;
++F32 gTargetFreq = 100.f;
++F32 gCurrentFreq = 100.f;
++F32 gTargetPanGainR = 0.5f;
++F32 gCurrentPanGainR = 0.5f;
++#endif // LL_OPENAL_WIND
++
++LLAudioEngine_OpenAL::LLAudioEngine_OpenAL(){
++
++#if LL_GSTREAMER_ENABLED
++	mMedia_data = new LLMediaManagerData;
++	LLMediaImplGStreamer::startup( mMedia_data );	// initialize GStreamer
++
++	m_streamer=new LLMediaImplGStreamer ();
++
++	if(!m_streamer)
++	{
++		llwarns << "LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() Failed to create our private gstreamer audio instance" << llendl;
++	}
++#endif
++}
++
++LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL(){
++}
++
++BOOL LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata){
++
++	LLAudioEngine::init(num_channels, userdata);
++
++	if(!alutInit(NULL, NULL)){
++		llwarns << "LLAudioEngine_OpenAL::init() ALUT initialization failed: " << alutGetErrorString (alutGetError ()) << llendl;
++		return FALSE;
++	}
++
++	initInternetStream();
++
++	llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl;
++
++	llinfos << "LLAudioEngine_OpenAL::init() Speed of sound is: " << alGetFloat(AL_SPEED_OF_SOUND) << llendl;
++
++	return TRUE;
++}
++
++void LLAudioEngine_OpenAL::idle(F32 max_decode_time){
++	LLAudioEngine::idle(max_decode_time);
++#if LL_GSTREAMER_ENABLED
++       if(m_streamer != NULL)
++		m_streamer->updateMedia();
++#endif
++}
++
++void LLAudioEngine_OpenAL::allocateListener(){
++	mListenerp = (LLListener *) new LLListener_OpenAL();
++	if(!mListenerp){
++		llwarns << "LLAudioEngine_OpenAL::allocateListener() Listener creation failed" << llendl;
++	}
++}
++
++void LLAudioEngine_OpenAL::shutdown(){
++	LLAudioEngine::shutdown();
++
++	if(!alutExit()){
++		llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl;
++	}
++
++	llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl;
++
++	delete mListenerp;
++	mListenerp = NULL;
++
++#if LL_GSTREAMER_ENABLED
++	if(m_streamer){
++		delete m_streamer;
++		m_streamer = NULL;
++	}
++#endif
++}
++
++LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer(){
++   return new LLAudioBufferOpenAL();
++}
++
++LLAudioChannel *LLAudioEngine_OpenAL::createChannel(){
++   return new LLAudioChannelOpenAL();
++}
++
++void LLAudioEngine_OpenAL::setInternalGain(F32 gain){
++	//llinfos << "LLAudioEngine_OpenAL::setInternalGain() Gain: " << gain << llendl;
++	alListenerf(AL_GAIN, gain);
++}
++
++LLAudioChannelOpenAL::LLAudioChannelOpenAL(){
++	alGenSources(1, &ALSource);
++}
++
++LLAudioChannelOpenAL::~LLAudioChannelOpenAL(){
++	cleanup();
++	alDeleteSources(1, &ALSource);
++}
++
++void LLAudioChannelOpenAL::cleanup(){
++	alSourceStop(ALSource);
++	mCurrentBufferp = NULL;
++}
++
++void LLAudioChannelOpenAL::play(){
++	if(!isPlaying()){
++		alSourcePlay(ALSource);
++		getSource()->setPlayedOnce(TRUE);
++	}
++}
++
++void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp){
++	play();
++}
++
++BOOL LLAudioChannelOpenAL::isPlaying(){
++	ALint state;
++	alGetSourcei(ALSource, AL_SOURCE_STATE, &state);
++	if(state == AL_PLAYING){
++		return TRUE;
++	}
++	return FALSE;
++}
++
++BOOL LLAudioChannelOpenAL::updateBuffer(){
++	if (LLAudioChannel::updateBuffer()){
++		// Base class update returned TRUE, which means that we need to actually
++		// set up the source for a different buffer.
++		LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer();
++		alSourcei(ALSource, AL_BUFFER, bufferp->getBuffer());
++		alSourcef(ALSource, AL_GAIN, mCurrentSourcep->getGain());
++		alSourcei(ALSource, AL_LOOPING, mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE);
++	}
++
++	return TRUE;
++}
++
++void LLAudioChannelOpenAL::update3DPosition(){
++	if(!mCurrentSourcep){
++		return;
++	}
++	if (mCurrentSourcep->isAmbient()){
++		alSource3f(ALSource, AL_POSITION, 0.0, 0.0, 0.0);
++		alSource3f(ALSource, AL_VELOCITY, 0.0, 0.0, 0.0);
++		//alSource3f(ALSource, AL_DIRECTION, 0.0, 0.0, 0.0);
++		alSourcef (ALSource, AL_ROLLOFF_FACTOR, 0.0);
++		alSourcei (ALSource, AL_SOURCE_RELATIVE, AL_TRUE);
++	}else{
++		LLVector3 float_pos;
++		float_pos.setVec(mCurrentSourcep->getPositionGlobal());
++		alSourcefv(ALSource, AL_POSITION, float_pos.mV);
++		//llinfos << "LLAudioChannelOpenAL::update3DPosition() Velocity: " << mCurrentSourcep->getVelocity() << llendl;
++		alSourcefv(ALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV);
++		//alSource3f(ALSource, AL_DIRECTION, 0.0, 0.0, 0.0);
++		alSourcef (ALSource, AL_ROLLOFF_FACTOR, 1.0);
++		alSourcei (ALSource, AL_SOURCE_RELATIVE, AL_FALSE);
++	}
++	//llinfos << "LLAudioChannelOpenAL::update3DPosition() Gain: " << mCurrentSourcep->getGain() << llendl;
++	alSourcef(ALSource, AL_GAIN, mCurrentSourcep->getGain());
++}
++
++LLAudioBufferOpenAL::LLAudioBufferOpenAL(){
++	ALBuffer = AL_NONE;
++}
++
++LLAudioBufferOpenAL::~LLAudioBufferOpenAL(){
++	cleanup();
++}
++
++void LLAudioBufferOpenAL::cleanup(){
++	if(ALBuffer != AL_NONE){
++		alDeleteBuffers(1, &ALBuffer);
++	}
++}
++
++BOOL LLAudioBufferOpenAL::loadWAV(const std::string& filename){
++	cleanup();
++	ALBuffer = alutCreateBufferFromFile(filename.c_str());
++	if(ALBuffer == AL_NONE){
++		//ALenum error = alutGetError();
++		//llwarns << "LLAudioBufferOpenAL::loadWAV() Error loading " << filename
++		//	<< " " << alutGetErrorString(error) << llendl;
++		return FALSE;
++	}
++
++	return TRUE;
++}
++
++U32 LLAudioBufferOpenAL::getLength(){
++	if(ALBuffer == AL_NONE){
++		return 0;
++	}
++	ALint length;
++	alGetBufferi(ALBuffer, AL_SIZE, &length);
++	return length >> 2;
++}
++
++// ------------
++
++void LLAudioEngine_OpenAL::initWind(){
++#if LL_OPENAL_WIND
++	ALenum error;
++       llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl;
++
++       alGetError(); /* clear error */
++       alGenBuffers(NO_WIND_BUFFERS,wind_buffers);
++       if((error=alGetError()) != AL_NO_ERROR)
++       {
++               llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffers: "<<error<<llendl;
++       }
++
++       alGenSources(1,wind_sources);
++
++       if((error=alGetError()) != AL_NO_ERROR)
++       {
++               llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<<error<<llendl;
++       }
++
++       winddata=(S16*)malloc(sizeof(S16)*44100*0.2*2*2); //200ms @44100Hz Stereo
++
++       if(winddata==NULL)
++       {
++               llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl;
++               mEnableWind=FALSE;
++       }
++
++       llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl;
++#endif
++}
++
++void LLAudioEngine_OpenAL::cleanupWind(){
++#if LL_OPENAL_WIND
++       llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl;
++
++       alDeleteBuffers(NO_WIND_BUFFERS,wind_buffers);
++
++       alDeleteSources(1, wind_sources);
++
++       if(winddata)
++               free(winddata);
++#endif
++}
++
++void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude){
++#if LL_OPENAL_WIND
++       LLVector3 wind_pos;
++       F64 pitch;
++       F64 center_freq;
++       ALenum error;
++
++       mMaxWindGain=1.0;
++
++       if (!mEnableWind)
++               return;
++
++       if(!winddata)
++               return;
++
++       if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
++       {
++
++               // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up)
++               // need to convert this to the conventional orientation DS3D and OpenAL use
++               // where +X = right, +Y = up, +Z = backwards
++
++               wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
++
++               // cerr << "Wind update" << endl;
++
++               pitch = 1.0 + mapWindVecToPitch(wind_vec);
++               center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
++
++               gTargetFreq = (F32)center_freq;
++               gTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
++               gTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
++
++               ALfloat source0Pos[]={mListenerp->getPosition().mV[0],mListenerp->getPosition().mV[1],mListenerp->getPosition().mV[2]};
++
++               alSourcef(wind_sources[0], AL_GAIN, gTargetGain);
++               alSourcef(wind_sources[0], AL_PITCH, pitch);
++               alSourcefv(wind_sources[0], AL_POSITION, source0Pos);
++               alSourcefv(wind_sources[0], AL_VELOCITY, source0Vel);
++               alSourcei(wind_sources[0], AL_LOOPING, AL_FALSE);
++
++       }
++
++       // ok lets make a wind buffer now
++
++       if(first_wind==TRUE)
++       {
++               llinfos << "LLAudioEngine_OpenAL::updateWind() making first buffer" << llendl;
++               alGetError(); /* clear error */
++
++               for(int counter=0;counter<NO_WIND_BUFFERS;counter++)
++               {
++                       alBufferData(wind_buffers[counter],AL_FORMAT_STEREO16,windDSP((void*)winddata,2*44100*0.02),2*44100*0.02*sizeof(U16),44100);
++                       if((error=alGetError()) != AL_NO_ERROR)
++                       {
++                               llwarns << "LLAudioEngine_OpenAL::initWind() Error creating INITAL WIND BUFFER 1: "<<error<<llendl;
++                       }
++               }
++
++               alSourceQueueBuffers(wind_sources[0], NO_WIND_BUFFERS, wind_buffers);
++
++               alSourcePlay(wind_sources[0]);
++               if((error=alGetError()) != AL_NO_ERROR)
++               {
++                       llwarns << "LLAudioEngine_OpenAL::initWind() Error inital wind play: "<<error<<llendl;
++               }
++
++               first_wind=FALSE;
++               llinfos << "LLAudioEngine_OpenAL::updateWind() making first buffer DONE!" << llendl;
++
++       }
++       else
++       {
++               int processed;
++               alGetSourcei(wind_sources[0], AL_BUFFERS_PROCESSED, &processed);
++
++               while(processed--)
++               {
++                       ALuint buffer;
++                       int error;
++                       alSourceUnqueueBuffers(wind_sources[0], 1, &buffer);
++                       error = alGetError();
++                       if(error != AL_NO_ERROR)
++                               llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping buffers" << llendl;
++
++                       alBufferData(buffer,AL_FORMAT_STEREO16,windDSP((void*)winddata,44100*0.2),2*44100*0.2*sizeof(U16),44100);
++                       error = alGetError();
++                       if(error != AL_NO_ERROR)
++                               llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping buffers" << llendl;
++
++
++                       alSourceQueueBuffers(wind_sources[0], 1, &buffer);
++                       error = alGetError();
++                       if(error != AL_NO_ERROR)
++                               llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping buffers" << llendl;
++
++
++               }
++
++               int playing;
++               alGetSourcei(wind_sources[0], AL_SOURCE_STATE, &playing);
++
++               if(playing==AL_STOPPED)
++                       alSourcePlay(wind_sources[0]);
++
++       }
++#endif //LL_OPENAL_WIND
++}
++
++inline S16 clipSample(S16 sample, S16 min, S16 max)
++{
++#if LL_OPENAL_WIND
++       if (sample > max)
++               sample = max;
++       else if (sample < min)
++               sample = min;
++
++#endif
++       return sample;
++}
++
++void * LLAudioEngine_OpenAL::windDSP(void *newbuffer, int length)
++{
++#if LL_OPENAL_WIND
++       // newbuffer = the buffer passed from the previous DSP unit.
++       // length = length in samples at this mix time.
++
++       U8 *cursamplep = (U8*)newbuffer;
++       U8   wordsize = 2;
++
++       double bandwidth = 50;
++       double inputSamplingRate = 44100;
++       double a0,b1,b2;
++
++       // calculate resonant filter coeffs
++       b2 = exp(-(F_TWO_PI) * (bandwidth / inputSamplingRate));
++
++       while (length--)
++       {
++               gCurrentFreq = (float)((0.999 * gCurrentFreq) + (0.001 * gTargetFreq));
++               gCurrentGain = (float)((0.999 * gCurrentGain) + (0.001 * gTargetGain));
++               gCurrentPanGainR = (float)((0.999 * gCurrentPanGainR) + (0.001 * gTargetPanGainR));
++               b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (gCurrentFreq / inputSamplingRate));
++               a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2));
++               double nextSample;
++
++           // start with white noise
++               nextSample = ll_frand(2.0f) - 1.0f;
++
++#if 1 // LLAE_WIND_PINK apply pinking filter
++               gbuf0 = 0.997f * gbuf0 + 0.0126502f * nextSample;
++               gbuf1 = 0.985f * gbuf1 + 0.0139083f * nextSample;
++               gbuf2 = 0.950f * gbuf2 + 0.0205439f * nextSample;
++               gbuf3 = 0.850f * gbuf3 + 0.0387225f * nextSample;
++               gbuf4 = 0.620f * gbuf4 + 0.0465932f * nextSample;
++               gbuf5 = 0.250f * gbuf5 + 0.1093477f * nextSample;
++
++                       nextSample = gbuf0 + gbuf1 + gbuf2 + gbuf3 + gbuf4 + gbuf5;
++#endif
++
++#if 1 //LLAE_WIND_RESONANT // do a resonant filter on the noise
++               nextSample = (double)( a0 * nextSample - b1 * gY0 - b2 * gY1 );
++
++               gY1 = gY0;
++               gY0 = nextSample;
++#endif
++               nextSample *= gCurrentGain;
++
++               S16     sample;
++
++               sample = llfloor(((F32)nextSample*32768.f*(1.0f - gCurrentPanGainR))+0.5f);
++               *(S16*)cursamplep = clipSample(sample, -32768, 32767);
++
++               cursamplep += wordsize;
++
++               sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f);
++
++               sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f);
++               *(S16*)cursamplep = clipSample(sample, -32768, 32767);
++               cursamplep += wordsize;
++       }
++
++#endif //LL_OPENAL_WIND
++       return newbuffer;
++}
++
++// ------------
++
++void LLAudioEngine_OpenAL::InitStreamer()
++{
++#if LL_GSTREAMER_ENABLED
++       m_streamer=new LLMediaImplGStreamer ();
++
++       if(!m_streamer)
++       {
++               llwarns << "LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() Failed to create our private gstreamer audio instance" << llendl;
++       }
++
++       if(m_streamer)
++       {
++               m_streamer->init ();
++       }
++#endif
++}
++
++// ------------
++
++void LLAudioEngine_OpenAL::initInternetStream(){
++	if(!mInternetStreamURL.empty())
++		mInternetStreamURL.erase();
++}
++
++void LLAudioEngine_OpenAL::startInternetStream(const std::string& url){
++
++#if LL_GSTREAMER_ENABLED
++	if(!m_streamer)
++		return;
++// DCF_DEBUG
++llinfos << "entered LLAudioEngine_OpenAL::startInternetStream()" << llendl;
++	
++
++	if (!url.empty()) {
++		llinfos << "LLAudioEngine_OpenAL::startInternetStream() Starting internet stream: " << url << llendl;
++		mInternetStreamURL=url;
++		m_streamer->navigateTo ( url );
++		llinfos << "Playing....." << llendl;		
++		m_streamer->addCommand(LLMediaBase::COMMAND_START);
++		m_streamer->updateMedia();
++
++	}else{
++		llinfos << "LLAudioEngine_OpenAL setting stream to NULL"<< llendl;
++		mInternetStreamURL.erase();
++		m_streamer->addCommand(LLMediaBase::COMMAND_STOP);
++		m_streamer->updateMedia();
++	}
++#endif
++}
++
++void LLAudioEngine_OpenAL::updateInternetStream(){
++// DCF_DEBUG
++llinfos << "entered LLAudioEngine_OpenAL::updateInternetStream()" << llendl;
++	
++}
++
++void LLAudioEngine_OpenAL::stopInternetStream(){
++// DCF_DEBUG
++llinfos << "entered LLAudioEngine_OpenAL::stopInternetStream()" << llendl;
++	
++#if LL_GSTREAMER_ENABLED
++	if( ! m_streamer->addCommand(LLMediaBase::COMMAND_STOP)){
++		llinfos << "attempting to stop stream failed!" << llendl;
++	}
++	m_streamer->updateMedia();
++#endif
++	mInternetStreamURL.erase();
++}
++
++void LLAudioEngine_OpenAL::pauseInternetStream(int pause){
++#if LL_GSTREAMER_ENABLED
++	if(!m_streamer)
++		return;
++// DCF_DEBUG
++llinfos << "entered LLAudioEngine_OpenAL::pauseInternetStream()" << llendl;
++	
++	if(pause){
++		if(!m_streamer->addCommand(LLMediaBase::COMMAND_PAUSE)){
++			llinfos << "attempting to pause stream failed!" << llendl;
++		}
++		m_streamer->updateMedia();
++	}else{
++		if( ! m_streamer->addCommand(LLMediaBase::COMMAND_START)){
++			llinfos << "attempting to pause stream failed!" << llendl;
++		}
++		m_streamer->updateMedia();
++	}
++#endif
++}
++
++int LLAudioEngine_OpenAL::isInternetStreamPlaying(){
++
++#if LL_GSTREAMER_ENABLED
++	if(!m_streamer)
++		return 0;
++	
++	if(m_streamer->getStatus() == LLMediaBase::STATUS_STARTED)
++	{
++		return 1; // Active and playing
++	}	
++
++	if(m_streamer->getStatus() == LLMediaBase::STATUS_PAUSED)
++	{
++		return 2; // paused
++	}
++#endif
++	return 0; // Stopped
++}
++
++void LLAudioEngine_OpenAL::getInternetStreamInfo(char* artist_out, char* title_out){
++}
++
++void LLAudioEngine_OpenAL::setInternetStreamGain(F32 vol){
++#if LL_GSTREAMER_ENABLED
++	// Set the gstreamer volume here
++	if(!m_streamer)
++		return;
++
++	vol = llclamp(vol, 0.f, 1.f);
++	m_streamer->setVolume(vol);
++	m_streamer->updateMedia();
++
++#endif
++}
++
++const std::string& LLAudioEngine_OpenAL::getInternetStreamURL(){
++	return mInternetStreamURL;
++}
++
+diff --git a/indra/llaudio/audioengine_openal.h b/indra/llaudio/audioengine_openal.h
+new file mode 100644
+index 0000000..604e8eb
+--- /dev/null
++++ b/indra/llaudio/audioengine_openal.h
+@@ -0,0 +1,123 @@
++/**
++ * @file audioengine_openal.cpp
++ * @brief implementation of audio engine using OpenAL
++ * support as a OpenAL 3D implementation
++ *
++ * Copyright (c) 2002-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.
++ */
++
++
++#ifndef LL_AUDIOENGINE_OpenAL_H
++#define LL_AUDIOENGINE_OpenAL_H
++
++#undef XMLCALL
++
++#include <string>
++
++#include "audioengine.h"
++#include "listener_openal.h"
++
++
++#if LL_GSTREAMER_ENABLED
++#include "llmediamanager.h"
++#include "llmediaimplgstreamer.h"
++#endif
++
++#include "llrand.h"
++
++class LLAudioEngine_OpenAL : public LLAudioEngine{
++	public:
++		LLAudioEngine_OpenAL();
++		virtual ~LLAudioEngine_OpenAL();
++
++		virtual BOOL init(const S32 num_channels, void *user_data);
++		virtual void allocateListener();
++
++		virtual void shutdown();
++
++		virtual void idle(F32 max_decode_time = 0.f);
++
++		void setInternalGain(F32 gain);
++
++		LLAudioBuffer* createBuffer();
++		LLAudioChannel* createChannel();
++
++		// Internet stream methods
++		virtual void initInternetStream();
++		virtual void startInternetStream(const std::string& url);
++		virtual void stopInternetStream();
++		virtual void updateInternetStream();
++		virtual void pauseInternetStream(int pause);
++		virtual int isInternetStreamPlaying();
++		virtual void getInternetStreamInfo(char* artist, char* title);
++		virtual void setInternetStreamGain(F32 vol);
++		virtual const std::string& getInternetStreamURL();
++		virtual void InitStreamer();
++
++		void initWind();
++		void cleanupWind();
++		void updateWind(LLVector3 direction, F32 camera_altitude);
++
++	protected:
++		std::string mInternetStreamURL;
++		void * windDSP(void *newbuffer, int length);
++#if LL_GSTREAMER_ENABLED
++		LLMediaManagerData * mMedia_data;
++		LLMediaImplGStreamer * m_streamer;
++#endif
++};
++
++class LLAudioChannelOpenAL : public LLAudioChannel{
++	public:
++		LLAudioChannelOpenAL();
++		virtual ~LLAudioChannelOpenAL();
++	protected:
++		void play();
++		void playSynced(LLAudioChannel *channelp);
++		void cleanup();
++		BOOL isPlaying();
++
++		BOOL updateBuffer();
++		void update3DPosition();
++		void updateLoop(){};
++
++		ALuint ALSource;
++};
++
++class LLAudioBufferOpenAL : public LLAudioBuffer{
++	public:
++		LLAudioBufferOpenAL();
++		virtual ~LLAudioBufferOpenAL();
++
++		BOOL loadWAV(const std::string& filename);
++		U32 getLength();
++
++		friend class LLAudioChannelOpenAL;
++	protected:
++		void cleanup();
++		ALuint getBuffer(){return ALBuffer;}
++		ALuint ALBuffer;
++};
++
++#endif
+diff --git a/indra/llaudio/listener_openal.cpp b/indra/llaudio/listener_openal.cpp
+new file mode 100644
+index 0000000..e4c6f64
+--- /dev/null
++++ b/indra/llaudio/listener_openal.cpp
+@@ -0,0 +1,95 @@
++/**
++ * @file audioengine_openal.cpp
++ * @brief implementation of audio engine using OpenAL
++ * support as a OpenAL 3D implementation
++ *
++ * Copyright (c) 2002-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.
++ */
++
++#include "linden_common.h"
++#include "audioengine.h"
++
++#include "listener_openal.h"
++
++LLListener_OpenAL::LLListener_OpenAL(){
++	init();
++}
++
++LLListener_OpenAL::~LLListener_OpenAL(){
++}
++
++void LLListener_OpenAL::translate(LLVector3 offset){
++	LLListener::translate(offset);
++	llinfos << "LLListener_OpenAL::translate() : " << offset << llendl;
++}
++
++void LLListener_OpenAL::setPosition(LLVector3 pos){
++	LLListener::setPosition(pos);
++	//llinfos << "LLListener_OpenAL::setPosition() : " << pos << llendl;
++}
++
++void LLListener_OpenAL::setVelocity(LLVector3 vel){
++	LLListener::setVelocity(vel);
++}
++
++void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at){
++	LLListener::orient(up, at);
++	//llinfos << "LLListener_OpenAL::orient() up: " << up << " at: " << at << llendl;
++}
++
++void LLListener_OpenAL::commitDeferredChanges(){
++	ALfloat orientation[6];
++	orientation[0] = mListenAt.mV[0];
++	orientation[1] = mListenAt.mV[1];
++	orientation[2] = mListenAt.mV[2];
++	orientation[3] = mListenUp.mV[0];
++	orientation[4] = mListenUp.mV[1];
++	orientation[5] = mListenUp.mV[2];
++
++	// Why is this backwards?
++	ALfloat velocity[3];
++	velocity[0] = -mVelocity.mV[0];
++	velocity[1] = -mVelocity.mV[1];
++	velocity[2] = -mVelocity.mV[2];
++
++	alListenerfv(AL_ORIENTATION, orientation);
++	alListenerfv(AL_POSITION, mPosition.mV);
++	alListenerfv(AL_VELOCITY, velocity);
++}
++
++void LLListener_OpenAL::setDopplerFactor(F32 factor){
++	// Effect is way too strong by default, scale it down here.
++	// Scaling the speed of sound up causes crashes.
++	factor *= 0.01f;
++	//llinfos << "LLListener_OpenAL::setDopplerFactor() : " << factor << llendl;
++	alDopplerFactor(factor);
++}
++
++F32 LLListener_OpenAL::getDopplerFactor(){
++	ALfloat factor=0;
++	alDopplerFactor(factor);
++	llinfos << "LLListener_OpenAL::getDopplerFactor() : " << factor << llendl;
++	return factor;
++}
++
+diff --git a/indra/llaudio/listener_openal.h b/indra/llaudio/listener_openal.h
+index e6c9324..beed15b 100644
+--- a/indra/llaudio/listener_openal.h
++++ b/indra/llaudio/listener_openal.h
+@@ -54,6 +54,10 @@ class LLListener_OpenAL  : public LLListener
+ 	virtual void setPosition(LLVector3 pos);
+ 	virtual void setVelocity(LLVector3 vel);
+ 	virtual void orient(LLVector3 up, LLVector3 at);
++	virtual void commitDeferredChanges();
++
++	virtual void setDopplerFactor(F32 factor);
++	virtual F32 getDopplerFactor();
+ };
+ 
+ #endif
+diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
+index 7c49f72..77a1dc5 100644
+--- a/indra/newview/CMakeLists.txt
++++ b/indra/newview/CMakeLists.txt
+@@ -9,6 +9,7 @@ include(DBusGlib)
+ include(DirectX)
+ include(ELFIO)
+ include(FMOD)
++include(OPENAL)
+ include(FindOpenGL)
+ include(LLAudio)
+ include(LLCharacter)
+@@ -57,6 +58,7 @@ include_directories(
+     ${LLXML_INCLUDE_DIRS}
+     ${LSCRIPT_INCLUDE_DIRS}
+     ${LSCRIPT_INCLUDE_DIRS}/lscript_compile
++    ${GSTREAMER_INCLUDE_DIRS}
+     )
+ 
+ set(viewer_SOURCE_FILES
+@@ -1246,6 +1248,10 @@ set_source_files_properties(${viewer_CHARACTER_FILES}
+ 
+ list(APPEND viewer_SOURCE_FILES ${viewer_CHARACTER_FILES})
+ 
++if (OPENAL)
++  set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS -DLL_OPENAL)
++endif (OPENAL)
++
+ if (WINDOWS)
+   file(GLOB viewer_INSTALLER_FILES installers/windows/*.nsi)
+ 
+diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
+index dd4b66c..76790ed 100644
+--- a/indra/newview/llstartup.cpp
++++ b/indra/newview/llstartup.cpp
+@@ -17,7 +17,7 @@
+  * 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
++ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexceptionOP
+  * 
+  * By copying, modifying or distributing this software, you acknowledge
+  * that you have read and understood your obligations described above,
+@@ -45,6 +45,10 @@
+ # include "audioengine_fmod.h"
+ #endif
+ 
++#ifdef LL_OPENAL
++#include "audioengine_openal.h"
++#endif
++
+ #include "llares.h"
+ #include "llcachename.h"
+ #include "llviewercontrol.h"
+@@ -581,10 +585,14 @@ bool idle_startup()
+ 
+ 		if (FALSE == gSavedSettings.getBOOL("NoAudio"))
+ 		{
++			gAudiop = NULL;
++
+ #ifdef LL_FMOD
+ 			gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD();
+-#else
+-			gAudiop = NULL;
++#endif
++
++#ifdef LL_OPENAL
++			gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL();
+ #endif
+ 
+ 			if (gAudiop)
+-- 
+tg: (fd717f3..) topic/features/jira-sent/openal_1.21.0 (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-backported/VWR-11068_fix_spill_over_menus_small_window.diff b/debian/patches/topic/fixes/jira-backported/VWR-11068_fix_spill_over_menus_small_window.diff
new file mode 100644
index 0000000..98ea06f
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-backported/VWR-11068_fix_spill_over_menus_small_window.diff
@@ -0,0 +1,67 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-backported/VWR-11068_fix_spill_over_menus_small_window
+
+<patch description>
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llui/llmenugl.cpp |   17 ++++++++++++++++-
+ 1 files changed, 16 insertions(+), 1 deletions(-)
+
+diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
+index 907777d..de12420 100644
+--- a/indra/llui/llmenugl.cpp
++++ b/indra/llui/llmenugl.cpp
+@@ -2267,6 +2267,9 @@ void LLMenuGL::arrange( void )
+ 				(*item_iter)->buildDrawLabel();
+ 			}
+ 		}
++
++		delete mSpilloverMenu;
++		mSpilloverMenu = NULL;
+ 	}
+ 	if (mKeepFixedSize)
+ 	{
+@@ -2295,7 +2298,8 @@ void LLMenuGL::createSpilloverBranch()
+ 
+ void LLMenuGL::cleanupSpilloverBranch()
+ {
+-	if (mSpilloverBranch && mSpilloverBranch->getParent() == this)
++	if (mSpilloverBranch)
++	if(mSpilloverBranch->getParent() == this)
+ 	{
+ 		// head-recursion to propagate items back up to root menu
+ 		mSpilloverMenu->cleanupSpilloverBranch();
+@@ -2468,6 +2472,11 @@ BOOL LLMenuGL::handleJumpKey(KEY key)
+ // Add the menu item to this menu.
+ BOOL LLMenuGL::append( LLMenuItemGL* item )
+ {
++	if (mSpilloverMenu)
++	{
++		return mSpilloverMenu->append(item);
++	}
++
+ 	mItems.push_back( item );
+ 	addChild( item );
+ 	arrange();
+@@ -2758,11 +2767,17 @@ void LLMenuGL::updateParent(LLView* parentp)
+ 		getParent()->removeChild(this);
+ 	}
+ 	parentp->addChild(this);
++
+ 	item_list_t::iterator item_iter;
+ 	for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
+ 	{
+ 		(*item_iter)->updateBranchParent(parentp);
+ 	}
++
++	if (mSpilloverMenu)
++	{
++		mSpilloverMenu->updateParent(parentp);
++	}
+ }
+ 
+ BOOL LLMenuGL::handleAcceleratorKey(KEY key, MASK mask)
+-- 
+tg: (fd717f3..) topic/fixes/jira-backported/VWR-11068_fix_spill_over_menus_small_window (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-backported/VWR-11103-FIx_local_ruler_on_linked_objects.diff b/debian/patches/topic/fixes/jira-backported/VWR-11103-FIx_local_ruler_on_linked_objects.diff
new file mode 100644
index 0000000..9301488
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-backported/VWR-11103-FIx_local_ruler_on_linked_objects.diff
@@ -0,0 +1,28 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-backported/VWR-11103-FIx_local_ruler_on_linked_objects
+
+<patch description>
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/newview/llselectmgr.cpp |    4 ++++
+ 1 files changed, 4 insertions(+), 0 deletions(-)
+
+diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
+index e891599..41ca2a9 100644
+--- a/indra/newview/llselectmgr.cpp
++++ b/indra/newview/llselectmgr.cpp
+@@ -5499,6 +5499,10 @@ void LLSelectMgr::updateSelectionCenter()
+ 
+ 		std::vector < LLViewerObject *> jointed_objects;
+ 
++		// Initialize the bounding box to the root prim, so the BBox orientation
++		// matches the root prim's (affecting the orientation of the manipulators).
++		bbox.addBBoxAgent( (mSelectedObjects->getFirstRootObject(TRUE))->getBoundingBoxAgent() );
++
+ 		for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
+ 			 iter != mSelectedObjects->end(); iter++)
+ 		{
+-- 
+tg: (fd717f3..) topic/fixes/jira-backported/VWR-11103-FIx_local_ruler_on_linked_objects (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-backported/VWR-11674_dont_download_muted_sounds.diff b/debian/patches/topic/fixes/jira-backported/VWR-11674_dont_download_muted_sounds.diff
new file mode 100644
index 0000000..2dc9c73
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-backported/VWR-11674_dont_download_muted_sounds.diff
@@ -0,0 +1,62 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-backported/VWR-11674_dont_download_muted_sounds
+
+<patch description>
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llaudio/audioengine.cpp     |    3 ++-
+ indra/newview/llviewermessage.cpp |    9 ++++++++-
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/indra/llaudio/audioengine.cpp b/indra/llaudio/audioengine.cpp
+index 81536cf..f18d401 100644
+--- a/indra/llaudio/audioengine.cpp
++++ b/indra/llaudio/audioengine.cpp
+@@ -739,7 +739,8 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i
+ 	// Create a new source (since this can't be associated with an existing source.
+ 	//llinfos << "Localized: " << audio_uuid << llendl;
+ 
+-	if (mMuted)
++	//If we cannot hear it, dont even try to load the sound.
++	if (mMuted || gain == 0.0)
+ 	{
+ 		return;
+ 	}
+diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
+index 461a598..1e4d8d2 100644
+--- a/indra/newview/llviewermessage.cpp
++++ b/indra/newview/llviewermessage.cpp
+@@ -3285,6 +3285,10 @@ void process_sound_trigger(LLMessageSystem *msg, void **)
+ 	msg->getVector3Fast(_PREHASH_SoundData, _PREHASH_Position, pos_local);
+ 	msg->getF32Fast(_PREHASH_SoundData, _PREHASH_Gain, gain);
+ 
++	//If we have sounds muted, don't even try to load or trigger the sound.
++	if(gSavedSettings.getBOOL("MuteSounds") || gain == 0.0)
++		return;
++
+ 	// adjust sound location to true global coords
+ 	LLVector3d	pos_global = from_region_handle(region_handle);
+ 	pos_global.mdV[VX] += pos_local.mV[VX];
+@@ -3313,7 +3317,7 @@ void process_sound_trigger(LLMessageSystem *msg, void **)
+ 
+ void process_preload_sound(LLMessageSystem *msg, void **user_data)
+ {
+-	if (!gAudiop)
++	if (!gAudiop || gSavedSettings.getBOOL("MuteSounds"))
+ 	{
+ 		return;
+ 	}
+@@ -3359,6 +3363,9 @@ void process_attached_sound(LLMessageSystem *msg, void **user_data)
+ 	msg->getF32Fast(_PREHASH_DataBlock, _PREHASH_Gain, gain);
+ 	msg->getU8Fast(_PREHASH_DataBlock, _PREHASH_Flags, flags);
+ 
++	if(gSavedSettings.getBOOL("MuteSounds") || gain == 0.0)
++		return;
++
+ 	LLViewerObject *objectp = gObjectList.findObject(object_id);
+ 	if (!objectp)
+ 	{
+-- 
+tg: (fd717f3..) topic/fixes/jira-backported/VWR-11674_dont_download_muted_sounds (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-backported/VWR-3766_llGetInventoryNumber_tooltip_missing_INVENTORY_ANIMATION.diff b/debian/patches/topic/fixes/jira-backported/VWR-3766_llGetInventoryNumber_tooltip_missing_INVENTORY_ANIMATION.diff
new file mode 100644
index 0000000..6b8abae
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-backported/VWR-3766_llGetInventoryNumber_tooltip_missing_INVENTORY_ANIMATION.diff
@@ -0,0 +1,26 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-backported/VWR-3766_llGetInventoryNumber_tooltip_missing_INVENTORY_ANIMATION
+
+Apply correct tooltips for script editing, adding some missing defines
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/lscript/lscript_library/lscript_library.cpp |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp
+index 2ac45f0..9ce0d2a 100644
+--- a/indra/lscript/lscript_library/lscript_library.cpp
++++ b/indra/lscript/lscript_library/lscript_library.cpp
+@@ -221,7 +221,7 @@ void LLScriptLibrary::init()
+ 	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llBreakAllLinks", NULL, NULL, "llBreakAllLinks()\nDelinks all tasks in the link set (requires permission PERMISSION_CHANGE_LINKS be set)"));
+ 	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetLinkKey", "k", "i", "key llGetLinkKey(integer linknum)\nGet the key of linknumber in link set"));
+ 	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetLinkName", "s", "i", "string llGetLinkName(integer linknum)\nGet the name of linknumber in link set"));
+-	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetInventoryNumber", "i", "i", "integer llGetInventoryNumber(integer type)\nGet the number of items of a given type in the task's inventory.\nValid types: INVENTORY_TEXTURE, INVENTORY_SOUND, INVENTORY_OBJECT, INVENTORY_SCRIPT, INVENTORY_CLOTHING, INVENTORY_BODYPART, INVENTORY_NOTECARD, INVENTORY_LANDMARK, INVENTORY_ALL"));
++	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetInventoryNumber", "i", "i", "integer llGetInventoryNumber(integer type)\nGet the number of items of a given type in the task's inventory.\nValid types: INVENTORY_TEXTURE, INVENTORY_SOUND, INVENTORY_OBJECT, INVENTORY_SCRIPT, INVENTORY_CLOTHING, INVENTORY_BODYPART, INVENTORY_NOTECARD, INVENTORY_LANDMARK, INVENTORY_ANIMATION, INVENTORY_GESTURE, INVENTORY_ALL"));
+ 	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetInventoryName", "s", "ii", "string llGetInventoryName(integer type, integer number)\nGet the name of the inventory item number of type"));
+ 	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetScriptState", NULL, "si", "llSetScriptState(string name, integer run)\nControl the state of a script name."));
+ 	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetEnergy", "f", NULL, "float llGetEnergy()\nReturns how much energy is in the object as a percentage of maximum"));
+-- 
+tg: (fd717f3..) topic/fixes/jira-backported/VWR-3766_llGetInventoryNumber_tooltip_missing_INVENTORY_ANIMATION (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-backported/VWR5717_text_not_replaced_by_input_with_japanses_im.diff b/debian/patches/topic/fixes/jira-backported/VWR5717_text_not_replaced_by_input_with_japanses_im.diff
new file mode 100644
index 0000000..0620210
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-backported/VWR5717_text_not_replaced_by_input_with_japanses_im.diff
@@ -0,0 +1,70 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-backported/VWR5717_text_not_replaced_by_input_with_japanses_im
+
+Fix to allow Japanese input, taken from VWR-5717
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llui/lllineeditor.cpp |   12 +++++++++---
+ indra/llui/lltexteditor.cpp |   12 +++++++++---
+ 2 files changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
+index 64b1284..da633dd 100644
+--- a/indra/llui/lllineeditor.cpp
++++ b/indra/llui/lllineeditor.cpp
+@@ -2370,14 +2370,20 @@ BOOL LLLineEditor::hasPreeditString() const
+ 
+ void LLLineEditor::resetPreedit()
+ {
+-	if (hasPreeditString())
++	if (hasSelection())
+ 	{
+-		if (hasSelection())
++		if (hasPreeditString())
+ 		{
+ 			llwarns << "Preedit and selection!" << llendl;
+ 			deselect();
+ 		}
+-
++		else
++		{
++			deleteSelection();
++		}
++	}
++	if (hasPreeditString())
++	{
+ 		const S32 preedit_pos = mPreeditPositions.front();
+ 		mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos);
+ 		mText.insert(preedit_pos, mPreeditOverwrittenWString);
+diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
+index a40fec8..f14244d 100644
+--- a/indra/llui/lltexteditor.cpp
++++ b/indra/llui/lltexteditor.cpp
+@@ -4410,14 +4410,20 @@ BOOL LLTextEditor::hasPreeditString() const
+ 
+ void LLTextEditor::resetPreedit()
+ {
+-	if (hasPreeditString())
++	if (hasSelection())
+ 	{
+-		if (hasSelection())
++		if (hasPreeditString())
+ 		{
+ 			llwarns << "Preedit and selection!" << llendl;
+ 			deselect();
+ 		}
+-
++		else
++		{
++			deleteSelection(FALSE);
++		}
++	}
++	if (hasPreeditString())
++	{
+ 		mCursorPos = mPreeditPositions.front();
+ 		removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos);
+ 		insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString);
+-- 
+tg: (fd717f3..) topic/fixes/jira-backported/VWR5717_text_not_replaced_by_input_with_japanses_im (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-backported/glh_linear.diff b/debian/patches/topic/fixes/jira-backported/glh_linear.diff
new file mode 100644
index 0000000..002ed8b
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-backported/glh_linear.diff
@@ -0,0 +1,1640 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/fixes/jira-backported/glh_linear
+
+Adds the missing glh_linear.h header.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/llwindow/glh/glh_linear.h | 1621 +++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 1621 insertions(+), 0 deletions(-)
+
+diff --git a/indra/llwindow/glh/glh_linear.h b/indra/llwindow/glh/glh_linear.h
+new file mode 100644
+index 0000000..04ae1bd
+--- /dev/null
++++ b/indra/llwindow/glh/glh_linear.h
+@@ -0,0 +1,1621 @@
++/*
++    glh - is a platform-indepenedent C++ OpenGL helper library 
++
++
++    Copyright (c) 2000 Cass Everitt
++	Copyright (c) 2000 NVIDIA Corporation
++    All rights reserved.
++
++    Redistribution and use in source and binary forms, with or
++	without modification, are permitted provided that the following
++	conditions are met:
++
++     * Redistributions of source code must retain the above
++	   copyright notice, this list of conditions and the following
++	   disclaimer.
++
++     * Redistributions in binary form must reproduce the above
++	   copyright notice, this list of conditions and the following
++	   disclaimer in the documentation and/or other materials
++	   provided with the distribution.
++
++     * The names of contributors to this software may not be used
++	   to endorse or promote products derived from this software
++	   without specific prior written permission. 
++
++       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++	   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++	   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++	   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++	   REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
++	   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
++	   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++	   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
++	   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++	   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
++	   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
++	   POSSIBILITY OF SUCH DAMAGE. 
++
++
++    Cass Everitt - cass at r3.nu
++*/
++
++/*
++glh_linear.h
++*/
++
++// Author:  Cass W. Everitt
++
++#ifndef GLH_LINEAR_H
++#define GLH_LINEAR_H
++
++#include <memory.h>
++#include <math.h>
++#include <assert.h>
++
++// only supports float for now...
++#define GLH_REAL_IS_FLOAT
++
++#ifdef GLH_REAL_IS_FLOAT
++# define GLH_REAL float
++# define GLH_REAL_NAMESPACE ns_float
++#endif
++
++#define     GLH_QUATERNION_NORMALIZATION_THRESHOLD  64
++
++#define     GLH_RAD_TO_DEG      GLH_REAL(57.2957795130823208767981548141052)
++#define     GLH_DEG_TO_RAD      GLH_REAL(0.0174532925199432957692369076848861)
++#define     GLH_ZERO            GLH_REAL(0.0)
++#define     GLH_ONE             GLH_REAL(1.0)
++#define     GLH_TWO             GLH_REAL(2.0)
++#define     GLH_EPSILON         GLH_REAL(10e-6)
++#define     GLH_PI              GLH_REAL(3.1415926535897932384626433832795)    
++
++#define     equivalent(a,b)     (((a < b + GLH_EPSILON) && (a > b - GLH_EPSILON)) ? true : false)
++
++namespace glh
++{
++
++	inline GLH_REAL to_degrees(GLH_REAL radians) { return radians*GLH_RAD_TO_DEG; }
++	inline GLH_REAL to_radians(GLH_REAL degrees) { return degrees*GLH_DEG_TO_RAD; }
++
++	// forward declarations for friend template functions.
++	template <int N, class T> class vec;
++	
++	// forward declarations for friend template functions.
++	template <int N, class T>
++		bool operator == ( const vec<N,T> & v1, const vec<N,T> & v2 );
++	
++	// forward declarations for friend template functions.
++	template <int N, class T>
++		bool operator != ( const vec<N,T> & v1, const vec<N,T> & v2 );
++
++	template <int N, class T>	
++	class vec
++	{				
++    public:
++		int size() const { return N; }
++		
++		vec(const T & t = T()) 
++		{ for(int i = 0; i < N; i++) v[i] = t; }
++		vec(const T * tp)
++		{ for(int i = 0; i < N; i++) v[i] = tp[i]; }
++		
++		const T * get_value() const
++		{ return v; }
++		
++		
++		T dot( const vec<N,T> & rhs ) const
++		{ 
++			T r = 0;
++			for(int i = 0; i < N; i++) r += v[i]*rhs.v[i];
++			return r;
++		}
++		
++		T length() const
++		{
++			T r = 0;
++			for(int i = 0; i < N; i++) r += v[i]*v[i]; 
++			return T(sqrt(r));
++		}	
++		
++		T square_norm() const
++		{
++			T r = 0;
++			for(int i = 0; i < N; i++) r += v[i]*v[i]; 
++			return r;
++		}	
++		
++		void  negate()
++		{ for(int i = 0; i < N; i++) v[i] = -v[i]; }
++		
++		
++		T normalize() 
++		{ 
++			T sum(0);
++			for(int i = 0; i < N; i++) 
++                sum += v[i]*v[i];
++			sum = T(sqrt(sum));
++            if (sum > GLH_EPSILON)
++			    for(int i = 0; i < N; i++) 
++                    v[i] /= sum;
++			return sum;
++		}
++		
++		
++		vec<N,T> & set_value( const T * rhs )
++		{ for(int i = 0; i < N; i++) v[i] = rhs[i]; return *this; }
++		
++		T & operator [] ( int i )
++		{ return v[i]; }
++		
++		const T & operator [] ( int i ) const
++		{ return v[i]; }
++
++		vec<N,T> & operator *= ( T d )
++		{ for(int i = 0; i < N; i++) v[i] *= d; return *this;}
++		
++		vec<N,T> & operator *= ( const vec<N,T> & u )
++		{ for(int i = 0; i < N; i++) v[i] *= u[i]; return *this;}
++		
++		vec<N,T> & operator /= ( T d )
++		{ if(d == 0) return *this; for(int i = 0; i < N; i++) v[i] /= d; return *this;}
++		
++		vec<N,T> & operator += ( const vec<N,T> & u )
++		{ for(int i = 0; i < N; i++) v[i] += u.v[i]; return *this;}
++		
++		vec<N,T> & operator -= ( const vec<N,T> & u )
++		{ for(int i = 0; i < N; i++) v[i] -= u.v[i]; return *this;}
++		
++		
++		vec<N,T> operator - () const
++		{ vec<N,T> rv = v; rv.negate(); return rv; }
++		
++		vec<N,T> operator + ( const vec<N,T> &v) const
++		{ vec<N,T> rt(*this); return rt += v; }
++		
++		vec<N,T> operator - ( const vec<N,T> &v) const
++		{ vec<N,T> rt(*this); return rt -= v; }
++		
++		vec<N,T> operator * ( T d) const
++		{ vec<N,T> rt(*this); return rt *= d; }
++		
++		friend bool operator == <> ( const vec<N,T> &v1, const vec<N,T> &v2 );
++		friend bool operator != <> ( const vec<N,T> &v1, const vec<N,T> &v2 );
++		
++		
++	//protected:
++		T v[N];
++	};
++	
++	
++	
++	// vector friend operators
++	
++	template <int N, class T> inline
++		vec<N,T> operator * ( const vec<N,T> & b, T d )
++	{
++		vec<N,T> rt(b);
++		return rt *= d;
++	}
++
++	template <int N, class T> inline
++		vec<N,T> operator * ( T d, const vec<N,T> & b )
++	{ return b*d; }
++	
++	template <int N, class T> inline
++		vec<N,T> operator * ( const vec<N,T> & b, const vec<N,T> & d )
++	{
++		vec<N,T> rt(b);
++		return rt *= d;
++	}
++
++	template <int N, class T> inline
++		vec<N,T> operator / ( const vec<N,T> & b, T d )
++	{ vec<N,T> rt(b); return rt /= d; }
++	
++	template <int N, class T> inline
++		vec<N,T> operator + ( const vec<N,T> & v1, const vec<N,T> & v2 )
++	{ vec<N,T> rt(v1); return rt += v2; }
++	
++	template <int N, class T> inline
++		vec<N,T> operator - ( const vec<N,T> & v1, const vec<N,T> & v2 )
++	{ vec<N,T> rt(v1); return rt -= v2; }
++	
++	
++	template <int N, class T> inline
++		bool operator == ( const vec<N,T> & v1, const vec<N,T> & v2 )
++	{
++		for(int i = 0; i < N; i++)
++			if(v1.v[i] != v2.v[i])
++				return false;
++			return true;
++	}
++	
++	template <int N, class T> inline
++		bool operator != ( const vec<N,T> & v1, const vec<N,T> & v2 )
++	{ return !(v1 == v2); }
++	
++
++	typedef vec<3,unsigned char> vec3ub;
++	typedef vec<4,unsigned char> vec4ub;
++
++
++
++
++
++	namespace GLH_REAL_NAMESPACE
++	{
++	typedef GLH_REAL real;
++
++	class line;
++	class plane;
++	class matrix4;
++	class quaternion;
++	typedef quaternion rotation; 
++  
++	class vec2 : public vec<2,real>
++	{
++    public:
++		vec2(const real & t = real()) : vec<2,real>(t)
++		{}
++		vec2(const vec<2,real> & t) : vec<2,real>(t)
++		{}
++		vec2(const real * tp) : vec<2,real>(tp)
++		{}
++		
++		vec2(real x, real y )
++		{ v[0] = x; v[1] = y; }
++		
++		void get_value(real & x, real & y) const
++		{ x = v[0]; y = v[1]; }
++		
++		vec2 & set_value( const real & x, const real & y)
++		{ v[0] = x; v[1] = y; return *this; }
++		
++	};
++	
++	
++	class vec3 : public vec<3,real>
++	{
++    public:
++		vec3(const real & t = real()) : vec<3,real>(t)
++		{}
++		vec3(const vec<3,real> & t) : vec<3,real>(t)
++		{}
++		vec3(const real * tp) : vec<3,real>(tp)
++		{}
++		
++		vec3(real x, real y, real z)
++		{ v[0] = x; v[1] = y; v[2] = z; }
++		
++		void get_value(real & x, real & y, real & z) const
++		{ x = v[0]; y = v[1]; z = v[2]; }
++		
++		vec3 cross( const vec3 &rhs ) const
++		{
++			vec3 rt;
++			rt.v[0] = v[1]*rhs.v[2]-v[2]*rhs.v[1];
++			rt.v[1] = v[2]*rhs.v[0]-v[0]*rhs.v[2];
++			rt.v[2] = v[0]*rhs.v[1]-v[1]*rhs.v[0];	
++			return rt;
++		}
++		
++		vec3 & set_value( const real & x, const real & y, const real & z)
++		{ v[0] = x; v[1] = y; v[2] = z; return *this; }
++		
++	};
++
++  		
++    class vec4 : public vec<4,real>
++    {
++    public:
++        vec4(const real & t = real()) : vec<4,real>(t)
++        {}
++        vec4(const vec<4,real> & t) : vec<4,real>(t)
++        {}
++
++        vec4(const vec<3,real> & t, real fourth)
++
++        { v[0] = t.v[0]; v[1] = t.v[1]; v[2] = t.v[2]; v[3] = fourth; }
++        vec4(const real * tp) : vec<4,real>(tp)
++        {}
++        vec4(real x, real y, real z, real w)
++        { v[0] = x; v[1] = y; v[2] = z; v[3] = w; }
++
++        void get_value(real & x, real & y, real & z, real & w) const
++        { x = v[0]; y = v[1]; z = v[2]; w = v[3]; }
++  
++        vec4 & set_value( const real & x, const real & y, const real & z, const real & w)
++        { v[0] = x; v[1] = y; v[2] = z; v[3] = w; return *this; }
++    };
++
++    inline
++    vec3 homogenize(const vec4 & v)
++    {
++      vec3 rt;
++      assert(v.v[3] != GLH_ZERO);
++      rt.v[0] = v.v[0]/v.v[3];
++      rt.v[1] = v.v[1]/v.v[3];
++      rt.v[2] = v.v[2]/v.v[3];
++      return rt;
++    }
++  
++
++
++    class line
++    {
++    public:
++  
++        line()
++        { set_value(vec3(0,0,0),vec3(0,0,1)); }
++
++        line( const vec3 & p0, const vec3 &p1)
++        { set_value(p0,p1); }
++
++        void set_value( const vec3 &p0, const vec3 &p1)
++        {
++          position = p0;
++          direction = p1-p0;
++          direction.normalize();
++        }
++  
++        bool get_closest_points(const line &line2, 
++					          vec3 &pointOnThis,
++					          vec3 &pointOnThat)
++        {
++  
++          // quick check to see if parallel -- if so, quit.
++          if(fabs(direction.dot(line2.direction)) == 1.0)
++	          return 0;
++          line l2 = line2;
++  
++          // Algorithm: Brian Jean
++          // 
++          register real u;
++          register real v;
++          vec3 Vr = direction;
++          vec3 Vs = l2.direction;
++          register real Vr_Dot_Vs = Vr.dot(Vs);
++          register real detA = real(1.0 - (Vr_Dot_Vs * Vr_Dot_Vs));
++          vec3 C = l2.position - position;
++          register real C_Dot_Vr =  C.dot(Vr);
++          register real C_Dot_Vs =  C.dot(Vs);
++  
++          u = (C_Dot_Vr - Vr_Dot_Vs * C_Dot_Vs)/detA;
++          v = (C_Dot_Vr * Vr_Dot_Vs - C_Dot_Vs)/detA;
++  
++          pointOnThis = position;
++          pointOnThis += direction * u;
++          pointOnThat = l2.position;
++          pointOnThat += l2.direction * v;
++  
++          return 1;
++        }
++  
++        vec3 get_closest_point(const vec3 &point)
++        {
++          vec3 np = point - position;
++          vec3 rp = direction*direction.dot(np)+position;
++          return rp;
++        }
++  
++        const vec3 & get_position() const {return position;}
++
++        const vec3 & get_direction() const {return direction;}
++  
++    //protected:
++        vec3 position;
++        vec3 direction;
++    };
++  
++  
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++  
++  
++
++
++
++
++
++
++
++
++
++
++
++  // matrix
++
++  
++  class matrix4
++  {
++    
++  public:
++        
++    matrix4() { make_identity(); }
++    
++	matrix4( real r ) 
++	{ set_value(r); }
++
++	matrix4( real * m )
++	{ set_value(m); }
++    
++    matrix4( real a00, real a01, real a02, real a03,
++	       real a10, real a11, real a12, real a13,
++		   real a20, real a21, real a22, real a23,
++		   real a30, real a31, real a32, real a33 )
++	{
++		element(0,0) = a00;
++		element(0,1) = a01;
++		element(0,2) = a02;
++		element(0,3) = a03;
++		
++		element(1,0) = a10;
++		element(1,1) = a11;
++		element(1,2) = a12;
++		element(1,3) = a13;
++		
++		element(2,0) = a20;
++		element(2,1) = a21;
++		element(2,2) = a22;
++		element(2,3) = a23;
++		
++		element(3,0) = a30;
++		element(3,1) = a31;
++		element(3,2) = a32;
++		element(3,3) = a33;
++	}
++            
++    
++    void get_value( real * mp ) const
++	{
++		int c = 0;
++		for(int j=0; j < 4; j++)
++			for(int i=0; i < 4; i++)
++				mp[c++] = element(i,j);
++	}
++    
++    
++    const real * get_value() const
++	{ return m; }
++    
++	void set_value( real * mp)
++	{
++		int c = 0;
++		for(int j=0; j < 4; j++)
++			for(int i=0; i < 4; i++)
++				element(i,j) = mp[c++];
++	}
++    
++	void set_value( real r ) 
++	{
++		for(int i=0; i < 4; i++)
++			for(int j=0; j < 4; j++)
++				element(i,j) = r;
++	}
++    
++    void make_identity()
++	{
++		element(0,0) = 1.0;
++		element(0,1) = 0.0;
++		element(0,2) = 0.0; 
++		element(0,3) = 0.0;
++		
++		element(1,0) = 0.0;
++		element(1,1) = 1.0; 
++		element(1,2) = 0.0;
++		element(1,3) = 0.0;
++		
++		element(2,0) = 0.0;
++		element(2,1) = 0.0;
++		element(2,2) = 1.0;
++		element(2,3) = 0.0;
++		
++		element(3,0) = 0.0; 
++		element(3,1) = 0.0; 
++		element(3,2) = 0.0;
++		element(3,3) = 1.0;
++	}
++	
++	
++    static matrix4 identity()
++	{
++		static matrix4 mident (
++			1.0, 0.0, 0.0, 0.0,
++			0.0, 1.0, 0.0, 0.0,
++			0.0, 0.0, 1.0, 0.0,
++			0.0, 0.0, 0.0, 1.0  );
++		return mident;
++	}
++    
++        
++    void set_scale( real s )
++	{
++		element(0,0) = s;
++		element(1,1) = s;
++		element(2,2) = s;
++	}
++    
++    void set_scale( const vec3 & s )
++	{
++		element(0,0) = s.v[0];
++		element(1,1) = s.v[1];
++		element(2,2) = s.v[2];
++	}
++    
++    
++    void set_translate( const vec3 & t )
++	{
++		element(0,3) = t.v[0];
++		element(1,3) = t.v[1];
++		element(2,3) = t.v[2];
++	}
++    
++	void set_row(int r, const vec4 & t)
++	{
++		element(r,0) = t.v[0];
++		element(r,1) = t.v[1];
++		element(r,2) = t.v[2];
++		element(r,3) = t.v[3];
++	}
++
++	void set_column(int c, const vec4 & t)
++	{
++		element(0,c) = t.v[0];
++		element(1,c) = t.v[1];
++		element(2,c) = t.v[2];
++		element(3,c) = t.v[3];
++	}
++
++    
++	void get_row(int r, vec4 & t) const
++	{
++		t.v[0] = element(r,0);
++		t.v[1] = element(r,1);
++		t.v[2] = element(r,2);
++		t.v[3] = element(r,3);
++	}
++
++	vec4 get_row(int r) const
++	{
++		vec4 v; get_row(r, v);
++		return v;
++	}
++
++	void get_column(int c, vec4 & t) const
++	{
++		t.v[0] = element(0,c);
++		t.v[1] = element(1,c);
++		t.v[2] = element(2,c);
++		t.v[3] = element(3,c);
++	}
++
++	vec4 get_column(int c) const
++	{
++		vec4 v; get_column(c, v);
++		return v;
++	}
++
++    matrix4 inverse() const
++	{
++		matrix4 minv;
++		
++		real r1[8], r2[8], r3[8], r4[8];
++		real *s[4], *tmprow;
++		
++		s[0] = &r1[0];
++		s[1] = &r2[0];
++		s[2] = &r3[0];
++		s[3] = &r4[0];
++		
++		register int i,j,p,jj;
++		for(i=0;i<4;i++)
++		{
++			for(j=0;j<4;j++)
++			{
++				s[i][j] = element(i,j);
++				if(i==j) s[i][j+4] = 1.0;
++				else     s[i][j+4] = 0.0;
++			}
++		}
++		real scp[4];
++		for(i=0;i<4;i++)
++		{
++			scp[i] = real(fabs(s[i][0]));
++			for(j=1;j<4;j++)
++				if(real(fabs(s[i][j])) > scp[i]) scp[i] = real(fabs(s[i][j]));
++				if(scp[i] == 0.0) return minv; // singular matrix!
++		}
++		
++		int pivot_to;
++		real scp_max;
++		for(i=0;i<4;i++)
++		{
++			// select pivot row
++			pivot_to = i;
++			scp_max = real(fabs(s[i][i]/scp[i]));
++			// find out which row should be on top
++			for(p=i+1;p<4;p++)
++				if(real(fabs(s[p][i]/scp[p])) > scp_max)
++				{ scp_max = real(fabs(s[p][i]/scp[p])); pivot_to = p; }
++				// Pivot if necessary
++				if(pivot_to != i)
++				{
++					tmprow = s[i];
++					s[i] = s[pivot_to];
++					s[pivot_to] = tmprow;
++					real tmpscp;
++					tmpscp = scp[i];
++					scp[i] = scp[pivot_to];
++					scp[pivot_to] = tmpscp;
++				}
++				
++				real mji;
++				// perform gaussian elimination
++				for(j=i+1;j<4;j++)
++				{
++					mji = s[j][i]/s[i][i];
++					s[j][i] = 0.0;
++					for(jj=i+1;jj<8;jj++)
++						s[j][jj] -= mji*s[i][jj];
++				}
++		}
++		if(s[3][3] == 0.0) return minv; // singular matrix!
++		
++		//
++		// Now we have an upper triangular matrix.
++		//
++		//  x x x x | y y y y
++		//  0 x x x | y y y y 
++		//  0 0 x x | y y y y
++		//  0 0 0 x | y y y y
++		//
++		//  we'll back substitute to get the inverse
++		//
++		//  1 0 0 0 | z z z z
++		//  0 1 0 0 | z z z z
++		//  0 0 1 0 | z z z z
++		//  0 0 0 1 | z z z z 
++		//
++		
++		real mij;
++		for(i=3;i>0;i--)
++		{
++			for(j=i-1;j > -1; j--)
++			{
++				mij = s[j][i]/s[i][i];
++				for(jj=j+1;jj<8;jj++)
++					s[j][jj] -= mij*s[i][jj];
++			}
++		}
++		
++		for(i=0;i<4;i++)
++			for(j=0;j<4;j++)
++				minv(i,j) = s[i][j+4] / s[i][i];
++			
++			return minv;
++	}
++    
++    
++    matrix4 transpose() const
++	{
++		matrix4 mtrans;
++		
++		for(int i=0;i<4;i++)
++			for(int j=0;j<4;j++)
++				mtrans(i,j) = element(j,i);		
++		return mtrans;
++	}
++    
++    matrix4 & mult_right( const matrix4 & b )
++	{
++		matrix4 mt(*this);
++		set_value(real(0));
++
++		for(int i=0; i < 4; i++)
++			for(int j=0; j < 4; j++)
++				for(int c=0; c < 4; c++)
++					element(i,j) += mt(i,c) * b(c,j);
++		return *this;
++	}    
++
++    matrix4 & mult_left( const matrix4 & b )
++	{
++		matrix4 mt(*this);
++		set_value(real(0));
++
++		for(int i=0; i < 4; i++)
++			for(int j=0; j < 4; j++)
++				for(int c=0; c < 4; c++)
++					element(i,j) += b(i,c) * mt(c,j);
++		return *this;
++	}
++	
++	// dst = M * src
++    void mult_matrix_vec( const vec3 &src, vec3 &dst ) const
++	{
++		real w = (
++			src.v[0] * element(3,0) +
++			src.v[1] * element(3,1) + 
++			src.v[2] * element(3,2) +
++			element(3,3)          );
++        
++        assert(w != GLH_ZERO);
++
++        dst.v[0]  = (
++			src.v[0] * element(0,0) +
++			src.v[1] * element(0,1) +
++			src.v[2] * element(0,2) +
++			element(0,3)          ) / w;
++		dst.v[1]  = (
++			src.v[0] * element(1,0) +
++			src.v[1] * element(1,1) +
++			src.v[2] * element(1,2) +
++			element(1,3)          ) / w;
++		dst.v[2]  = (
++			src.v[0] * element(2,0) +
++			src.v[1] * element(2,1) + 
++			src.v[2] * element(2,2) +
++			element(2,3)          ) / w;
++	}
++    
++	void mult_matrix_vec( vec3 & src_and_dst) const
++	{ mult_matrix_vec(vec3(src_and_dst), src_and_dst); }
++
++
++    // dst = src * M
++    void mult_vec_matrix( const vec3 &src, vec3 &dst ) const
++	{
++		real w = (
++			src.v[0] * element(0,3) +
++			src.v[1] * element(1,3) +
++			src.v[2] * element(2,3) +
++			element(3,3)          );
++        
++        assert(w != GLH_ZERO);
++
++		dst.v[0]  = (
++			src.v[0] * element(0,0) +
++			src.v[1] * element(1,0) + 
++			src.v[2] * element(2,0) + 
++			element(3,0)          ) / w;
++		dst.v[1]  = (
++			src.v[0] * element(0,1) +
++			src.v[1] * element(1,1) +
++			src.v[2] * element(2,1) +
++			element(3,1)          ) / w;
++		dst.v[2]  = (
++			src.v[0] * element(0,2) +
++			src.v[1] * element(1,2) +
++			src.v[2] * element(2,2) +
++			element(3,2)          ) / w;
++	}
++        
++
++	void mult_vec_matrix( vec3 & src_and_dst) const
++	{ mult_vec_matrix(vec3(src_and_dst), src_and_dst); }
++
++	// dst = M * src
++    void mult_matrix_vec( const vec4 &src, vec4 &dst ) const
++	{
++        dst.v[0]  = (
++			src.v[0] * element(0,0) +
++			src.v[1] * element(0,1) +
++			src.v[2] * element(0,2) +
++			src.v[3] * element(0,3));
++		dst.v[1]  = (
++			src.v[0] * element(1,0) +
++			src.v[1] * element(1,1) +
++			src.v[2] * element(1,2) +
++			src.v[3] * element(1,3));
++		dst.v[2]  = (
++			src.v[0] * element(2,0) +
++			src.v[1] * element(2,1) + 
++			src.v[2] * element(2,2) +
++			src.v[3] * element(2,3));
++		dst.v[3] = (
++			src.v[0] * element(3,0) +
++			src.v[1] * element(3,1) + 
++			src.v[2] * element(3,2) +
++			src.v[3] * element(3,3));
++	}
++    
++	void mult_matrix_vec( vec4 & src_and_dst) const
++	{ mult_matrix_vec(vec4(src_and_dst), src_and_dst); }
++
++
++    // dst = src * M
++    void mult_vec_matrix( const vec4 &src, vec4 &dst ) const
++	{
++		dst.v[0]  = (
++			src.v[0] * element(0,0) +
++			src.v[1] * element(1,0) + 
++			src.v[2] * element(2,0) + 
++			src.v[3] * element(3,0));
++		dst.v[1]  = (
++			src.v[0] * element(0,1) +
++			src.v[1] * element(1,1) +
++			src.v[2] * element(2,1) +
++			src.v[3] * element(3,1));
++		dst.v[2]  = (
++			src.v[0] * element(0,2) +
++			src.v[1] * element(1,2) +
++			src.v[2] * element(2,2) +
++			src.v[3] * element(3,2));
++		dst.v[3] = (
++			src.v[0] * element(0,3) +
++			src.v[1] * element(1,3) +
++			src.v[2] * element(2,3) +
++			src.v[3] * element(3,3));
++	}
++        
++
++	void mult_vec_matrix( vec4 & src_and_dst) const
++	{ mult_vec_matrix(vec4(src_and_dst), src_and_dst); }
++
++    
++    // dst = M * src
++    void mult_matrix_dir( const vec3 &src, vec3 &dst ) const
++	{
++		dst.v[0]  = (
++			src.v[0] * element(0,0) +
++			src.v[1] * element(0,1) +
++			src.v[2] * element(0,2) ) ;
++		dst.v[1]  = ( 
++			src.v[0] * element(1,0) +
++			src.v[1] * element(1,1) +
++			src.v[2] * element(1,2) ) ;
++		dst.v[2]  = ( 
++			src.v[0] * element(2,0) +
++			src.v[1] * element(2,1) + 
++			src.v[2] * element(2,2) ) ;
++	}
++        
++
++	void mult_matrix_dir( vec3 & src_and_dst) const
++	{ mult_matrix_dir(vec3(src_and_dst), src_and_dst); }
++
++
++	// dst = src * M
++    void mult_dir_matrix( const vec3 &src, vec3 &dst ) const
++	{
++		dst.v[0]  = ( 
++			src.v[0] * element(0,0) +
++			src.v[1] * element(1,0) +
++			src.v[2] * element(2,0) ) ;
++		dst.v[1]  = ( 
++			src.v[0] * element(0,1) +
++			src.v[1] * element(1,1) +
++			src.v[2] * element(2,1) ) ;
++		dst.v[2]  = (
++			src.v[0] * element(0,2) +
++			src.v[1] * element(1,2) + 
++			src.v[2] * element(2,2) ) ;
++	}
++    
++    
++	void mult_dir_matrix( vec3 & src_and_dst) const
++	{ mult_dir_matrix(vec3(src_and_dst), src_and_dst); }
++
++
++    real & operator () (int row, int col)
++    { return element(row,col); }
++
++    const real & operator () (int row, int col) const
++    { return element(row,col); }
++
++	real & element (int row, int col)
++    { return m[row | (col<<2)]; }
++
++    const real & element (int row, int col) const
++    { return m[row | (col<<2)]; }
++
++    matrix4 & operator *= ( const matrix4 & mat )
++	{
++		mult_right( mat );
++		return *this;
++	}
++    
++    matrix4 & operator *= ( const real & r )
++	{
++		for (int i = 0; i < 4; ++i)
++        {
++            element(0,i) *= r;
++            element(1,i) *= r;
++            element(2,i) *= r;
++            element(3,i) *= r;
++        }
++		return *this;
++	}
++
++    matrix4 & operator += ( const matrix4 & mat )
++	{
++		for (int i = 0; i < 4; ++i)
++        {
++            element(0,i) += mat.element(0,i);
++            element(1,i) += mat.element(1,i);
++            element(2,i) += mat.element(2,i);
++            element(3,i) += mat.element(3,i);
++        }
++		return *this;
++	}
++
++    friend matrix4 operator * ( const matrix4 & m1,	const matrix4 & m2 );
++    friend bool operator == ( const matrix4 & m1, const matrix4 & m2 );
++    friend bool operator != ( const matrix4 & m1, const matrix4 & m2 );
++    
++  //protected:
++	  real m[16];
++  };
++  
++  inline  
++  matrix4 operator * ( const matrix4 & m1, const matrix4 & m2 )
++  {
++	  matrix4 product;
++	  
++	  product = m1;
++	  product.mult_right(m2);
++	  
++	  return product;
++  }
++  
++  inline
++  bool operator ==( const matrix4 &m1, const matrix4 &m2 )
++  {
++	  return ( 
++		  m1(0,0) == m2(0,0) &&
++		  m1(0,1) == m2(0,1) &&
++		  m1(0,2) == m2(0,2) &&
++		  m1(0,3) == m2(0,3) &&
++		  m1(1,0) == m2(1,0) &&
++		  m1(1,1) == m2(1,1) &&
++		  m1(1,2) == m2(1,2) &&
++		  m1(1,3) == m2(1,3) &&
++		  m1(2,0) == m2(2,0) &&
++		  m1(2,1) == m2(2,1) &&
++		  m1(2,2) == m2(2,2) &&
++		  m1(2,3) == m2(2,3) &&
++		  m1(3,0) == m2(3,0) &&
++		  m1(3,1) == m2(3,1) &&
++		  m1(3,2) == m2(3,2) &&
++		  m1(3,3) == m2(3,3) );
++  }
++  
++  inline
++  bool operator != ( const matrix4 & m1, const matrix4 & m2 )
++  { return !( m1 == m2 ); }  
++
++
++
++
++
++
++
++
++
++
++
++
++  
++    class quaternion
++    {
++    public:
++    
++    quaternion()
++    {
++        *this = identity();
++    }
++
++    quaternion( const real v[4] )
++    {
++        set_value( v );
++    }
++
++
++    quaternion( real q0, real q1, real q2, real q3 )
++    {
++        set_value( q0, q1, q2, q3 );
++    }
++
++
++    quaternion( const matrix4 & m )
++    {
++        set_value( m );
++    }
++
++
++    quaternion( const vec3 &axis, real radians )
++    {
++        set_value( axis, radians );
++    }
++
++
++    quaternion( const vec3 &rotateFrom, const vec3 &rotateTo )
++    {
++        set_value( rotateFrom, rotateTo );
++    }
++
++    quaternion( const vec3 & from_look, const vec3 & from_up,
++		      const vec3 & to_look, const vec3& to_up)
++    {
++	    set_value(from_look, from_up, to_look, to_up);
++    }
++
++    const real * get_value() const
++    {
++        return  &q[0];
++    }
++
++    void get_value( real &q0, real &q1, real &q2, real &q3 ) const
++    {
++        q0 = q[0];
++        q1 = q[1];
++        q2 = q[2];
++        q3 = q[3];
++    }
++
++    quaternion & set_value( real q0, real q1, real q2, real q3 )
++    {
++        q[0] = q0;
++        q[1] = q1;
++        q[2] = q2;
++        q[3] = q3;
++        counter = 0;
++        return *this;
++    }
++
++    void get_value( vec3 &axis, real &radians ) const
++    {
++        radians = real(acos( q[3] ) * GLH_TWO);
++        if ( radians == GLH_ZERO )
++            axis = vec3( 0.0, 0.0, 1.0 );
++        else
++        {
++            axis.v[0] = q[0];
++            axis.v[1] = q[1];
++            axis.v[2] = q[2];
++            axis.normalize();
++        }
++    }
++
++    void get_value( matrix4 & m ) const
++    {
++        real s, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
++
++        real norm = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
++
++        s = (equivalent(norm,GLH_ZERO)) ? GLH_ZERO : ( GLH_TWO / norm );
++
++        xs = q[0] * s;
++        ys = q[1] * s;
++        zs = q[2] * s;
++
++        wx = q[3] * xs;
++        wy = q[3] * ys;
++        wz = q[3] * zs;
++
++        xx = q[0] * xs;
++        xy = q[0] * ys;
++        xz = q[0] * zs;
++
++        yy = q[1] * ys;
++        yz = q[1] * zs;
++        zz = q[2] * zs;
++
++        m(0,0) = real( GLH_ONE - ( yy + zz ));
++        m(1,0) = real ( xy + wz );
++        m(2,0) = real ( xz - wy );
++
++        m(0,1) = real ( xy - wz );
++        m(1,1) = real ( GLH_ONE - ( xx + zz ));
++        m(2,1) = real ( yz + wx );
++
++        m(0,2) = real ( xz + wy );
++        m(1,2) = real ( yz - wx );
++        m(2,2) = real ( GLH_ONE - ( xx + yy ));
++
++        m(3,0) = m(3,1) = m(3,2) = m(0,3) = m(1,3) = m(2,3) = GLH_ZERO;
++        m(3,3) = GLH_ONE;
++    }
++
++    quaternion & set_value( const real * qp )
++    {
++        memcpy(q,qp,sizeof(real) * 4);
++
++        counter = 0;
++        return *this;
++    }
++
++    quaternion & set_value( const matrix4 & m )
++    {
++        real tr, s;
++        int i, j, k;
++        const int nxt[3] = { 1, 2, 0 };
++
++        tr = m(0,0) + m(1,1) + m(2,2);
++
++        if ( tr > GLH_ZERO )
++        {
++            s = real(sqrt( tr + m(3,3) ));
++            q[3] = real ( s * 0.5 );
++            s = real(0.5) / s;
++
++            q[0] = real ( ( m(1,2) - m(2,1) ) * s );
++            q[1] = real ( ( m(2,0) - m(0,2) ) * s );
++            q[2] = real ( ( m(0,1) - m(1,0) ) * s );
++        }
++        else
++        {
++            i = 0;
++            if ( m(1,1) > m(0,0) )
++              i = 1;
++
++            if ( m(2,2) > m(i,i) )
++              i = 2;
++
++            j = nxt[i];
++            k = nxt[j];
++
++            s = real(sqrt( ( m(i,j) - ( m(j,j) + m(k,k) )) + GLH_ONE ));
++
++            q[i] = real ( s * 0.5 );
++            s = real(0.5 / s);
++
++            q[3] = real ( ( m(j,k) - m(k,j) ) * s );
++            q[j] = real ( ( m(i,j) + m(j,i) ) * s );
++            q[k] = real ( ( m(i,k) + m(k,i) ) * s );
++        }
++
++        counter = 0;
++        return *this;
++    }
++
++    quaternion & set_value( const vec3 &axis, real theta )
++    {
++        real sqnorm = axis.square_norm();
++
++        if (sqnorm <= GLH_EPSILON)
++        {
++            // axis too small.
++            x = y = z = 0.0;
++            w = 1.0;
++        } 
++        else 
++        {
++            theta *= real(0.5);
++            real sin_theta = real(sin(theta));
++
++            if (!equivalent(sqnorm,GLH_ONE)) 
++              sin_theta /= real(sqrt(sqnorm));
++            x = sin_theta * axis.v[0];
++            y = sin_theta * axis.v[1];
++            z = sin_theta * axis.v[2];
++            w = real(cos(theta));
++        }
++        return *this;
++    }
++
++    quaternion & set_value( const vec3 & rotateFrom, const vec3 & rotateTo )
++    {
++        vec3 p1, p2;
++        real alpha;
++
++        p1 = rotateFrom; 
++        p1.normalize();
++        p2 = rotateTo;  
++        p2.normalize();
++
++        alpha = p1.dot(p2);
++
++        if(equivalent(alpha,GLH_ONE))
++        { 
++            *this = identity(); 
++            return *this; 
++        }
++
++        // ensures that the anti-parallel case leads to a positive dot
++        if(equivalent(alpha,-GLH_ONE))
++        {
++            vec3 v;
++
++            if(p1.v[0] != p1.v[1] || p1.v[0] != p1.v[2])
++    	        v = vec3(p1.v[1], p1.v[2], p1.v[0]);
++            else
++    	        v = vec3(-p1.v[0], p1.v[1], p1.v[2]);
++
++            v -= p1 * p1.dot(v);
++            v.normalize();
++
++            set_value(v, GLH_PI);
++            return *this;
++        }
++
++        p1 = p1.cross(p2);  
++        p1.normalize();
++        set_value(p1,real(acos(alpha)));
++
++        counter = 0;
++        return *this;
++    }
++
++    quaternion & set_value( const vec3 & from_look, const vec3 & from_up,
++		      const vec3 & to_look, const vec3 & to_up)
++    {
++	    quaternion r_look = quaternion(from_look, to_look);
++	    
++	    vec3 rotated_from_up(from_up);
++	    r_look.mult_vec(rotated_from_up);
++	    
++	    quaternion r_twist = quaternion(rotated_from_up, to_up);
++	    
++	    *this = r_twist;
++	    *this *= r_look;
++	    return *this;
++    }
++
++    quaternion & operator *= ( const quaternion & qr )
++    {
++        quaternion ql(*this);
++   
++        w = ql.w * qr.w - ql.x * qr.x - ql.y * qr.y - ql.z * qr.z;
++        x = ql.w * qr.x + ql.x * qr.w + ql.y * qr.z - ql.z * qr.y;
++        y = ql.w * qr.y + ql.y * qr.w + ql.z * qr.x - ql.x * qr.z;
++        z = ql.w * qr.z + ql.z * qr.w + ql.x * qr.y - ql.y * qr.x;
++
++        counter += qr.counter;
++        counter++;
++        counter_normalize();
++        return *this;
++    }
++
++    void normalize()
++    {
++        real rnorm = GLH_ONE / real(sqrt(w * w + x * x + y * y + z * z));
++        if (equivalent(rnorm, GLH_ZERO))
++            return;
++        x *= rnorm;
++        y *= rnorm;
++        z *= rnorm;
++        w *= rnorm;
++        counter = 0;
++    }
++
++    friend bool operator == ( const quaternion & q1, const quaternion & q2 );      
++
++    friend bool operator != ( const quaternion & q1, const quaternion & q2 );
++
++    friend quaternion operator * ( const quaternion & q1, const quaternion & q2 );
++
++    bool equals( const quaternion & r, real tolerance ) const
++    {
++        real t;
++
++        t = (
++			(q[0]-r.q[0])*(q[0]-r.q[0]) +
++            (q[1]-r.q[1])*(q[1]-r.q[1]) +
++            (q[2]-r.q[2])*(q[2]-r.q[2]) +
++            (q[3]-r.q[3])*(q[3]-r.q[3]) );
++        if(t > GLH_EPSILON) 
++            return false;
++        return 1;
++    }
++
++    quaternion & conjugate()
++    {
++        q[0] *= -GLH_ONE;
++        q[1] *= -GLH_ONE;
++        q[2] *= -GLH_ONE;
++        return *this;
++    }
++
++    quaternion & invert()
++    {
++        return conjugate();
++    }
++
++    quaternion inverse() const
++    {
++        quaternion r = *this;
++        return r.invert();
++    }
++
++    //
++    // Quaternion multiplication with cartesian vector
++    // v' = q*v*q(star)
++    //
++    void mult_vec( const vec3 &src, vec3 &dst ) const
++    {
++        real v_coef = w * w - x * x - y * y - z * z;                     
++        real u_coef = GLH_TWO * (src.v[0] * x + src.v[1] * y + src.v[2] * z);  
++        real c_coef = GLH_TWO * w;                                       
++
++        dst.v[0] = v_coef * src.v[0] + u_coef * x + c_coef * (y * src.v[2] - z * src.v[1]);
++        dst.v[1] = v_coef * src.v[1] + u_coef * y + c_coef * (z * src.v[0] - x * src.v[2]);
++        dst.v[2] = v_coef * src.v[2] + u_coef * z + c_coef * (x * src.v[1] - y * src.v[0]);
++    }
++
++    void mult_vec( vec3 & src_and_dst) const
++    {
++        mult_vec(vec3(src_and_dst), src_and_dst);
++    }
++
++    void scale_angle( real scaleFactor )
++    {
++        vec3 axis;
++        real radians;
++
++        get_value(axis, radians);
++        radians *= scaleFactor;
++        set_value(axis, radians);
++    }
++
++    static quaternion slerp( const quaternion & p, const quaternion & q, real alpha )
++    {
++        quaternion r;
++
++        real cos_omega = p.x * q.x + p.y * q.y + p.z * q.z + p.w * q.w;
++        // if B is on opposite hemisphere from A, use -B instead
++      
++        int bflip;
++        if ( ( bflip = (cos_omega < GLH_ZERO)) )
++            cos_omega = -cos_omega;
++
++        // complementary interpolation parameter
++        real beta = GLH_ONE - alpha;     
++
++        if(cos_omega <= GLH_ONE - GLH_EPSILON)
++            return p;
++
++        real omega = real(acos(cos_omega));
++        real one_over_sin_omega = GLH_ONE / real(sin(omega));
++
++        beta    = real(sin(omega*beta)  * one_over_sin_omega);
++        alpha   = real(sin(omega*alpha) * one_over_sin_omega);
++
++        if (bflip)
++            alpha = -alpha;
++
++        r.x = beta * p.q[0]+ alpha * q.q[0];
++        r.y = beta * p.q[1]+ alpha * q.q[1];
++        r.z = beta * p.q[2]+ alpha * q.q[2];
++        r.w = beta * p.q[3]+ alpha * q.q[3];
++        return r;
++    }
++
++    static quaternion identity()
++    {
++        static quaternion ident( vec3( 0.0, 0.0, 0.0 ), GLH_ONE );
++        return ident;
++    }
++
++    real & operator []( int i )
++    {
++        assert(i < 4);
++        return q[i];
++    }
++
++    const real & operator []( int i ) const
++    {
++        assert(i < 4);
++        return q[i];
++    }
++
++    protected:
++
++        void counter_normalize()
++        {
++            if (counter > GLH_QUATERNION_NORMALIZATION_THRESHOLD)
++                normalize();
++        }
++
++        union 
++        {
++            struct 
++            {
++                real q[4];
++            };
++            struct 
++            {
++                real x;
++                real y;
++                real z;
++                real w;
++            };
++        };
++
++        // renormalization counter
++        unsigned char counter;
++    };
++
++    inline
++    bool operator == ( const quaternion & q1, const quaternion & q2 )
++    {
++        return (equivalent(q1.x, q2.x) &&
++		        equivalent(q1.y, q2.y) &&
++		        equivalent(q1.z, q2.z) &&
++		        equivalent(q1.w, q2.w) );
++    }
++
++    inline
++    bool operator != ( const quaternion & q1, const quaternion & q2 )
++    { 
++        return ! ( q1 == q2 ); 
++    }
++
++    inline
++    quaternion operator * ( const quaternion & q1, const quaternion & q2 )
++    {	
++        quaternion r(q1); 
++        r *= q2; 
++        return r; 
++    }
++  
++      
++    
++
++
++
++
++
++  
++  
++  class plane
++  {
++  public:
++	  
++	  plane()
++      {
++		  planedistance = 0.0;
++		  planenormal.set_value( 0.0, 0.0, 1.0 );
++      }
++	  
++	  
++	  plane( const vec3 &p0, const vec3 &p1, const vec3 &p2 )
++      {
++		  vec3 v0 = p1 - p0;
++		  vec3 v1 = p2 - p0;
++		  planenormal = v0.cross(v1);  
++		  planenormal.normalize();
++		  planedistance = p0.dot(planenormal);
++      }
++	  
++	  plane( const vec3 &normal, real distance )
++      {
++		  planedistance = distance;
++		  planenormal = normal;
++		  planenormal.normalize();
++      }
++	  
++	  plane( const vec3 &normal, const vec3 &point )
++      {
++		  planenormal = normal;
++		  planenormal.normalize();
++		  planedistance = point.dot(planenormal);
++      }
++	  
++	  void offset( real d )
++      {
++		  planedistance += d;
++      }
++	  
++	  bool intersect( const line &l, vec3 &intersection ) const
++      {
++		  vec3 pos, dir;
++		  vec3 pn = planenormal;
++		  real pd = planedistance;
++		  
++		  pos = l.get_position();
++		  dir = l.get_direction();
++		  
++		  if(dir.dot(pn) == 0.0) return 0;
++		  pos -= pn*pd;
++		  // now we're talking about a plane passing through the origin
++		  if(pos.dot(pn) < 0.0) pn.negate();
++		  if(dir.dot(pn) > 0.0) dir.negate();
++		  vec3 ppos = pn * pos.dot(pn);
++		  pos = (ppos.length()/dir.dot(-pn))*dir;
++		  intersection = l.get_position();
++		  intersection += pos;
++		  return 1;
++      }
++	  void transform( const matrix4 &matrix )
++      {
++		  matrix4 invtr = matrix.inverse();
++		  invtr = invtr.transpose();
++		  
++		  vec3 pntOnplane = planenormal * planedistance;
++		  vec3 newPntOnplane;
++		  vec3 newnormal;
++		  
++		  invtr.mult_dir_matrix(planenormal, newnormal);
++		  matrix.mult_vec_matrix(pntOnplane, newPntOnplane);
++		  
++		  newnormal.normalize();
++		  planenormal = newnormal;
++		  planedistance = newPntOnplane.dot(planenormal);
++      }
++	  
++	  bool is_in_half_space( const vec3 &point ) const
++      {
++		  
++		  if(( point.dot(planenormal) - planedistance) < 0.0)
++			  return 0;
++		  return 1;
++      }
++	  
++	  
++	  real distance( const vec3 & point ) const 
++      {
++		  return planenormal.dot(point - planenormal*planedistance);
++      }
++	  
++	  const vec3 &get_normal() const
++      {
++		  return planenormal;
++      }
++	  
++	  
++	  real get_distance_from_origin() const
++      {
++		  return planedistance;
++      }
++	  
++	  
++	  friend bool operator == ( const plane & p1, const plane & p2 );
++	  
++	  
++	  friend bool operator != ( const plane & p1, const plane & p2 );
++	  
++  //protected:
++	  vec3 planenormal;
++	  real planedistance;
++  };
++  
++  inline
++  bool operator == (const plane & p1, const plane & p2 )
++  {
++	  return (  p1.planedistance == p2.planedistance && p1.planenormal == p2.planenormal);
++  }
++  
++  inline
++  bool operator != ( const plane & p1, const plane & p2 )
++  { return  ! (p1 == p2); }
++  
++  
++
++  } // "ns_##GLH_REAL"
++
++  // make common typedefs...
++#ifdef GLH_REAL_IS_FLOAT
++  typedef GLH_REAL_NAMESPACE::vec2 vec2f;
++  typedef GLH_REAL_NAMESPACE::vec3 vec3f;
++  typedef GLH_REAL_NAMESPACE::vec4 vec4f;
++  typedef GLH_REAL_NAMESPACE::quaternion quaternionf;
++  typedef GLH_REAL_NAMESPACE::quaternion rotationf;
++  typedef GLH_REAL_NAMESPACE::line linef;
++  typedef GLH_REAL_NAMESPACE::plane planef;
++  typedef GLH_REAL_NAMESPACE::matrix4 matrix4f;
++#endif
++
++  
++
++
++}  // namespace glh
++
++
++
++#endif
++
+-- 
+tg: (fd717f3..) topic/fixes/jira-backported/glh_linear (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/50_get_cpu_clock_count_for_more_than_just_i386.diff b/debian/patches/topic/fixes/jira-sent/50_get_cpu_clock_count_for_more_than_just_i386.diff
new file mode 100644
index 0000000..fb4e824
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/50_get_cpu_clock_count_for_more_than_just_i386.diff
@@ -0,0 +1,40 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/50_get_cpu_clock_count_for_more_than_just_i386
+
+Fix CPU clock count for non i386 based processors eg PPC.
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llcommon/llfasttimer.cpp |   16 ++--------------
+ 1 files changed, 2 insertions(+), 14 deletions(-)
+
+diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
+index 3304528..804d124 100644
+--- a/indra/llcommon/llfasttimer.cpp
++++ b/indra/llcommon/llfasttimer.cpp
+@@ -91,20 +91,8 @@ U64 get_cpu_clock_count()
+ #endif // LL_WINDOWS
+ 
+ 
+-#if (LL_LINUX || LL_SOLARIS) && (defined(__i386__) || defined(__amd64__))
+-U64 get_cpu_clock_count()
+-{
+-	U64 x;
+-	__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
+-	return x;
+-}
+-#endif
+-
+-#if LL_DARWIN || (LL_SOLARIS && defined(__sparc__))
+-//
+-// Mac implementation of CPU clock
+-//
+-// Just use gettimeofday implementation for now
++#if LL_LINUX || LL_DARWIN || LL_SOLARIS
++// Both Linux and Mac use gettimeofday for accurate time
+ 
+ U64 get_cpu_clock_count()
+ {
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/50_get_cpu_clock_count_for_more_than_just_i386 (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/59_need_llpreprocessor_to_access_endian_macros.diff b/debian/patches/topic/fixes/jira-sent/59_need_llpreprocessor_to_access_endian_macros.diff
new file mode 100644
index 0000000..d179877
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/59_need_llpreprocessor_to_access_endian_macros.diff
@@ -0,0 +1,25 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/59_need_llpreprocessor_to_access_endian_macros
+
+PPC compile fix, give access to endian macros
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llmessage/message.h |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
+index c503a58..3fae382 100644
+--- a/indra/llmessage/message.h
++++ b/indra/llmessage/message.h
+@@ -48,6 +48,7 @@
+ #include "winsock2.h" // htons etc.
+ #endif
+ 
++#include "llpreprocessor.h"
+ #include "llerror.h"
+ #include "net.h"
+ #include "string_table.h"
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/59_need_llpreprocessor_to_access_endian_macros (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/VWR-10759_delete_LLMediaImplGStreamer_mediaData_as_array.diff b/debian/patches/topic/fixes/jira-sent/VWR-10759_delete_LLMediaImplGStreamer_mediaData_as_array.diff
new file mode 100644
index 0000000..d31ff0b
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/VWR-10759_delete_LLMediaImplGStreamer_mediaData_as_array.diff
@@ -0,0 +1,27 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/fixes/new/delete_LLMediaImplGStreamer_mediaData_as_array
+
+LLMediaImplGStreamer::mediaData is a pointer to an array.
+Delete with operator [] instead of operator delete.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/llmedia/llmediaimplgstreamer.cpp |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/indra/llmedia/llmediaimplgstreamer.cpp b/indra/llmedia/llmediaimplgstreamer.cpp
+index 573c699..7e2923c 100644
+--- a/indra/llmedia/llmediaimplgstreamer.cpp
++++ b/indra/llmedia/llmediaimplgstreamer.cpp
+@@ -431,7 +431,7 @@ unload ()
+ 
+ 	if (mediaData)
+ 	{
+-		delete mediaData;
++		delete [] mediaData;
+ 		mediaData = NULL;
+ 	}
+ 
+-- 
+tg: (d0f2f61..) topic/fixes/jira-sent/VWR-10759_delete_LLMediaImplGStreamer_mediaData_as_array (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/VWR-11128-Find_Python.diff b/debian/patches/topic/fixes/jira-sent/VWR-11128-Find_Python.diff
new file mode 100644
index 0000000..2841345
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/VWR-11128-Find_Python.diff
@@ -0,0 +1,29 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/VWR-11128-Find_Python
+
+<patch description>
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/cmake/Python.cmake |    5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake
+index 4f86d32..e23e2ca 100644
+--- a/indra/cmake/Python.cmake
++++ b/indra/cmake/Python.cmake
+@@ -13,6 +13,11 @@ if (WINDOWS)
+     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
+     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
+     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
++    [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
++    [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
++    [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
++    [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
++
+     )
+ elseif (EXISTS /etc/debian_version)
+   # On Debian and Ubuntu, avoid Python 2.4 if possible.
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/VWR-11128-Find_Python (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/VWR-11138_Develop_py_and_express_VS.diff b/debian/patches/topic/fixes/jira-sent/VWR-11138_Develop_py_and_express_VS.diff
new file mode 100644
index 0000000..5cd531f
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/VWR-11138_Develop_py_and_express_VS.diff
@@ -0,0 +1,89 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/VWR-11138_Develop_py_and_express_VS
+
+<patch description>
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/develop.py |   49 ++++++++++++++++++++++++++++++++++++++++++++++---
+ 1 files changed, 46 insertions(+), 3 deletions(-)
+
+diff --git a/indra/develop.py b/indra/develop.py
+index 29fe0e8..bb12437 100755
+--- a/indra/develop.py
++++ b/indra/develop.py
+@@ -464,8 +464,15 @@ class WindowsSetup(PlatformSetup):
+                     print 'Building with ', self.gens[version]['gen']
+                     break
+             else:
+-                print >> sys.stderr, 'Cannot find a Visual Studio installation!'
+-                eys.exit(1)
++                print >> sys.stderr, 'Cannot find a Visual Studio installation, testing for express editions'
++                for version in 'vc80 vc90 vc71'.split():
++                    if self.find_visual_studio_express(version):
++                        self._generator = version
++                        print 'Building with ', self.gens[version]['gen'] , "Express edition"
++                        break
++                else:
++                    print >> sys.stderr, 'Cannot find any Visual Studio installation'
++                    eys.exit(1)
+         return self._generator
+ 
+     def _set_generator(self, gen):
+@@ -515,6 +522,29 @@ class WindowsSetup(PlatformSetup):
+         except WindowsError, err:
+             print >> sys.stderr, "Didn't find ", self.gens[gen]['gen']
+             return ''
++        
++    def find_visual_studio_express(self, gen=None):
++        if gen is None:
++            gen = self._generator
++        gen = gen.lower()
++        try:
++            import _winreg
++            key_str = (r'SOFTWARE\Microsoft\VCEXpress\%s\Setup\VC' %
++                       self.gens[gen]['ver'])
++            value_str = (r'ProductDir')
++            print ('Reading VS environment from HKEY_LOCAL_MACHINE\%s\%s' %
++                   (key_str, value_str))
++            print key_str
++
++            reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
++            key = _winreg.OpenKey(reg, key_str)
++            value = _winreg.QueryValueEx(key, value_str)[0]+"IDE"
++            print 'Found: %s' % value
++            return value
++        except WindowsError, err:
++            print >> sys.stderr, "Didn't find ", self.gens[gen]['gen']
++            return ''
++
+ 
+     def get_build_cmd(self):
+         if self.incredibuild:
+@@ -524,9 +554,22 @@ class WindowsSetup(PlatformSetup):
+ 
+             return "buildconsole Secondlife.sln /build %s" % config
+ 
++        environment = self.find_visual_studio()
++        if environment == '':
++            environment = self.find_visual_studio_express()
++            if environment == '':
++                 print >> sys.stderr, "Something went very wrong during build stage, could not find a Visual Studio?"
++            else:
++                 print >> sys.stderr, "\nSolution generation complete, as you are using an express edition the final\n stages will need to be completed by hand"
++                 build_dirs=self.build_dirs();
++                 print >> sys.stderr, "Solution can now be found in:", build_dirs[0]
++                 print >> sys.stderr, "Set secondlife-bin as startup project"
++                 print >> sys.stderr, "Set build target is Release or RelWithDbgInfo"
++                 exit(0)
++    
+         # devenv.com is CLI friendly, devenv.exe... not so much.
+         return ('"%sdevenv.com" Secondlife.sln /build %s' % 
+-                (self.find_visual_studio(), self.build_type))
++                (environment, self.build_type))
+ 
+     # this override of run exists because the PlatformSetup version
+     # uses Unix/Mac only calls. Freakin' os module!
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/VWR-11138_Develop_py_and_express_VS (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/VWR-1815_top_corner_fix.diff b/debian/patches/topic/fixes/jira-sent/VWR-1815_top_corner_fix.diff
new file mode 100644
index 0000000..17060a0
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/VWR-1815_top_corner_fix.diff
@@ -0,0 +1,62 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/VWR-1815_top_corner_fix
+
+Remains of the top corner texture fix, this part accellerates downloads
+for stuck textures
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/newview/lltexturefetch.cpp |   16 +++++++++++++++-
+ 1 files changed, 15 insertions(+), 1 deletions(-)
+
+diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
+index 11882b2..cf02830 100644
+--- a/indra/newview/lltexturefetch.cpp
++++ b/indra/newview/lltexturefetch.cpp
+@@ -53,6 +53,9 @@ class LLTextureFetchWorker : public LLWorkerClass
+ {
+ friend class LLTextureFetch;
+ 
++public:
++	BOOL mAccelerateDownloadStuckTexture;
++
+ private:
+ #if 0
+ 	class URLResponder : public LLHTTPClient::Responder
+@@ -1061,6 +1064,14 @@ bool LLTextureFetchWorker::processSimulatorPackets()
+ 		}
+ 		bool have_all_data = mLastPacket >= mTotalPackets-1;
+ 		llassert_always(mRequestedSize > 0);
++		
++		if((buffer_size >= mRequestedSize) && mRequestedDiscard <=0)
++ 		{
++			if(!mAccelerateDownloadStuckTexture);
++				llwarns << "Accelerating download of a stuck texture :"<<mID << llendl
++			mAccelerateDownloadStuckTexture=TRUE;
++		}
++
+ 		if (buffer_size >= mRequestedSize || have_all_data)
+ 		{
+ 			/// We have enough (or all) data
+@@ -1557,6 +1568,7 @@ void LLTextureFetch::sendRequestListToSimulators()
+ 	const F32 LAZY_FLUSH_TIMEOUT = 15.f; // 10.0f // temp
+ 	const F32 MIN_REQUEST_TIME = 1.0f;
+ 	const F32 MIN_DELTA_PRIORITY = 1000.f;
++	const F32 MIN_ACCEL_KICK = 0.5f;
+ 
+ 	LLMutexLock lock(&mQueueMutex);
+ 	
+@@ -1587,7 +1599,9 @@ void LLTextureFetch::sendRequestListToSimulators()
+ 		F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority);
+ 		if ((req->mSimRequestedDiscard != req->mDesiredDiscard) ||
+ 			(delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) ||
+-			(elapsed >= LAZY_FLUSH_TIMEOUT))
++			(elapsed >= LAZY_FLUSH_TIMEOUT) ||
++			(req->mAccelerateDownloadStuckTexture && (elapsed >=MIN_ACCEL_KICK))
++			)
+ 		{
+ 			requests[req->mHost].insert(req);
+ 		}
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/VWR-1815_top_corner_fix (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/VWR-8194_clamp_outline_for_broken_nvidia.diff b/debian/patches/topic/fixes/jira-sent/VWR-8194_clamp_outline_for_broken_nvidia.diff
new file mode 100644
index 0000000..3b836e8
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/VWR-8194_clamp_outline_for_broken_nvidia.diff
@@ -0,0 +1,38 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/VWR-8194_clamp_outline_for_broken_nvidia
+
+Prevent buffer overflow in temp GL matrix
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llrender/llrender.cpp |    7 +++++++
+ 1 files changed, 7 insertions(+), 0 deletions(-)
+
+diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
+index ff0a2db..f2b4352 100644
+--- a/indra/llrender/llrender.cpp
++++ b/indra/llrender/llrender.cpp
+@@ -899,6 +899,9 @@ void LLRender::vertex3fv(const GLfloat* v)
+ 
+ void LLRender::texCoord2f(const GLfloat& x, const GLfloat& y)
+ { 
++	if (mCount >= 4096)
++		return;
++
+ 	mTexcoordsp[mCount] = LLVector2(x,y);
+ }
+ 
+@@ -914,6 +917,10 @@ void LLRender::texCoord2fv(const GLfloat* tc)
+ 
+ void LLRender::color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a)
+ {
++
++	if (mCount >= 4096)
++		return;
++
+ 	mColorsp[mCount] = LLColor4U(r,g,b,a);
+ }
+ void LLRender::color4ubv(const GLubyte* c)
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/VWR-8194_clamp_outline_for_broken_nvidia (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/VWR-9557-EnableBuildWithNvidiaOrMesaHeaders.diff b/debian/patches/topic/fixes/jira-sent/VWR-9557-EnableBuildWithNvidiaOrMesaHeaders.diff
new file mode 100644
index 0000000..ab0c0cf
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/VWR-9557-EnableBuildWithNvidiaOrMesaHeaders.diff
@@ -0,0 +1,75 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/VWR-9557-EnableBuildWithNvidiaOrMesaHeaders
+
+Enable the build to succeed with either the mesa gl.h or the nvidia gl.h headers
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llrender/llgl.cpp      |   17 ++++++++++++++---
+ indra/llrender/llglheaders.h |    9 +++++++++
+ 2 files changed, 23 insertions(+), 3 deletions(-)
+
+diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
+index a9cf073..88b1671 100644
+--- a/indra/llrender/llgl.cpp
++++ b/indra/llrender/llgl.cpp
+@@ -252,6 +252,12 @@ PFNWGLSWAPINTERVALEXTPROC			wglSwapIntervalEXT = NULL;
+ PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL;
+ #endif // LL_LINUX
+ 
++#if LL_LINUX && defined(WINGDIAPI)
++PFNGLACTIVETEXTUREARBPROC	glActiveTextureARB=NULL;
++PFNGLCLIENTACTIVETEXTUREARBPROC	glClientActiveTextureARB=NULL;
++PFNGLDRAWRANGEELEMENTSPROC 	glDrawRangeElements=NULL;
++#endif
++
+ #endif
+ 
+ LLGLManager gGLManager;
+@@ -762,15 +768,20 @@ void LLGLManager::initExtensions()
+ 		glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameterivEXT");
+ 		glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmapEXT");
+ 	}
+-#if !LL_LINUX
+-	// This is expected to be a static symbol on Linux GL implementations
++#if !LL_LINUX || (LL_LINUX && defined(WINGDIAPI))
++	// This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers
+ 	glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
+ 	if (!glDrawRangeElements)
+ 	{
+ 		mGLMaxVertexRange = 0;
+ 		mGLMaxIndexRange = 0;
+ 	}
+-#endif // !LL_LINUX
++#endif //!LL_LINUX
++
++#if LL_LINUX && defined(WINGDIAPI)
++	glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTextureARB");
++	glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTextureARB");
++#endif
+ 
+ 	if (mHasOcclusionQuery)
+ 	{
+diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
+index 20a420b..c3035e0 100644
+--- a/indra/llrender/llglheaders.h
++++ b/indra/llrender/llglheaders.h
+@@ -76,6 +76,15 @@
+ #undef Status
+ #endif // LL_LINUX && !LL_MESA_HEADLESS
+ 
++#if LL_LINUX && defined(WINGDIAPI)
++// WINGDIAPI gets set if we are using the linux nvidia gl.h header which needs the 
++// functions below setting up
++// Missing functions when using nvidia header
++extern PFNGLACTIVETEXTUREARBPROC	glActiveTextureARB;
++extern PFNGLCLIENTACTIVETEXTUREARBPROC	glClientActiveTextureARB;
++extern PFNGLDRAWRANGEELEMENTSPROC 	glDrawRangeElements;
++
++#endif
+ 
+ // GL_ARB_vertex_buffer_object
+ extern PFNGLBINDBUFFERARBPROC		glBindBufferARB;
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/VWR-9557-EnableBuildWithNvidiaOrMesaHeaders (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/correctly_find_dbus_headers_on_standalone.diff b/debian/patches/topic/fixes/jira-sent/correctly_find_dbus_headers_on_standalone.diff
new file mode 100644
index 0000000..52bb5b9
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/correctly_find_dbus_headers_on_standalone.diff
@@ -0,0 +1,42 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/correctly_find_dbus_headers_on_standalone
+
+Correctly find the DBUS headers in cmake, patch sent up stream to LL and in the queue to be applied
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ doc/contributions.txt        |    1 +
+ indra/newview/CMakeLists.txt |    5 +++++
+ 2 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/doc/contributions.txt b/doc/contributions.txt
+index f5f50a1..57b53bd 100644
+--- a/doc/contributions.txt
++++ b/doc/contributions.txt
+@@ -232,6 +232,7 @@ Michelle2 Zenovka
+ 	VWR-8889
+ 	VWR-8310
+ 	VWR-4022
++	VWR-9499
+ Mm Alder
+ 	VWR-3777
+ 	VWR-4794
+diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
+index 7c49f72..b21e957 100644
+--- a/indra/newview/CMakeLists.txt
++++ b/indra/newview/CMakeLists.txt
+@@ -59,6 +59,11 @@ include_directories(
+     ${LSCRIPT_INCLUDE_DIRS}/lscript_compile
+     )
+ 
++if (LINUX)
++    include_directories (${DBUSGLIB_INCLUDE_DIRS})
++endif (LINUX)
++
++
+ set(viewer_SOURCE_FILES
+     llagent.cpp
+     llagentdata.cpp
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/correctly_find_dbus_headers_on_standalone (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/dont_depend_on_artwork_to_build.diff b/debian/patches/topic/fixes/jira-sent/dont_depend_on_artwork_to_build.diff
new file mode 100644
index 0000000..3d554c1
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/dont_depend_on_artwork_to_build.diff
@@ -0,0 +1,28 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/dont_depend_on_artwork_to_build
+
+Do not require the artwork to be present in the cmake tree, sent
+upstream and discussed with BoS expected to be fixed upstream at
+some point.
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/newview/CMakeLists.txt |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
+index 7c49f72..cb974c9 100644
+--- a/indra/newview/CMakeLists.txt
++++ b/indra/newview/CMakeLists.txt
+@@ -1244,7 +1244,7 @@ source_group("Character File" FILES ${viewer_CHARACTER_FILES})
+ set_source_files_properties(${viewer_CHARACTER_FILES}
+                             PROPERTIES HEADER_FILE_ONLY TRUE)
+ 
+-list(APPEND viewer_SOURCE_FILES ${viewer_CHARACTER_FILES})
++#list(APPEND viewer_SOURCE_FILES ${viewer_CHARACTER_FILES})
+ 
+ if (WINDOWS)
+   file(GLOB viewer_INSTALLER_FILES installers/windows/*.nsi)
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/dont_depend_on_artwork_to_build (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/gcc_warning_on_llwindowsdl_var_not_set.diff b/debian/patches/topic/fixes/jira-sent/gcc_warning_on_llwindowsdl_var_not_set.diff
new file mode 100644
index 0000000..9ccddab
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/gcc_warning_on_llwindowsdl_var_not_set.diff
@@ -0,0 +1,25 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/gcc_warning_on_llwindowsdl_var_not_set
+
+Prevent FTBFS error with gcc and a wild variable.
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llwindow/llwindowsdl.cpp |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
+index 23228be..0d843ef 100644
+--- a/indra/llwindow/llwindowsdl.cpp
++++ b/indra/llwindow/llwindowsdl.cpp
+@@ -2646,6 +2646,7 @@ BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
+ 		orig_color.red = guint16(65535 * *r);
+ 		orig_color.green= guint16(65535 * *g);
+ 		orig_color.blue = guint16(65535 * *b);
++		orig_color.pixel = -1; //Default this to something or the copy next will produce a gcc warning
+ 		color = orig_color;
+ 
+ 		gtk_color_selection_set_previous_color (colorsel, &color);
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/gcc_warning_on_llwindowsdl_var_not_set (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/lltemplatemessagereader_memcpy.diff b/debian/patches/topic/fixes/jira-sent/lltemplatemessagereader_memcpy.diff
new file mode 100644
index 0000000..9495ad2
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/lltemplatemessagereader_memcpy.diff
@@ -0,0 +1,27 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/lltemplatemessagereader_memcpy
+
+Fix gcc FTBFS bug, possibly a gcc bug.
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llmessage/lltemplatemessagereader.cpp |    3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
+index 7a7d3bb..aef2d33 100644
+--- a/indra/llmessage/lltemplatemessagereader.cpp
++++ b/indra/llmessage/lltemplatemessagereader.cpp
+@@ -676,7 +676,8 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
+ 						// default to 0s.
+ 						U32 size = mvci.getSize();
+ 						std::vector<U8> data(size);
+-						memset(&(data[0]), 0, size);
++						if(size>0)
++							memset(&(data[0]), 0, size);
+ 						cur_data_block->addData(mvci.getName(), &(data[0]), 
+ 												size, mvci.getType());
+ 					}
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/lltemplatemessagereader_memcpy (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/no_format_or_string_literal.diff b/debian/patches/topic/fixes/jira-sent/no_format_or_string_literal.diff
new file mode 100644
index 0000000..60b44f4
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/no_format_or_string_literal.diff
@@ -0,0 +1,27 @@
+From: Guillermo Gutiérrez Herrera <terrex at xiterrex.net>
+Subject: [PATCH] topic/fixes/jira-sent/no_format_or_string_literal
+
+Correcty pass format specifier to string via string literal
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+Signed-off-by: Guillermo Gutiérrez Herrera <terrex at xiterrex.net>
+
+---
+ indra/linux_crash_logger/llcrashloggerlinux.cpp |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp
+index 467dacf..ae8038c 100644
+--- a/indra/linux_crash_logger/llcrashloggerlinux.cpp
++++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp
+@@ -90,7 +90,7 @@ static BOOL do_ask_dialog(void)
+ 
+ 	win = gtk_message_dialog_new(NULL,
+ 				     flags, messagetype, buttons,
+-				     dialog_text);
++				     "%s", dialog_text);
+ 	gtk_window_set_type_hint(GTK_WINDOW(win),
+ 				 GDK_WINDOW_TYPE_HINT_DIALOG);
+ 	gtk_window_set_title(GTK_WINDOW(win), dialog_title);
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/no_format_or_string_literal (depends on: upstream)
diff --git a/debian/patches/topic/fixes/jira-sent/use_c_locale_and_dont_spam_me_because_i_am_not_american.diff b/debian/patches/topic/fixes/jira-sent/use_c_locale_and_dont_spam_me_because_i_am_not_american.diff
new file mode 100644
index 0000000..ac0c0e6
--- /dev/null
+++ b/debian/patches/topic/fixes/jira-sent/use_c_locale_and_dont_spam_me_because_i_am_not_american.diff
@@ -0,0 +1,29 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/jira-sent/use_c_locale_and_dont_spam_me_because_i_am_not_american
+
+Better protection of locales, and don't enforce en_US.UTF-8
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llui/llresmgr.cpp |    5 ++++-
+ 1 files changed, 4 insertions(+), 1 deletions(-)
+
+diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
+index d111bd6..9d8c283 100644
+--- a/indra/llui/llresmgr.cpp
++++ b/indra/llui/llresmgr.cpp
+@@ -446,7 +446,10 @@ const std::string LLLocale::SYSTEM_LOCALE("en_US.iso8859-1");
+ const std::string LLLocale::USER_LOCALE("en_US.ISO8859-1");
+ const std::string LLLocale::SYSTEM_LOCALE("C");
+ #else // LL_LINUX likes this
+-const std::string LLLocale::USER_LOCALE("en_US.utf8");
++//const std::string LLLocale::USER_LOCALE("en_US.utf8");
++// this is a good chance that I AM NOT AN AMERICAN don't assume that i am and
++// assume i have an american locale installed, C should do for the viewer
++const std::string LLLocale::USER_LOCALE("C");
+ const std::string LLLocale::SYSTEM_LOCALE("C");
+ #endif
+ 
+-- 
+tg: (fd717f3..) topic/fixes/jira-sent/use_c_locale_and_dont_spam_me_because_i_am_not_american (depends on: upstream)
diff --git a/debian/patches/topic/fixes/new/allow_compilation_when_GST_DISABLE_GST_DEBUG_is_defined.diff b/debian/patches/topic/fixes/new/allow_compilation_when_GST_DISABLE_GST_DEBUG_is_defined.diff
new file mode 100644
index 0000000..105e963
--- /dev/null
+++ b/debian/patches/topic/fixes/new/allow_compilation_when_GST_DISABLE_GST_DEBUG_is_defined.diff
@@ -0,0 +1,44 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/fixes/new/allow_compilation_when_GST_DISABLE_GST_DEBUG_is_defined
+
+Allow compilation when GST_DISABLE_GST_DEBUG is defined.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/llmedia/llmediaimplgstreamer_syms.h       |    2 ++
+ indra/llmedia/llmediaimplgstreamer_syms_raw.inc |    2 ++
+ 2 files changed, 4 insertions(+), 0 deletions(-)
+
+diff --git a/indra/llmedia/llmediaimplgstreamer_syms.h b/indra/llmedia/llmediaimplgstreamer_syms.h
+index 6957b1c..29ac00d 100644
+--- a/indra/llmedia/llmediaimplgstreamer_syms.h
++++ b/indra/llmedia/llmediaimplgstreamer_syms.h
+@@ -67,8 +67,10 @@ void ungrab_gst_syms();
+ #define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type())
+ #undef _gst_debug_register_funcptr
+ #define _gst_debug_register_funcptr ll_gst_debug_register_funcptr
++#ifndef GST_DISABLE_GST_DEBUG
+ #undef _gst_debug_category_new
+ #define _gst_debug_category_new ll_gst_debug_category_new
++#endif
+ #undef __gst_debug_enabled
+ #define __gst_debug_enabled (0)
+ 
+diff --git a/indra/llmedia/llmediaimplgstreamer_syms_raw.inc b/indra/llmedia/llmediaimplgstreamer_syms_raw.inc
+index 08ba6df..eb2b3ee 100644
+--- a/indra/llmedia/llmediaimplgstreamer_syms_raw.inc
++++ b/indra/llmedia/llmediaimplgstreamer_syms_raw.inc
+@@ -19,8 +19,10 @@ LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klas
+ LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details);
+ LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps);
+ LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps);
++#ifndef GST_DISABLE_GST_DEBUG
+ LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname);
+ LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description);
++#endif
+ LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps);
+ LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string);
+ LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps);
+-- 
+tg: (fd717f3..) topic/fixes/new/allow_compilation_when_GST_DISABLE_GST_DEBUG_is_defined (depends on: upstream)
diff --git a/debian/patches/topic/fixes/new/delete_LLImageTGA_mColorMap_as_array.diff b/debian/patches/topic/fixes/new/delete_LLImageTGA_mColorMap_as_array.diff
new file mode 100644
index 0000000..1fd9e03
--- /dev/null
+++ b/debian/patches/topic/fixes/new/delete_LLImageTGA_mColorMap_as_array.diff
@@ -0,0 +1,26 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/fixes/new/delete_LLImageTGA_mColorMap_as_array
+
+The destructor of LLImageTGA should delete mColorMap with 'operator delete[]', not 'operator delete'.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/llimage/llimagetga.cpp |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp
+index 853a0dc..c72a1cd 100644
+--- a/indra/llimage/llimagetga.cpp
++++ b/indra/llimage/llimagetga.cpp
+@@ -104,7 +104,7 @@ LLImageTGA::LLImageTGA(const std::string& file_name)
+ 
+ LLImageTGA::~LLImageTGA()
+ {
+-	delete mColorMap;
++	delete [] mColorMap;
+ }
+ 
+ BOOL LLImageTGA::updateData()
+-- 
+tg: (fd717f3..) topic/fixes/new/delete_LLImageTGA_mColorMap_as_array (depends on: upstream)
diff --git a/debian/patches/topic/fixes/thirdparty/0000_keep_statbars_from_overshooting.patch.diff b/debian/patches/topic/fixes/thirdparty/0000_keep_statbars_from_overshooting.patch.diff
new file mode 100644
index 0000000..3a57d31
--- /dev/null
+++ b/debian/patches/topic/fixes/thirdparty/0000_keep_statbars_from_overshooting.patch.diff
@@ -0,0 +1,54 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/thirdparty/0000_keep_statbars_from_overshooting.patch
+
+fix an issue with status bars overshooting their window
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/newview/llstatbar.cpp |   13 +++++++------
+ 1 files changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/indra/newview/llstatbar.cpp b/indra/newview/llstatbar.cpp
+index 2673166..88b329a 100644
+--- a/indra/newview/llstatbar.cpp
++++ b/indra/newview/llstatbar.cpp
+@@ -213,6 +213,7 @@ void LLStatBar::draw()
+ 		}
+ 
+ 		right = (S32) ((max - mMinBar) * value_scale);
++		right = llclamp(0, right, width);
+ 		gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 0.f, 0.f, 0.25f));
+ 
+ 		S32 num_values = mStatp->getNumValues() - 1;
+@@ -228,22 +229,22 @@ void LLStatBar::draw()
+ 				if (mPerSec)
+ 				{
+ 					left = (S32)((mStatp->getPrevPerSec(i) - mMinBar) * value_scale);
+-					right = (S32)((mStatp->getPrevPerSec(i) - mMinBar) * value_scale) + 1;
+-					gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f));
+ 				}
+ 				else
+ 				{
+ 					left = (S32)((mStatp->getPrev(i) - mMinBar) * value_scale);
+-					right = (S32)((mStatp->getPrev(i) - mMinBar) * value_scale) + 1;
+-					gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f));
+-				}
++				}	
++				left = llclamp(0, left, width-1);
++				right = left+1;
++				gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f));
+ 			}
+ 		}
+ 		else
+ 		{
+ 			// draw current
+ 			left = (S32) ((current - mMinBar) * value_scale) - 1;
+-			right = (S32) ((current - mMinBar) * value_scale) + 1;
++			left = llclamp(0, left, width-1);
++			right = left + 2;
+ 			gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 0.f, 0.f, 1.f));
+ 		}
+ 
+-- 
+tg: (fd717f3..) topic/fixes/thirdparty/0000_keep_statbars_from_overshooting.patch (depends on: upstream)
diff --git a/debian/patches/topic/fixes/thirdparty/0001_possible_crash_and_leak_llassetstorage.patch.diff b/debian/patches/topic/fixes/thirdparty/0001_possible_crash_and_leak_llassetstorage.patch.diff
new file mode 100644
index 0000000..86fb7d8
--- /dev/null
+++ b/debian/patches/topic/fixes/thirdparty/0001_possible_crash_and_leak_llassetstorage.patch.diff
@@ -0,0 +1,148 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/thirdparty/0001_possible_crash_and_leak_llassetstorage.patch
+
+possible crash and memory leak
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llmessage/llassetstorage.cpp |   41 ++++++++++++++++++-----------------
+ 1 files changed, 21 insertions(+), 20 deletions(-)
+
+diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
+index a89a786..5970a34 100644
+--- a/indra/llmessage/llassetstorage.cpp
++++ b/indra/llmessage/llassetstorage.cpp
+@@ -522,16 +522,19 @@ void LLAssetStorage::downloadCompleteCallback(
+ 	S32 result,
+ 	const LLUUID& file_id,
+ 	LLAssetType::EType file_type,
+-	void* user_data, LLExtStat ext_status)
++	void* callback_parm_req, LLExtStat ext_status)
+ {
+ 	lldebugs << "LLAssetStorage::downloadCompleteCallback() for " << file_id
+ 		 << "," << LLAssetType::lookup(file_type) << llendl;
+-	LLAssetRequest* req = (LLAssetRequest*)user_data;
++
++	// be careful! req may be a ptr to memory already freed (a timeout does this)
++	LLAssetRequest* req = (LLAssetRequest*)callback_parm_req;	
+ 	if(!req)
+ 	{
+ 		llwarns << "LLAssetStorage::downloadCompleteCallback called without"
+ 			"a valid request." << llendl;
+-		return;
++		// we can live with a null pointer, we're not allowed to deref the ptr anyway (see above)
++		// return;  
+ 	}
+ 	if (!gAssetStorage)
+ 	{
+@@ -539,12 +542,10 @@ void LLAssetStorage::downloadCompleteCallback(
+ 		return;
+ 	}
+ 
+-	req->setUUID(file_id);
+-	req->setType(file_type);
+ 	if (LL_ERR_NOERR == result)
+ 	{
+ 		// we might have gotten a zero-size file
+-		LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType());
++		LLVFile vfile(gAssetStorage->mVFS, file_id, file_type);
+ 		if (vfile.getSize() <= 0)
+ 		{
+ 			llwarns << "downloadCompleteCallback has non-existent or zero-size asset " << req->getUUID() << llendl;
+@@ -563,7 +564,7 @@ void LLAssetStorage::downloadCompleteCallback(
+ 	{
+ 		request_list_t::iterator curiter = iter++;
+ 		LLAssetRequest* tmp = *curiter;
+-		if ((tmp->getUUID() == req->getUUID()) && (tmp->getType()== req->getType()))
++		if ((tmp->getUUID() == file_id) && (tmp->getType() == file_type))
+ 		{
+ 			requests.push_front(tmp);
+ 			iter = gAssetStorage->mPendingDownloads.erase(curiter);
+@@ -576,7 +577,7 @@ void LLAssetStorage::downloadCompleteCallback(
+ 		LLAssetRequest* tmp = *curiter;
+ 		if (tmp->mDownCallback)
+ 		{
+-			tmp->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), tmp->mUserData, result, ext_status);
++			tmp->mDownCallback(gAssetStorage->mVFS, tmp->getUUID(), tmp->getType(), tmp->mUserData, result, ext_status);
+ 		}
+ 		delete tmp;
+ 	}
+@@ -672,10 +673,10 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback(
+ 	S32 result,
+ 	const LLUUID& file_id,
+ 	LLAssetType::EType file_type,
+-	void* user_data,
++	void* callback_parm_req,
+ 	LLExtStat ext_status)
+ {
+-	LLEstateAssetRequest *req = (LLEstateAssetRequest*)user_data;
++	LLEstateAssetRequest *req = (LLEstateAssetRequest*)callback_parm_req;
+ 	if(!req)
+ 	{
+ 		llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
+@@ -689,12 +690,10 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback(
+ 		return;
+ 	}
+ 
+-	req->setUUID(file_id);
+-	req->setType(file_type);
+ 	if (LL_ERR_NOERR == result)
+ 	{
+ 		// we might have gotten a zero-size file
+-		LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getAType());
++		LLVFile vfile(gAssetStorage->mVFS, file_id, file_type);
+ 		if (vfile.getSize() <= 0)
+ 		{
+ 			llwarns << "downloadCompleteCallback has non-existent or zero-size asset!" << llendl;
+@@ -704,7 +703,9 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback(
+ 		}
+ 	}
+ 
+-	req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getAType(), req->mUserData, result, ext_status);
++	req->mDownCallback(gAssetStorage->mVFS, file_id, file_type, req->mUserData, result, ext_status);
++
++	delete req;
+ }
+ 
+ void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
+@@ -809,10 +810,10 @@ void LLAssetStorage::downloadInvItemCompleteCallback(
+ 	S32 result,
+ 	const LLUUID& file_id,
+ 	LLAssetType::EType file_type,
+-	void* user_data,
++	void* callback_parm_req,
+ 	LLExtStat ext_status)
+ {
+-	LLInvItemRequest *req = (LLInvItemRequest*)user_data;
++	LLInvItemRequest *req = (LLInvItemRequest*)callback_parm_req;
+ 	if(!req)
+ 	{
+ 		llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
+@@ -825,12 +826,10 @@ void LLAssetStorage::downloadInvItemCompleteCallback(
+ 		return;
+ 	}
+ 
+-	req->setUUID(file_id);
+-	req->setType(file_type);
+ 	if (LL_ERR_NOERR == result)
+ 	{
+ 		// we might have gotten a zero-size file
+-		LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType());
++		LLVFile vfile(gAssetStorage->mVFS, file_id, file_type);
+ 		if (vfile.getSize() <= 0)
+ 		{
+ 			llwarns << "downloadCompleteCallback has non-existent or zero-size asset!" << llendl;
+@@ -840,7 +839,9 @@ void LLAssetStorage::downloadInvItemCompleteCallback(
+ 		}
+ 	}
+ 
+-	req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), req->mUserData, result, ext_status);
++	req->mDownCallback(gAssetStorage->mVFS, file_id, file_type, req->mUserData, result, ext_status);
++
++	delete req;
+ }
+ 
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+-- 
+tg: (fd717f3..) topic/fixes/thirdparty/0001_possible_crash_and_leak_llassetstorage.patch (depends on: upstream)
diff --git a/debian/patches/topic/fixes/thirdparty/0001_possible_crash_in_llviewerpartssim.diff b/debian/patches/topic/fixes/thirdparty/0001_possible_crash_in_llviewerpartssim.diff
new file mode 100644
index 0000000..be6ffa8
--- /dev/null
+++ b/debian/patches/topic/fixes/thirdparty/0001_possible_crash_in_llviewerpartssim.diff
@@ -0,0 +1,38 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/thirdparty/0001_possible_crash_in_llviewerpartssim
+
+Another possible crash fix
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/newview/llviewerpartsim.cpp |   13 ++++++++++---
+ 1 files changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp
+index 529ec4d..34217a2 100644
+--- a/indra/newview/llviewerpartsim.cpp
++++ b/indra/newview/llviewerpartsim.cpp
+@@ -686,10 +686,17 @@ void LLViewerPartSim::updateSimulation()
+ 		S32 visirate = 1;
+ 		if (vobj)
+ 		{
+-			LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup();
+-			if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY))
++			if(vobj->mDrawable)
+ 			{
+-				visirate = 8;
++				LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup();
++				if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY))
++				{
++					visirate = 8;
++				}
++			}
++			else
++			{
++				llwarns << "Crash avoided, vobj->mDrawable is NULL" << llendl;
+ 			}
+ 		}
+ 
+-- 
+tg: (fd717f3..) topic/fixes/thirdparty/0001_possible_crash_in_llviewerpartssim (depends on: upstream)
diff --git a/debian/patches/topic/fixes/thirdparty/1294_llworkerthread_when_terminating_program.patch.diff b/debian/patches/topic/fixes/thirdparty/1294_llworkerthread_when_terminating_program.patch.diff
new file mode 100644
index 0000000..9258447
--- /dev/null
+++ b/debian/patches/topic/fixes/thirdparty/1294_llworkerthread_when_terminating_program.patch.diff
@@ -0,0 +1,26 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/thirdparty/1294_llworkerthread_when_terminating_program.patch
+
+Kill a llworker thread when exiting
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llcommon/llworkerthread.cpp |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
+index 96a957b..a28259b 100644
+--- a/indra/llcommon/llworkerthread.cpp
++++ b/indra/llcommon/llworkerthread.cpp
+@@ -111,7 +111,7 @@ S32 LLWorkerThread::update(U32 max_time_ms)
+ 	}
+ 	LLWorkerClass::sDeleteLock = FALSE ;
+     // delete and aborted entries mean there's still work to do
+-	res += delete_list.size() + abort_list.size();
++	res +=  !mDeleteList.empty() + !delete_list.empty();  // deleted entries mean there's still work to do
+ 	return res;
+ }
+ 
+-- 
+tg: (fd717f3..) topic/fixes/thirdparty/1294_llworkerthread_when_terminating_program.patch (depends on: upstream)
diff --git a/debian/patches/topic/fixes/thirdparty/1857_apr_thread_mutex_nested.patch.diff b/debian/patches/topic/fixes/thirdparty/1857_apr_thread_mutex_nested.patch.diff
new file mode 100644
index 0000000..f92f02e
--- /dev/null
+++ b/debian/patches/topic/fixes/thirdparty/1857_apr_thread_mutex_nested.patch.diff
@@ -0,0 +1,56 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/thirdparty/1857_apr_thread_mutex_nested.patch
+
+Fix issue with nested apt thread mutex
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llcommon/llapr.cpp     |    2 +-
+ indra/llcommon/llthread.cpp  |    2 +-
+ indra/llmessage/llpumpio.cpp |    4 ++--
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
+index 589d3f5..0613df5 100644
+--- a/indra/llcommon/llapr.cpp
++++ b/indra/llcommon/llapr.cpp
+@@ -47,7 +47,7 @@ void ll_init_apr()
+ 		apr_pool_create(&gAPRPoolp, NULL);
+ 
+ 		// Initialize the logging mutex
+-		apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
++		apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_NESTED, gAPRPoolp);
+ 	}
+ }
+ 
+diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
+index b31c9ab..b187e50 100644
+--- a/indra/llcommon/llthread.cpp
++++ b/indra/llcommon/llthread.cpp
+@@ -276,7 +276,7 @@ LLMutex::LLMutex(apr_pool_t *poolp) :
+ 		mIsLocalPool = TRUE;
+ 		apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
+ 	}
+-	apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
++	apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_NESTED, mAPRPoolp);
+ }
+ 
+ 
+diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
+index 01a43ec..bb754c2 100644
+--- a/indra/llmessage/llpumpio.cpp
++++ b/indra/llmessage/llpumpio.cpp
+@@ -830,8 +830,8 @@ void LLPumpIO::initialize(apr_pool_t* pool)
+ 	if(!pool) return;
+ #if LL_THREADS_APR
+ 	// SJB: Windows defaults to NESTED and OSX defaults to UNNESTED, so use UNNESTED explicitly.
+-	apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, pool);
+-	apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, pool);
++	apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_NESTED, pool);
++	apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_NESTED, pool);
+ #endif
+ 	mPool = pool;
+ }
+-- 
+tg: (fd717f3..) topic/fixes/thirdparty/1857_apr_thread_mutex_nested.patch (depends on: upstream)
diff --git a/debian/patches/topic/fixes/thirdparty/2003_possible_crash_draganddrop.patch.diff b/debian/patches/topic/fixes/thirdparty/2003_possible_crash_draganddrop.patch.diff
new file mode 100644
index 0000000..c5cc270
--- /dev/null
+++ b/debian/patches/topic/fixes/thirdparty/2003_possible_crash_draganddrop.patch.diff
@@ -0,0 +1,30 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/thirdparty/2003_possible_crash_draganddrop.patch
+
+Possible crash fix
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/newview/lltooldraganddrop.cpp |    6 ++++++
+ 1 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
+index c83d0f4..efd8060 100644
+--- a/indra/newview/lltooldraganddrop.cpp
++++ b/indra/newview/lltooldraganddrop.cpp
+@@ -850,6 +850,12 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
+ 		{
+ 			LLInventoryObject* cargo = locateInventory(item, cat);
+ 
++			if (!cargo) 
++			{
++				handled = FALSE;
++				break;
++			}
++
+ 			EAcceptance item_acceptance = ACCEPT_NO;
+ 			handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE,
+ 												mCargoTypes[mCurItemIndex],
+-- 
+tg: (fd717f3..) topic/fixes/thirdparty/2003_possible_crash_draganddrop.patch (depends on: upstream)
diff --git a/debian/patches/topic/fixes/thirdparty/2543_possible_crash_in_group_voting_propsals.patch.diff b/debian/patches/topic/fixes/thirdparty/2543_possible_crash_in_group_voting_propsals.patch.diff
new file mode 100644
index 0000000..675afce
--- /dev/null
+++ b/debian/patches/topic/fixes/thirdparty/2543_possible_crash_in_group_voting_propsals.patch.diff
@@ -0,0 +1,126 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/thirdparty/2543_possible_crash_in_group_voting_propsals.patch
+
+Possible crash fix
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/llui/llscrolllistctrl.cpp      |   18 ++++++++++++++++++
+ indra/newview/llpanelgroupvoting.cpp |    9 ++++++++-
+ 2 files changed, 26 insertions(+), 1 deletions(-)
+
+diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
+index 7dba55f..4691701 100644
+--- a/indra/llui/llscrolllistctrl.cpp
++++ b/indra/llui/llscrolllistctrl.cpp
+@@ -676,6 +676,11 @@ void LLScrollListCtrl::clearRows()
+ 
+ LLScrollListItem* LLScrollListCtrl::getFirstSelected() const
+ {
++	if (!getCanSelect())
++	{
++		return NULL;
++	}
++
+ 	item_list::const_iterator iter;
+ 	for(iter = mItemList.begin(); iter != mItemList.end(); iter++)
+ 	{
+@@ -691,6 +696,13 @@ LLScrollListItem* LLScrollListCtrl::getFirstSelected() const
+ std::vector<LLScrollListItem*> LLScrollListCtrl::getAllSelected() const
+ {
+ 	std::vector<LLScrollListItem*> ret;
++
++	if (!getCanSelect())
++	{
++		return ret;
++	}
++
++
+ 	item_list::const_iterator iter;
+ 	for(iter = mItemList.begin(); iter != mItemList.end(); iter++)
+ 	{
+@@ -705,6 +717,12 @@ std::vector<LLScrollListItem*> LLScrollListCtrl::getAllSelected() const
+ 
+ S32 LLScrollListCtrl::getFirstSelectedIndex() const
+ {
++	if (!getCanSelect())
++	{
++		return -1;
++	}
++
++
+ 	S32 CurSelectedIndex = 0;
+ 	item_list::const_iterator iter;
+ 	for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
+diff --git a/indra/newview/llpanelgroupvoting.cpp b/indra/newview/llpanelgroupvoting.cpp
+index 41650ad..d3783d5 100644
+--- a/indra/newview/llpanelgroupvoting.cpp
++++ b/indra/newview/llpanelgroupvoting.cpp
+@@ -592,6 +592,7 @@ void LLPanelGroupVoting::impl::sendGroupProposalsRequest(const LLUUID& group_id)
+ 	//we're pining the server in high latency situations
+ 	addPendingActiveScrollListItem(0, 0, ADD_BOTTOM);
+ 	mProposals->setCanSelect(FALSE);
++	mBtnViewProposalItem->setEnabled(FALSE);
+ 
+ 	LLMessageSystem *msg = gMessageSystem;
+ 	msg->newMessageFast(_PREHASH_GroupActiveProposalsRequest);
+@@ -870,6 +871,7 @@ void LLPanelGroupVoting::impl::sendGroupVoteHistoryRequest(const LLUUID& group_i
+ 	//add some text so the user knows we're doing something
+ 	addPendingHistoryScrollListItem(0, 0, ADD_BOTTOM);
+ 	mVotesHistory->setCanSelect(FALSE);
++	mBtnViewHistoryItem->setEnabled(FALSE);
+ 
+ 	LLMessageSystem *msg = gMessageSystem;
+ 	msg->newMessageFast(_PREHASH_GroupVoteHistoryRequest);
+@@ -1066,6 +1068,7 @@ void LLPanelGroupVoting::impl::processGroupActiveProposalItemReply(LLMessageSyst
+ 		//no active proposals and make the scroll list unselectable
+ 		self->addNoActiveScrollListItem(ADD_BOTTOM);
+ 		self->mProposals->setCanSelect(FALSE);
++		self->mBtnViewProposalItem->setEnabled(FALSE);
+ 	}
+ 	else if ( (U32)received != num_expected )
+ 	{
+@@ -1073,6 +1076,7 @@ void LLPanelGroupVoting::impl::processGroupActiveProposalItemReply(LLMessageSyst
+ 											 num_expected,
+ 											 ADD_BOTTOM);
+ 		self->mProposals->setCanSelect(FALSE);
++		self->mBtnViewProposalItem->setEnabled(FALSE);
+ 	}
+ 	else
+ 	{
+@@ -1086,6 +1090,7 @@ void LLPanelGroupVoting::impl::processGroupActiveProposalItemReply(LLMessageSyst
+ 		}
+ 
+ 		self->mProposals->setCanSelect(TRUE);
++		self->mBtnViewProposalItem->setEnabled(TRUE);
+ 	}
+ }
+ 
+@@ -1134,7 +1139,7 @@ void LLPanelGroupVoting::impl::processGroupVoteHistoryItemReply(LLMessageSystem
+ 		//no active proposals and make the scroll list unselectable
+ 		self->addNoHistoryScrollListItem(ADD_BOTTOM);
+ 		self->mVotesHistory->setCanSelect(FALSE);
+-
++		self->mBtnViewHistoryItem->setEnabled(FALSE);
+ 		return;
+ 	}
+ 
+@@ -1248,6 +1253,7 @@ void LLPanelGroupVoting::impl::processGroupVoteHistoryItemReply(LLMessageSystem
+ 											  num_expected,
+ 											  ADD_BOTTOM);
+ 		self->mVotesHistory->setCanSelect(FALSE);
++		self->mBtnViewHistoryItem->setEnabled(FALSE);
+ 	}
+ 	else
+ 	{
+@@ -1261,6 +1267,7 @@ void LLPanelGroupVoting::impl::processGroupVoteHistoryItemReply(LLMessageSystem
+ 		}
+ 
+ 		self->mVotesHistory->setCanSelect(TRUE);
++		self->mBtnViewHistoryItem->setEnabled(TRUE);
+ 	}
+ }
+ 
+-- 
+tg: (fd717f3..) topic/fixes/thirdparty/2543_possible_crash_in_group_voting_propsals.patch (depends on: upstream)
diff --git a/debian/patches/topic/fixes/thirdparty/2683_possible_crash_update_speaker_list.patch.diff b/debian/patches/topic/fixes/thirdparty/2683_possible_crash_update_speaker_list.patch.diff
new file mode 100644
index 0000000..e313b81
--- /dev/null
+++ b/debian/patches/topic/fixes/thirdparty/2683_possible_crash_update_speaker_list.patch.diff
@@ -0,0 +1,51 @@
+From: Robin Cornelius <robin.cornelius at gmail.com>
+Subject: [PATCH] topic/fixes/thirdparty/2683_possible_crash_update_speaker_list.patch
+
+Possible crash fix
+
+Signed-off-by: Robin Cornelius <robin.cornelius at gmail.com>
+
+---
+ indra/newview/llfloateractivespeakers.cpp |    4 ++--
+ indra/newview/llviewerobjectlist.cpp      |    4 ++++
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/indra/newview/llfloateractivespeakers.cpp b/indra/newview/llfloateractivespeakers.cpp
+index be0e88f..7314534 100644
+--- a/indra/newview/llfloateractivespeakers.cpp
++++ b/indra/newview/llfloateractivespeakers.cpp
+@@ -1369,7 +1369,7 @@ void LLLocalSpeakerMgr::updateSpeakerList()
+ 	for(avatar_it = LLCharacter::sInstances.begin(); avatar_it != LLCharacter::sInstances.end(); ++avatar_it)
+ 	{
+ 		LLVOAvatar* avatarp = (LLVOAvatar*)*avatar_it;
+-		if (dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) <= CHAT_NORMAL_RADIUS)
++		if (!avatarp->isDead() &&  dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) <= CHAT_NORMAL_RADIUS)
+ 		{
+ 			setSpeaker(avatarp->getID());
+ 		}
+@@ -1383,7 +1383,7 @@ void LLLocalSpeakerMgr::updateSpeakerList()
+ 		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)
++			if (!avatarp || avatarp->isDead() || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS)
+ 			{
+ 				speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ 				speakerp->mDotColor = INACTIVE_COLOR;
+diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
+index e28a768..9b85fec 100644
+--- a/indra/newview/llviewerobjectlist.cpp
++++ b/indra/newview/llviewerobjectlist.cpp
+@@ -873,6 +873,10 @@ void LLViewerObjectList::killObjects(LLViewerRegion *regionp)
+ 		if (objectp->mRegionp == regionp)
+ 		{
+ 			killObject(objectp);
++
++			// invalidate region pointer. region will become invalid, but 
++			// refcounted objects may survive the cleanDeadObjects() call below
++			objectp->mRegionp = NULL;	 
+ 		}
+ 	}
+ 
+-- 
+tg: (fd717f3..) topic/fixes/thirdparty/2683_possible_crash_update_speaker_list.patch (depends on: upstream)
diff --git a/debian/patches/topic/pandora/add_support_for_libcwd.diff b/debian/patches/topic/pandora/add_support_for_libcwd.diff
new file mode 100644
index 0000000..cc56ff9
--- /dev/null
+++ b/debian/patches/topic/pandora/add_support_for_libcwd.diff
@@ -0,0 +1,815 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/pandora/add_support_for_libcwd
+
+This adds support for libcwd (version 1.0.1 or higher).
+In order to actually link with libcwd_r, you need to
+have the string 'libcwd' in DEB_BUILD_OPTIONS.
+For example: DEB_BUILD_OPTIONS="parallel=4 noopt libcwd"
+
+Furthermore, for debugging in general, it is
+highly recommended to use:
+
+CXXFLAGS+="-g3"
+
+This patch also introduces two commands that can be run
+from without gdb:
+
+(gdb) call cwdebug_start
+(gdb) c
+^C
+(gdb) call cwdebug_stop
+
+which starts and stops recording backtraces for
+calls to malloc.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ debian/conffiles/libcwd                 |   22 ++
+ indra/CMakeLists.txt                    |    1 +
+ indra/cmake/Cwdebug.cmake               |    1 +
+ indra/cwdebug/CMakeLists.txt            |   31 +++
+ indra/cwdebug/cwdebug.h                 |    9 +
+ indra/cwdebug/debug.cc                  |  388 +++++++++++++++++++++++++++++++
+ indra/cwdebug/debug.h                   |  176 ++++++++++++++
+ indra/cwdebug/debug_ostream_operators.h |    1 +
+ indra/cwdebug/sys.h                     |    9 +
+ indra/linux_crash_logger/CMakeLists.txt |    2 +
+ indra/llcommon/llerror.cpp              |    8 +
+ indra/newview/CMakeLists.txt            |    2 +
+ indra/newview/llappviewerlinux.cpp      |    3 +
+ 13 files changed, 653 insertions(+), 0 deletions(-)
+
+diff --git a/debian/conffiles/libcwd b/debian/conffiles/libcwd
+new file mode 100644
+index 0000000..199d23c
+--- /dev/null
++++ b/debian/conffiles/libcwd
+@@ -0,0 +1,22 @@
++# Debug code and actually linking with libcwd_r is only done if
++# DEB_BUILD_OPTIONS contains the string 'libcwd'.
++for opt in $DEB_BUILD_OPTIONS dummy; do
++  if [ "$opt" = "libcwd" ]; then
++    if expr match "$(pkg-config --cflags libcwd_r)" ".*-D_GLIBCXX_DEBUG" >/dev/null; then
++      CONFFILE_CMAKE_ARGUMENTS+=" -DBOOST_INCLUDEDIR=\"/sl/_GLIBCXX_DEBUG/include/boost-1_37\" -DBOOST_LIBRARYDIR=\"/sl/_GLIBCXX_DEBUG/lib\""
++    fi
++    LDFLAGS+=" $(pkg-config --libs libcwd_r)"
++    CXXFLAGS+=" $(pkg-config --cflags libcwd_r)"
++    if [ $? -ne 0 ]; then
++      exit $?
++    fi
++  fi
++done
++
++# We have to use a full path here in order for cmake's 'compile a simple test'
++# to work. Correct would be to add ${CWDEBUG_INCLUDE_DIRS} to the
++# include_directories of every CMakeLists.txt, but the whole point of
++# doing this -include is to avoid too many collision with upstream
++# changes by NOT having to change a lot of files.
++CXXFLAGS+=" -I`pwd`/indra/cwdebug -include cwdebug.h"
++
+diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
+index c473b94..7aa95cc 100644
+--- a/indra/CMakeLists.txt
++++ b/indra/CMakeLists.txt
+@@ -34,6 +34,7 @@ file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/temp)
+ file(WRITE ${CMAKE_BINARY_DIR}/temp/sentinel_installed "0")
+ add_subdirectory(cmake)
+ 
++add_subdirectory(${LIBS_OPEN_PREFIX}cwdebug)
+ add_subdirectory(${LIBS_OPEN_PREFIX}llaudio)
+ add_subdirectory(${LIBS_OPEN_PREFIX}llcharacter)
+ add_subdirectory(${LIBS_OPEN_PREFIX}llcommon)
+diff --git a/indra/cmake/Cwdebug.cmake b/indra/cmake/Cwdebug.cmake
+new file mode 100644
+index 0000000..9568a62
+--- /dev/null
++++ b/indra/cmake/Cwdebug.cmake
+@@ -0,0 +1 @@
++set(CWDEBUG_LIBRARIES cwdebug)
+diff --git a/indra/cwdebug/CMakeLists.txt b/indra/cwdebug/CMakeLists.txt
+new file mode 100644
+index 0000000..e3dc504
+--- /dev/null
++++ b/indra/cwdebug/CMakeLists.txt
+@@ -0,0 +1,31 @@
++# -*- cmake -*-
++
++project(cwdebug)
++
++include(00-Common)
++include(LLCommon)
++include(LLMath)
++include(LLMessage)
++include(LLVFS)
++
++include_directories (${CMAKE_CURRENT_SOURCE_DIR})
++
++set(cwdebug_SOURCE_FILES
++    debug.cc
++    )
++
++set(cwdebug_HEADER_FILES
++    CMakeLists.txt
++
++    cwdebug.h
++    sys.h
++    debug.h
++    debug_ostream_operators.h
++    )
++
++set_source_files_properties(${cwdebug_HEADER_FILES}
++                            PROPERTIES HEADER_FILE_ONLY TRUE)
++
++list(APPEND cwdebug_SOURCE_FILES ${cwdebug_HEADER_FILES})
++
++add_library (cwdebug ${cwdebug_SOURCE_FILES})
+diff --git a/indra/cwdebug/cwdebug.h b/indra/cwdebug/cwdebug.h
+new file mode 100644
+index 0000000..37415df
+--- /dev/null
++++ b/indra/cwdebug/cwdebug.h
+@@ -0,0 +1,9 @@
++// We support compiling C++ source files that are not
++// thread-safe, but in that case we assume that they
++// will not be linked with libcwd_r.
++#if !defined(_REENTRANT) || !defined(__linux__)
++#undef CWDEBUG
++#endif
++
++#include "sys.h"
++#include "debug.h"
+diff --git a/indra/cwdebug/debug.cc b/indra/cwdebug/debug.cc
+new file mode 100644
+index 0000000..92fa8e4
+--- /dev/null
++++ b/indra/cwdebug/debug.cc
+@@ -0,0 +1,388 @@
++// slviewer -- Second Life Viewer Source Code
++//
++//! @file debug.cc
++//! @brief This file contains the definitions of debug related objects and functions.
++//
++// Copyright (C) 2008, by
++// 
++// Carlo Wood, Run on IRC <carlo at alinoe.com>
++// RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
++// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
++// 
++// This program is free software: you can redistribute it and/or modify
++// it under the terms of the GNU General Public License as published by
++// the Free Software Foundation, either version 2 of the License, or
++// (at your option) any later version.
++// 
++// This program is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++// 
++// You should have received a copy of the GNU General Public License
++// along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++#ifndef USE_PCH
++#include "sys.h"                        // Needed for platform-specific code
++#endif
++
++#ifdef CWDEBUG
++
++#ifndef USE_PCH
++#include <cctype>                       // Needed for std::isprint
++#include <iomanip>                      // Needed for setfill
++#include <map>
++#include <string>
++#include <sstream>
++#include <boost/shared_array.hpp>
++#include "debug.h"
++#ifdef USE_LIBCW
++#include <libcw/memleak.h>		// memleak_filter
++#endif
++#endif // USE_PCH
++
++#define BACKTRACE_AQUIRE_LOCK           libcwd::_private_::mutex_tct<libcwd::_private_::backtrace_instance>::lock()
++#define BACKTRACE_RELEASE_LOCK          libcwd::_private_::mutex_tct<libcwd::_private_::backtrace_instance>::unlock()
++
++namespace debug {
++
++static int total_calls = 0;
++static int number_of_stack_traces = 0;
++
++class BackTrace {
++  private:
++    boost::shared_array<void*> M_buffer;
++    int M_frames;
++  public:
++    BackTrace(void** buffer, int frames) : M_buffer(new void* [frames]), M_frames(frames) { std::memcpy(M_buffer.get(), buffer, sizeof(void*) * frames); }
++
++    friend bool operator<(BackTrace const& bt1, BackTrace const& bt2)
++    {
++      if (bt1.M_frames != bt2.M_frames)
++	return bt1.M_frames < bt2.M_frames;
++      for (int frame = 0; frame < bt1.M_frames; ++frame)
++	if (bt1.M_buffer[frame] < bt2.M_buffer[frame])
++	  return true;
++        else if (bt1.M_buffer[frame] > bt2.M_buffer[frame])
++	  return true;
++      return false;
++    }
++
++  void dump_backtrace(void) const;
++
++  int frames(void) const { return M_frames; }
++  boost::shared_array<void*> const& buffer(void) const { return M_buffer; }
++};
++
++void BackTrace::dump_backtrace(void) const
++{
++  for (int frame = 0; frame < frames(); ++frame)
++  {
++    Dout(dc::notice, '#' << frame << ' ' << buffer()[frame] << ' ' << location_ct((char*)buffer()[frame] + libcwd::builtin_return_address_offset));
++  }
++}
++
++typedef std::map<BackTrace, int, std::less<BackTrace>, libcwd::_private_::internal_allocator> backtrace_map_t;
++backtrace_map_t* backtrace_map;
++
++void my_backtrace_hook(void** buffer, int frames LIBCWD_COMMA_TSD_PARAM)
++{
++  ++total_calls;
++
++  backtrace_map_t::iterator iter;
++
++  set_alloc_checking_off(__libcwd_tsd);
++  {
++    BackTrace backtrace(buffer, frames);
++    std::pair<backtrace_map_t::iterator, bool> res = backtrace_map->insert(backtrace_map_t::value_type(backtrace, 0));
++    if (res.second)
++      ++number_of_stack_traces;
++    ++res.first->second;
++    iter = res.first;
++  }
++  set_alloc_checking_on(__libcwd_tsd);
++#if 0
++  // Dump the stack trace.
++  iter->first.dump_backtrace();
++#endif
++}
++
++void start_recording_backtraces(void)
++{
++  BACKTRACE_AQUIRE_LOCK;
++  libcwd::backtrace_hook = my_backtrace_hook;
++  BACKTRACE_RELEASE_LOCK;
++  //Debug(dc::malloc.on());
++  LIBCWD_TSD_DECLARATION;
++  set_alloc_checking_off(__libcwd_tsd);
++  backtrace_map = new backtrace_map_t;
++  set_alloc_checking_on(__libcwd_tsd);
++}
++
++struct Compare {
++  bool operator()(backtrace_map_t::const_iterator const& iter1, backtrace_map_t::const_iterator const& iter2)
++  {
++    return iter1->second > iter2->second;
++  }
++};
++
++void stop_recording_backtraces(void)
++{
++  //Debug(dc::malloc.off());
++  BACKTRACE_AQUIRE_LOCK;
++  libcwd::backtrace_hook = NULL;
++
++  if (!backtrace_map)
++  {
++    Dout(dc::notice, "Not recording; call cwdebug_start() first.");
++    return;
++  }
++
++  Dout(dc::notice, "Total number of calls: " << total_calls);
++  Dout(dc::notice, "Number of different stack traces: " << number_of_stack_traces);
++  Dout(dc::notice, "First 10 stack traces:");
++  std::list<backtrace_map_t::const_iterator> entries;
++  for (backtrace_map_t::const_iterator iter = backtrace_map->begin(); iter != backtrace_map->end(); ++iter)
++    entries.push_back(iter);
++  entries.sort(Compare());
++  int count = 0;
++  for (std::list<backtrace_map_t::const_iterator>::iterator iter = entries.begin(); iter != entries.end(); ++iter, ++count)
++  {
++    Dout(dc::notice, "Used: " << (*iter)->second);
++    // Dump the stack trace.
++    (*iter)->first.dump_backtrace();
++    if (count == 10)
++      break;
++  }
++
++  // Clear all data.
++  LIBCWD_TSD_DECLARATION;
++  set_alloc_checking_off(__libcwd_tsd);
++  delete backtrace_map;
++  set_alloc_checking_on(__libcwd_tsd);
++  backtrace_map = NULL;
++  total_calls = 0;
++  number_of_stack_traces = 0;
++
++  BACKTRACE_RELEASE_LOCK;
++}
++
++  namespace channels {	// namespace DEBUGCHANNELS
++    namespace dc {
++
++#ifndef DOXYGEN
++#define DDCN(x) (x)
++#endif
++      // Add new debug channels here.
++
++      channel_ct viewer DDCN("VIEWER");	//!< This debug channel is used for the normal debugging out of the viewer.
++
++    } // namespace dc
++  } // namespace DEBUGCHANNELS
++
++  // Anonymous namespace, this map and its initialization functions are private to this file
++  // for Thead-safeness reasons.
++  namespace {
++
++    /*! @brief The type of rcfile_dc_states.
++     * @internal
++     */
++    typedef std::map<std::string, bool> rcfile_dc_states_type;
++
++    /*! @brief Map containing the default debug channel states used at the start of each new thread.
++     * @internal
++     *
++     * The first thread calls main, which calls debug::init which will initialize this
++     * map with all debug channel labels and whether or not they were turned on in the
++     * rcfile or not.
++     */
++    rcfile_dc_states_type rcfile_dc_states;
++
++    /*! @brief Set the default state of debug channel \a dc_label.
++     * @internal
++     *
++     * This function is called once for each debug channel.
++     */
++    void set_state(char const* dc_label, bool is_on)
++    {
++      std::pair<rcfile_dc_states_type::iterator, bool> res =
++          rcfile_dc_states.insert(rcfile_dc_states_type::value_type(std::string(dc_label), is_on));
++      if (!res.second)
++        Dout(dc::warning, "Calling set_state() more than once for the same label!");
++      return;
++    }
++
++    /*! @brief Save debug channel states.
++     * @internal
++     *
++     * One time initialization function of rcfile_dc_state.
++     * This must be called from debug::init after reading the rcfile.
++     */
++    void save_dc_states(void)
++    {
++      // We may only call this function once: it reflects the states as stored
++      // in the rcfile and that won't change.  Therefore it is not needed to
++      // lock `rcfile_dc_states', it is only written to by the first thread
++      // (once, via main -> init) when there are no other threads yet.
++      static bool second_time = false;
++      if (second_time)
++      {
++        Dout(dc::warning, "Calling save_dc_states() more than once!");
++	return;
++      }
++      second_time = true;
++      ForAllDebugChannels( set_state(debugChannel.get_label(), debugChannel.is_on()) );
++    }
++
++  } // anonymous namespace
++
++  /*! @brief Returns the the original state of a debug channel.
++   * @internal
++   *
++   * For a given \a dc_label, which must be the exact name (<tt>channel_ct::get_label</tt>) of an
++   * existing debug channel, this function returns \c true when the corresponding debug channel was
++   * <em>on</em> at the startup of the application, directly after reading the libcwd runtime
++   * configuration file (.libcwdrc).
++   *
++   * If the label/channel did not exist at the start of the application, it will return \c false
++   * (note that libcwd disallows adding debug channels to modules - so this would probably
++   * a bug).
++   */
++  bool is_on_in_rcfile(char const* dc_label)
++  {
++    rcfile_dc_states_type::const_iterator iter = rcfile_dc_states.find(std::string(dc_label));
++    if (iter == rcfile_dc_states.end())
++    {
++      Dout(dc::warning, "is_on_in_rcfile(\"" << dc_label << "\"): \"" << dc_label << "\" is an unknown label!");
++      return false;
++    }
++    return iter->second;
++  }
++
++#if LIBCWD_THREAD_SAFE
++  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
++  // I can cause I'm the maintainer of libcwd ;).
++  libcwd::_private_::pthread_lock_interface_ct cout_mutex(&mutex);
++  libcwd::_private_::lock_interface_base_ct* cout_mutex_ptr(&cout_mutex);
++#endif
++
++  /*! @brief Initialize debugging code from new threads.
++   *
++   * This function needs to be called at the start of each new thread,
++   * because a new thread starts in a completely reset state.
++   *
++   * The function turns on all debug channels that were turned on
++   * after reading the rcfile at the start of the application.
++   * Furthermore it initializes the debug ostream, its mutex and the
++   * margin of the default debug object (Dout).
++   */
++  void init_thread(void)
++  {
++    // Turn on all debug channels that are turned on as per rcfile configuration.
++    ForAllDebugChannels(
++        if (!debugChannel.is_on() && is_on_in_rcfile(debugChannel.get_label()))
++	  debugChannel.on();
++    );
++
++    // Turn on debug output.
++    Debug( libcw_do.on() );
++#if LIBCWD_THREAD_SAFE
++    Debug( libcw_do.set_ostream(&std::cout, cout_mutex_ptr) );
++#else
++    Debug( libcw_do.set_ostream(&std::cout) );
++#endif
++
++    static bool first_thread = true;
++    if (!first_thread)			// So far, the application has only one thread.  So don't add a thread id.
++    {
++      // Set the thread id in the margin.
++      char margin[22];
++      sprintf(margin, "%-20lu ", pthread_self());
++      Debug( libcw_do.margin().assign(margin, 21) );
++    }
++  }
++
++  /*! @brief Initialize debugging code from main.
++   *
++   * This function initializes the debug code.
++   */
++  void init(void)
++  {
++#if CWDEBUG_ALLOC && defined(USE_LIBCW)
++    // Tell the memory leak detector which parts of the code are
++    // expected to leak so that we won't get an alarm for those.
++    {
++      std::vector<std::pair<std::string, std::string> > hide_list;
++      hide_list.push_back(std::pair<std::string, std::string>("libdl.so.2", "_dlerror_run"));
++      hide_list.push_back(std::pair<std::string, std::string>("libstdc++.so.6", "__cxa_get_globals"));
++      // The following is actually necessary because of a bug in glibc
++      // (see http://sources.redhat.com/bugzilla/show_bug.cgi?id=311).
++      hide_list.push_back(std::pair<std::string, std::string>("libc.so.6", "dl_open_worker"));
++      memleak_filter().hide_functions_matching(hide_list);
++    }
++    {
++      std::vector<std::string> hide_list;
++      // Also because of http://sources.redhat.com/bugzilla/show_bug.cgi?id=311
++      hide_list.push_back(std::string("ld-linux.so.2"));
++      memleak_filter().hide_objectfiles_matching(hide_list);
++    }
++    memleak_filter().set_flags(libcwd::show_objectfile|libcwd::show_function);
++#endif
++
++    // The following call allocated the filebuf's of cin, cout, cerr, wcin, wcout and wcerr.
++    // Because this causes a memory leak being reported, make them invisible.
++    Debug(set_invisible_on());
++
++    // You want this, unless you mix streams output with C output.
++    // Read  http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#8 for an explanation.
++    //std::ios::sync_with_stdio(false);
++
++    // Cancel previous call to set_invisible_on.
++    Debug(set_invisible_off());
++
++    // This will warn you when you are using header files that do not belong to the
++    // shared libcwd object that you linked with.
++    Debug( check_configuration() );
++
++    Debug(
++      libcw_do.on();		// Show which rcfile we are reading!
++      ForAllDebugChannels(
++        while (debugChannel.is_on())
++	  debugChannel.off()	// Print as little as possible though.
++      );
++      read_rcfile();		// Put 'silent = on' in the rcfile to suppress most of the output here.
++      libcw_do.off()
++    );
++    save_dc_states();
++
++    init_thread();
++  }
++
++#if CWDEBUG_LOCATION
++  /*! @brief Return call location.
++   *
++   * @param return_addr The return address of the call.
++   */
++  std::string call_location(void const* return_addr)
++  {
++    libcwd::location_ct loc((char*)return_addr + libcwd::builtin_return_address_offset);
++    std::ostringstream convert;
++    convert << loc;
++    return convert.str();
++  }
++#endif
++
++} // namespace debug
++
++// These can be called from gdb.
++void cwdebug_start()
++{
++  debug::start_recording_backtraces();
++}
++
++void cwdebug_stop()
++{
++  debug::stop_recording_backtraces();
++}
++
++#endif // CWDEBUG
+diff --git a/indra/cwdebug/debug.h b/indra/cwdebug/debug.h
+new file mode 100644
+index 0000000..0fe75c5
+--- /dev/null
++++ b/indra/cwdebug/debug.h
+@@ -0,0 +1,176 @@
++// slviewer -- Second Life Viewer Source Code
++//
++//! @file debug.h
++//! @brief This file contains the declaration of debug related macros, objects and functions.
++//
++// Copyright (C) 2008, by
++// 
++// Carlo Wood, Run on IRC <carlo at alinoe.com>
++// RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
++// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
++// 
++// This program is free software: you can redistribute it and/or modify
++// it under the terms of the GNU General Public License as published by
++// the Free Software Foundation, either version 2 of the License, or
++// (at your option) any later version.
++// 
++// This program is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++// 
++// You should have received a copy of the GNU General Public License
++// along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++#ifndef DEBUG_H
++#define DEBUG_H
++
++#ifndef CWDEBUG
++
++#ifndef DOXYGEN         // No need to document this.  See http://libcwd.sourceforge.net/ for more info.
++
++#include <iostream>
++#include <cstdlib>      // std::exit, EXIT_FAILURE
++
++#define AllocTag1(p)
++#define AllocTag2(p, desc)
++#define AllocTag_dynamic_description(p, x)
++#define AllocTag(p, x)
++#define Debug(x)
++#define Dout(a, b)
++#define DoutEntering(a, b)
++#define DoutFatal(a, b) LibcwDoutFatal(::std, , a, b)
++#define ForAllDebugChannels(STATEMENT)
++#define ForAllDebugObjects(STATEMENT)
++#define LibcwDebug(dc_namespace, x)
++#define LibcwDout(a, b, c, d)
++#define LibcwDoutFatal(a, b, c, d) do { ::std::cerr << d << ::std::endl; ::std::exit(EXIT_FAILURE); } while (1)
++#define NEW(x) new x
++#define CWDEBUG_ALLOC 0
++#define CWDEBUG_MAGIC 0
++#define CWDEBUG_LOCATION 0
++#define CWDEBUG_LIBBFD 0
++#define CWDEBUG_DEBUG 0
++#define CWDEBUG_DEBUGOUTPUT 0
++#define CWDEBUG_DEBUGM 0
++#define CWDEBUG_DEBUGT 0
++#define CWDEBUG_MARKER 0
++
++#endif // !DOXYGEN
++
++#include <cassert>
++#ifdef DEBUG
++#define ASSERT(x) assert(x)
++#else
++#define ASSERT(x)
++#endif
++
++#else // CWDEBUG
++
++//! Assert \a x, if debugging is turned on.
++#define ASSERT(x) LIBCWD_ASSERT(x)
++
++#ifndef DEBUGCHANNELS
++//! @brief The namespace in which the \c dc namespace is declared.
++//
++// <A HREF="http://libcwd.sourceforge.net/">Libcwd</A> demands that this macro is defined
++// before <libcwd/debug.h> is included and must be the name of the namespace containing
++// the \c dc (Debug Channels) namespace.
++//
++// @sa debug::channels::dc
++
++#define DEBUGCHANNELS ::debug::channels
++#endif
++#include <libcwd/debug.h>
++
++//! Debug specific code.
++namespace debug {
++
++void init(void);                // Initialize debugging code, called once from main.
++void init_thread(void);         // Initialize debugging code, called once for each thread.
++
++//! @brief Debug Channels (dc) namespace.
++//
++// @sa debug::channels::dc
++namespace channels {	// namespace DEBUGCHANNELS
++
++//! The namespace containing the actual debug channels.
++namespace dc {
++using namespace libcwd::channels::dc;
++using libcwd::channel_ct;
++
++#ifndef DOXYGEN         // Doxygen bug causes a warning here.
++// Add the declaration of new debug channels here
++// and add their definition in a custom debug.cc file.
++extern channel_ct viewer;	// The normal logging output of the viewer (normally to stderr).
++
++#endif
++
++} // namespace dc
++} // namespace DEBUGCHANNELS
++
++#if CWDEBUG_LOCATION
++std::string call_location(void const* return_addr);
++#endif
++
++//! @brief Interface for marking scopes of invisible memory allocations.
++//
++// Creation of the object does nothing, you have to explicitly call
++// InvisibleAllocations::on.  Destruction of the object automatically
++// cancels any call to \c on of this object.  This makes it exception-
++// (stack unwinding) and recursive-safe.
++struct InvisibleAllocations {
++  int M_on;             //!< The number of times that InvisibleAllocations::on() was called.
++  //! Constructor.
++  InvisibleAllocations() : M_on(0) { }
++  //! Destructor.
++  ~InvisibleAllocations() { while (M_on > 0) off(); }
++  //! Set invisible allocations on. Can be called recursively.
++  void on(void) { libcwd::set_invisible_on(); ++M_on; }
++  //! Cancel one call to on().
++  void off(void) { assert(M_on > 0); --M_on; libcwd::set_invisible_off(); }
++};
++
++//! @brief Interface for marking scopes with indented debug output.
++//
++// Creation of the object increments the debug indentation. Destruction
++// of the object automatically decrements the indentation again.
++struct Indent {
++  int M_indent;                 //!< The extra number of spaces that were added to the indentation.
++  //! Construct an Indent object.
++  Indent(int indent) : M_indent(indent) { if (M_indent > 0) libcwd::libcw_do.inc_indent(M_indent); }
++  //! Destructor.
++  ~Indent() { if (M_indent > 0) libcwd::libcw_do.dec_indent(M_indent); }
++};
++
++} // namespace debug
++
++//! Debugging macro.
++//
++// Print "Entering " << \a data to channel \a cntrl and increment
++// debugging output indentation until the end of the current scope.
++#define DoutEntering(cntrl, data) \
++  int __slviewer_debug_indentation = 2;                                                                      \
++  {                                                                                                                     \
++    LIBCWD_TSD_DECLARATION;                                                                                             \
++    if (LIBCWD_DO_TSD_MEMBER_OFF(::libcwd::libcw_do) < 0)                                                               \
++    {                                                                                                                   \
++      ::libcwd::channel_set_bootstrap_st __libcwd_channel_set(LIBCWD_DO_TSD(::libcwd::libcw_do) LIBCWD_COMMA_TSD);      \
++      bool on;                                                                                                          \
++      {                                                                                                                 \
++        using namespace LIBCWD_DEBUGCHANNELS;                                                                           \
++        on = (__libcwd_channel_set|cntrl).on;                                                                           \
++      }                                                                                                                 \
++      if (on)                                                                                                           \
++        Dout(cntrl, "Entering " << data);                                                                               \
++      else                                                                                                              \
++        __slviewer_debug_indentation = 0;                                                                    \
++    }                                                                                                                   \
++  }                                                                                                                     \
++  debug::Indent __slviewer_debug_indent(__slviewer_debug_indentation);
++
++#endif // CWDEBUG
++
++#include "debug_ostream_operators.h"
++
++#endif // DEBUG_H
+diff --git a/indra/cwdebug/debug_ostream_operators.h b/indra/cwdebug/debug_ostream_operators.h
+new file mode 100644
+index 0000000..4459e9f
+--- /dev/null
++++ b/indra/cwdebug/debug_ostream_operators.h
+@@ -0,0 +1 @@
++// Empty so far...
+diff --git a/indra/cwdebug/sys.h b/indra/cwdebug/sys.h
+new file mode 100644
+index 0000000..c18df17
+--- /dev/null
++++ b/indra/cwdebug/sys.h
+@@ -0,0 +1,9 @@
++// The following is the libcwd related mandatory part.
++// It must be included before any system header file is included.
++#ifdef CWDEBUG
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++#include <libcwd/sys.h>
++#endif
++
+diff --git a/indra/linux_crash_logger/CMakeLists.txt b/indra/linux_crash_logger/CMakeLists.txt
+index 6f6754e..edc0a94 100644
+--- a/indra/linux_crash_logger/CMakeLists.txt
++++ b/indra/linux_crash_logger/CMakeLists.txt
+@@ -11,6 +11,7 @@ include(LLVFS)
+ include(LLXML)
+ include(Linking)
+ include(UI)
++include(Cwdebug)
+ 
+ include_directories(
+     ${LLCOMMON_INCLUDE_DIRS}
+@@ -52,6 +53,7 @@ target_link_libraries(linux-crash-logger
+     ${LLCOMMON_LIBRARIES}
+     ${UI_LIBRARIES}
+     ${DB_LIBRARIES}
++    ${CWDEBUG_LIBRARIES}
+     )
+ 
+ add_custom_command(
+diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
+index 5d50f3b..bdbaea9 100644
+--- a/indra/llcommon/llerror.cpp
++++ b/indra/llcommon/llerror.cpp
+@@ -162,7 +162,15 @@ namespace {
+ 					break;
+ 				}
+ 			}
++#ifdef CWDEBUG
++			// Include normal logging in libcwd's message processing.
++			// This takes care of prefixing with thread ID's, locking
++			// and allows us to (temporarily) turn off normal logging
++			// output.
++			Dout(dc::viewer, message);
++#else
+ 			fprintf(stderr, "%s\n", message.c_str());
++#endif
+ 			if (ANSI_YES == mUseANSI) colorANSI("0"); // reset
+ 		}
+ 	
+diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
+index 7c49f72..b30cd91 100644
+--- a/indra/newview/CMakeLists.txt
++++ b/indra/newview/CMakeLists.txt
+@@ -34,6 +34,7 @@ include(UI)
+ include(UnixInstall)
+ include(LLKDU)
+ include(ViewerMiscLibs)
++include(Cwdebug)
+ 
+ if (WINDOWS)
+     include(CopyWinLibs)
+@@ -1411,6 +1412,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
+     ${WINDOWS_LIBRARIES}
+     ${XMLRPCEPI_LIBRARIES}
+     ${ELFIO_LIBRARIES}
++    ${CWDEBUG_LIBRARIES}
+     )
+ 
+ build_version(viewer)
+diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
+index ad90b82..7a952c6 100644
+--- a/indra/newview/llappviewerlinux.cpp
++++ b/indra/newview/llappviewerlinux.cpp
+@@ -93,6 +93,9 @@ static void exceptionTerminateHandler()
+ 
+ int main( int argc, char **argv ) 
+ {
++	Debug(debug::init());
++	Debug(libcw_do.on());
++
+ 	LLMemType mt1(LLMemType::MTYPE_STARTUP);
+ 
+ #if LL_SOLARIS && defined(__sparc)
+-- 
+tg: (fd964dd..) topic/pandora/add_support_for_libcwd (depends on: master)
diff --git a/debian/patches/topic/pandora/aleric.diff b/debian/patches/topic/pandora/aleric.diff
new file mode 100644
index 0000000..6f68e76
--- /dev/null
+++ b/debian/patches/topic/pandora/aleric.diff
@@ -0,0 +1,539 @@
+From: Carlo Wood <carlo at alinoe.com>
+Subject: [PATCH] topic/pandora/aleric
+
+Aleric's play ground.
+
+Signed-off-by: Carlo Wood <carlo at alinoe.com>
+
+---
+ indra/newview/lltexturecache.cpp |  344 ++++++++++++++++++++++++++++++++++++--
+ indra/newview/llviewermenu.cpp   |    4 +-
+ 2 files changed, 331 insertions(+), 17 deletions(-)
+
+diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
+index ce35377..bdeb990 100644
+--- a/indra/newview/lltexturecache.cpp
++++ b/indra/newview/lltexturecache.cpp
+@@ -289,6 +289,10 @@ public:
+ 	virtual bool doWrite();
+ 
+ private:
++#ifdef READABLE_CACHE
++	void download_completed(std::string const& filename, bool debug);
++#endif
++
+ 	enum e_state
+ 	{
+ 		INIT = 0,
+@@ -317,7 +321,8 @@ bool LLTextureCacheRemoteWorker::doRead()
+ 		std::string filename = mCache->getLocalFileName(mID);	
+ 		local_filename = filename + ".j2c";
+ 		local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool());
+-		if (local_size == 0)
++		if (false && local_size == 0)	// Do not read .tga from disk  FIXME? This is a test because expect that the .tga are corrupted.
++		  				// Note: turns out this was not it, but I leave it commented out (false &&) anyway.
+ 		{
+ 			local_filename = filename + ".tga";
+ 			local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool());
+@@ -392,9 +397,9 @@ bool LLTextureCacheRemoteWorker::doRead()
+ 											 mReadData, mOffset, mDataSize);
+ 		if (bytes_read != mDataSize)
+ 		{
+-// 			llwarns << "Error reading file from local cache: " << local_filename
+-// 					<< " Bytes: " << mDataSize << " Offset: " << mOffset
+-// 					<< " / " << mDataSize << llendl;
++ 			llwarns << "Error reading file from local cache: " << local_filename
++ 					<< " Bytes: " << mDataSize << " Offset: " << mOffset
++ 					<< " / " << mDataSize << llendl;
+ 			mDataSize = 0;
+ 			delete[] mReadData;
+ 			mReadData = NULL;
+@@ -612,27 +617,254 @@ bool LLTextureCacheRemoteWorker::doRead()
+ 	return false;
+ }
+ 
++#include <openjpeg.h>
++#include <cstring>
++
++extern "C" {
++
++// Strip trailing newline.
++static std::string stripnl(char const* msg)
++{
++  std::string result(msg, std::strlen(msg) - 1);
++  return result;
++}
++
++static void error_callback(char const* msg, void* client_data)
++{
++  LLUUID const& ID = *reinterpret_cast<LLUUID*>(client_data);
++  llwarns << "LLTextureCacheRemoteWorker::download_completed: ERROR while decoding " << ID << ": " << stripnl(msg) << llendl;
++}
++
++static void warning_callback(char const* msg, void* client_data)
++{
++  LLUUID const& ID = *reinterpret_cast<LLUUID*>(client_data);
++  llwarns << "LLTextureCacheRemoteWorker::download_completed: while decoding " << ID << ": " << stripnl(msg) << llendl;
++}
++
++static void info_callback(char const* msg, void* client_data)
++{
++  LLUUID const& ID = *reinterpret_cast<LLUUID*>(client_data);
++  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: decoding " << ID << " : " << stripnl(msg) << llendl;
++}
++
++} // extern "C"
++
++// TGA header definition.
++#pragma pack(push,1) // Pack structure byte aligned
++struct tga_header
++{
++	U8   id_length;              // Image id field length.
++	U8   colour_map_type;        // Colour map type.
++	U8   image_type;             // Image type.
++	U16  colour_map_index;       // First entry index.
++	U16  colour_map_length;      // Colour map length.
++	U8   colour_map_entry_size;  // Colour map entry size.
++	U16  x_origin;               // x origin of image.
++	U16  y_origin;               // u origin of image.
++	U16  image_width;            // Image width.
++	U16  image_height;           // Image height.
++	U8   pixel_depth;            // Pixel depth.
++	U8   image_desc;             // Image descriptor.
++};
++
++void save_tga(std::string const& filename, LLUUID const& id, U8 const* write_data, S32 data_size, bool debug)
++{
++        // Set up event callbacks.
++        opj_event_mgr_t event_mgr;
++        std::memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
++        event_mgr.error_handler = error_callback;
++	event_mgr.warning_handler = warning_callback;
++	if (debug)
++	  event_mgr.info_handler = info_callback;
++
++	// Set up decoding parameters.
++	opj_dparameters_t parameters;
++	std::memset(&parameters, 0, sizeof(opj_dparameters_t));
++	// opj_dparameters_t::cp_layer : Set the maximum number of quality layers to decode. 
++	//                               If there are less quality layers than the specified number, all the quality layers are decoded.
++	//                               if != 0, then only the first "layer" layers are decoded;
++	//                               if == 0 or not used, all the quality layers are decoded.
++	// opj_dparameters::cp_reduce  : Set the number of highest resolution levels to be discarded.
++	//                               The image resolution is effectively divided by 2 to the power of the number of discarded levels.
++	//                               The reduce factor is limited by the smallest total number of decomposition levels among tiles.
++	//                               if != 0, then original dimension divided by 2^(reduce);
++	//                               if == 0 or not used, image is decoded to the full resolution 
++
++        // Get a decoder handle.
++	opj_dinfo_t* dinfo = opj_create_decompress(CODEC_J2K);
++	if (!dinfo)
++	{
++	  llwarns << "LLTextureCacheRemoteWorker::download_completed: failed to create a J2K decompression structure for " << id << llendl;
++	  return;
++	}
++
++	// Catch events using our callbacks and give a local context.
++	opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, const_cast<LLUUID*>(&id));
++
++	// Setup the decoder decoding parameters using user parameters.
++	opj_setup_decoder(dinfo, &parameters);
++
++	// Open a memory byte stream.
++	opj_cio_t* cio = opj_cio_open((opj_common_ptr)dinfo, const_cast<U8*>(write_data), data_size);
++	if (!cio)
++	  return;
++
++	// Decode the stream and fill the image structure.
++	opj_image_t* image= opj_decode(dinfo, cio);
++	if (!image)
++        {
++	  llwarns << "LLTextureCacheRemoteWorker::download_completed: failed to decode j2c image " << id << llendl;
++	  opj_destroy_decompress(dinfo);
++	  opj_cio_close(cio);
++          return;
++	}
++
++        // Close the byte stream.
++	opj_cio_close(cio);
++
++	// Create a TGA output image.
++	bool have_five_components = (image->numcomps == 5);
++	if (image->numcomps > 4)
++	  llwarns << "LLTextureCacheRemoteWorker::download_completed: Number of components of " << id << " is " << image->numcomps << "." << llendl;
++	llassert_always(image->numcomps <= 5);
++
++	for(;;)	// So we can use break in case of errors.
++	{
++
++	  for (int i = 0; i < image->numcomps - 1; ++i)
++	  {
++	      if ((image->comps[0].dx != image->comps[i + 1].dx) ||
++		  (image->comps[0].dy != image->comps[i + 1].dy) ||
++		  (image->comps[0].prec != image->comps[i + 1].prec))
++	      {
++		llwarns << "LLTextureCacheRemoteWorker::download_completed: failed to create a tga file with J2K image charateristics of " << id << llendl;
++		break;
++	      }
++	  }
++
++	  int const width = image->comps[0].w;
++	  int const height = image->comps[0].h;
++	  if (width <= 0 || height <= 0)
++	    break;
++	  U32 const alpha_channel = image->numcomps - 1;
++	  bool const write_alpha = (image->numcomps == 2) || (image->numcomps == 4) || (image->numcomps == 5);
++	  int const bpp = write_alpha ? 32 : 24;
++	  float const scale = 255.0f / (float)((1 << image->comps[0].prec) - 1);
++	  size_t filesize = sizeof(tga_header) + width * height * bpp / 8;
++	  U8* tga_buf = new U8 [filesize];
++
++	  tga_header tga;
++	  std::memset(&tga, 0, sizeof(tga_header));
++	  tga.pixel_depth = bpp;
++	  tga.image_width  = width;
++	  tga.image_height = height;
++	  tga.image_type = 2;	// Uncompressed.
++	  tga.image_desc = 8;	// 8 bits per component.
++	  tga.image_desc |= 32;	// Flip image.
++	  std::memcpy(tga_buf, &tga, sizeof(tga_header));
++
++	  U8* out = tga_buf + sizeof(tga_header);
++	  for (int y = 0; y < height; ++y)
++	  {
++	    U32 index = y * width;
++	    for (int x = 0; x < width; ++x, ++index)
++	    {
++	      float r, g, b, B = 0, a;
++	      
++	      if (have_five_components)
++		B = (float)(image->comps[3].data[index]);
++
++	      r = (float)(image->comps[0].data[index] /* + B */);
++	      if (image->numcomps > 2)
++	      {
++		g = (float)(image->comps[1].data[index] /* + B */);
++		b = (float)(image->comps[2].data[index] /* + B */);
++	      }
++	      else
++	      {
++		// Greyscale.
++		g = r;
++		b = r;
++	      }
++
++	      // TGA format writes BGR ...
++	      *out++ = (U8)(b * scale);
++	      *out++ = (U8)(g * scale);
++	      *out++ = (U8)(r * scale);
++	      if (write_alpha)
++	      {
++		a = (float)(image->comps[alpha_channel].data[index]);
++		*out++ = (U8)(a * scale);
++	      }
++	    }
++	  }
++
++	  LLAPRPool pool;
++          S32 bytes_written = ll_apr_file_write_ex(filename + ".tga", pool.getAPRPool() /* mCache->getFileAPRPool() */, tga_buf, 0, filesize);
++          if (bytes_written <= 0)
++	  {
++	    llwarns << "LLTextureCacheWorker: ll_apr_file_write_ex failed for " << id << llendl;
++	  }
++	  else if (debug)
++	    LL_DEBUGS("TextureCache") << "TEXTURE CACHE: wrote file " << (filename + ".tga") << LL_ENDL;
++
++	  // Free memory.
++	  delete [] tga_buf;
++
++          break;
++	}	// End of Single-pass loop.
++
++        // Free remaining structures.
++	opj_destroy_decompress(dinfo);
++	opj_image_destroy(image);
++}
++
++#ifdef READABLE_CACHE
++#undef USE_LFS_WRITE	// USE_LFS_WRITE was not tested.
++// Decode the J2K image in mWriteData and write the result as TGA to filename + ".tga".
++void LLTextureCacheRemoteWorker::download_completed(std::string const& filename, bool debug)
++{
++  save_tga(filename, mID, mWriteData, mDataSize, debug);
++}
++#endif
++
+ bool LLTextureCacheRemoteWorker::doWrite()
+ {
+ 	S32 idx = -1;
+ 
+ 	// No LOCAL state for write()
+-	
++
++        std::string filename = mCache->getTextureFileName(mID);
++	bool const debug = false; // !strcmp(filename.c_str() + filename.size() - 36, "6dc6d2c5-9449-b18b-6187-b586868e727c");
++
++	if (debug)
++	  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Entering LLTextureCacheRemoteWorker::doWrite() for " << mID << " with mDataSize = " << mDataSize << LL_ENDL;
++
+ 	if (mState == INIT)
+ 	{
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: mState == INIT" << LL_ENDL;
++
+ 		S32 cur_imagesize = 0;
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: mOffset == " << mOffset << LL_ENDL;
+ 		S32 offset = mOffset;
+ 		idx = mCache->getHeaderCacheEntry(mID, false, &cur_imagesize);
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: getHeaderCacheEntry returns idx = " << idx << " and cur_imagesize = " << cur_imagesize << LL_ENDL;
+ 		if (idx >= 0 && cur_imagesize > 0)
+ 		{
+ 			offset = TEXTURE_CACHE_ENTRY_SIZE; // don't re-write header
+ 		}
+ 		idx = mCache->getHeaderCacheEntry(mID, true, &mImageSize); // touch entry
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: getHeaderCacheEntry returns idx = " << idx << " and mImageSize = " << mImageSize << LL_ENDL;
+ 		if (idx >= 0)
+ 		{
+ 			if(cur_imagesize > 0 && mImageSize != cur_imagesize)
+ 			{
+-// 				llwarns << "Header cache entry size: " << cur_imagesize << " != mImageSize: " << mImageSize << llendl;
++			        if (debug)
++				  llwarns << "Header cache entry size: " << cur_imagesize << " != mImageSize: " << mImageSize << llendl;
+ 				offset = 0; // re-write header
+ 			}
+ 			mState = offset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
+@@ -640,12 +872,17 @@ bool LLTextureCacheRemoteWorker::doWrite()
+ 		else
+ 		{
+ 			mDataSize = -1; // failed
++			if (debug)
++			  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning true." << LL_ENDL;
+ 			return true;
+ 		}
+ 	}
+ 	
+ 	if (mState == HEADER)
+ 	{
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: mState == HEADER" << LL_ENDL;
++
+ #if USE_LFS_WRITE
+ 		if (mFileHandle == LLLFSThread::nullHandle())
+ 		{
+@@ -659,6 +896,9 @@ bool LLTextureCacheRemoteWorker::doWrite()
+ 			mFileHandle = LLLFSThread::sLocal->write(mCache->mHeaderDataFileName,
+ 													 mWriteData, offset, mBytesToRead,
+ 													 new WriteResponder(mCache, mRequestHandle));
++			if (debug)
++			  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning false." << LL_ENDL;
++
+ 			return false;
+ 		}
+ 		else
+@@ -671,10 +911,22 @@ bool LLTextureCacheRemoteWorker::doWrite()
+ // 							<< " incorrect number of bytes written to header: " << mBytesRead
+ // 							<< " != " << mBytesToRead << llendl;
+ 					mDataSize = -1; // failed
++
++					if (debug)
++					  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning true." << LL_ENDL;
++
+ 					return true;
+ 				}
+ 				if (mDataSize <=  mBytesToRead)
+ 				{
++#ifdef READABLE_CACHE
++					if (mImageSize <= TEXTURE_CACHE_ENTRY_SIZE)
++					  download_completed(filename, debug);
++#endif
++
++					if (debug)
++					  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning true." << LL_ENDL;
++
+ 					return true; // done
+ 				}
+ 				else
+@@ -685,26 +937,47 @@ bool LLTextureCacheRemoteWorker::doWrite()
+ 			}
+ 			else
+ 			{
++				if (debug)
++				  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning false." << LL_ENDL;
++
+ 				return false;
+ 			}
+ 		}
+ #else
+ 		llassert_always(idx >= 0);
+ 		llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
+-		S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
+-		S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
++		S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;	// File offset to start of jpeg 2000 data.
++		S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;		// Size of data till end of cache entry block.
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: calling ll_apr_file_write_ex with offset = " << offset << " and size = " << size << LL_ENDL;
+ 		S32 bytes_written = ll_apr_file_write_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(),
+ 												 mWriteData, offset, size);
+-
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: ll_apr_file_write_ex returned bytes_written = " << bytes_written << LL_ENDL;
+ 		if (bytes_written <= 0)
+ 		{
+-// 			llwarns << "LLTextureCacheWorker: missing entry: " << mID << llendl;
++		        if (debug)
++			  llwarns << "LLTextureCacheWorker: missing entry: " << mID << llendl;
+ 			mDataSize = -1; // failed
++
++			if (debug)
++			  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning true." << LL_ENDL;
++
+ 			return true;
+ 		}
+ 
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: mDataSize = " << mDataSize << LL_ENDL;
++
+ 		if (mDataSize <= size)
+ 		{
++			if (debug)
++			  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning true." << LL_ENDL;
++
++#ifdef READABLE_CACHE
++			if (mImageSize <= TEXTURE_CACHE_ENTRY_SIZE)
++			  download_completed(filename, debug);
++#endif
+ 			return true; // done
+ 		}
+ 		else
+@@ -716,6 +989,9 @@ bool LLTextureCacheRemoteWorker::doWrite()
+ 	
+ 	if (mState == BODY)
+ 	{
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: mState == BODY" << LL_ENDL;
++
+ #if USE_LFS_WRITE
+ 		if (mFileHandle == LLLFSThread::nullHandle())
+ 		{
+@@ -733,10 +1009,16 @@ bool LLTextureCacheRemoteWorker::doWrite()
+ 				mFileHandle = LLLFSThread::sLocal->write(filename,
+ 														 mWriteData + data_offset, file_offset, mBytesToRead,
+ 														 new WriteResponder(mCache, mRequestHandle));
++				if (debug)
++				  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning false." << LL_ENDL;
++
+ 				return false;
+ 			}
+ 			else
+ 			{
++				if (debug)
++				  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning true." << LL_ENDL;
++
+ 				mDataSize = 0; // no data written
+ 				return true; // done
+ 			}
+@@ -752,40 +1034,70 @@ bool LLTextureCacheRemoteWorker::doWrite()
+ // 							<< " != " << mBytesToRead << llendl;
+ 					mDataSize = -1; // failed
+ 				}
++#ifdef READABLE_CACHE
++				else if (TEXTURE_CACHE_ENTRY_SIZE + file_size == mImageSize)
++				  download_completed(filename, debug);
++#endif
++
++				if (debug)
++				  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning true." << LL_ENDL;
++
+ 				return true;
+ 			}
+ 			else
+ 			{
++				if (debug)
++				  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning false." << LL_ENDL;
++
+ 				return false;
+ 			}
+ 		}
+ #else
+-		S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+-		data_offset = llmax(data_offset, 0);
+-		S32 file_size = mDataSize - data_offset;
+-		S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
+-		file_offset = llmax(file_offset, 0);
++		S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;	// Offset into jpeg 2000 data (data already written to cache entry).
++		llassert_always(data_offset > 0);
++		//data_offset = llmax(data_offset, 0);
++		S32 file_size = mDataSize - data_offset;		// Total size of jpeg 2000 data in this file so far (including data to be written).
++		S32 const file_offset = 0; // mOffset - TEXTURE_CACHE_ENTRY_SIZE; // == -data_offset < 0
++		//file_offset = llmax(file_offset, 0);
+ 		S32 bytes_written = 0;
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: data_offset = " << data_offset << "; file_size = " << file_size <<
++		      "; file_offset = " << file_offset << LL_ENDL;
+ 		if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size))
+ 		{
+ 			std::string filename = mCache->getTextureFileName(mID);
++			if (debug)
++			  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: calling ll_apr_file_write_ex with file_offset " << file_offset <<
++			      " and file_size " << file_size << LL_ENDL;
+ 			bytes_written = ll_apr_file_write_ex(filename, mCache->getFileAPRPool(),
+ 												 mWriteData + data_offset,
+ 												 file_offset, file_size);
++			if (debug)
++			  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: ll_apr_file_write_ex returned bytes_written = " << bytes_written << LL_ENDL;
+ 			if (bytes_written <= 0)
+ 			{
+ 				mDataSize = -1; // failed
+ 			}
++#ifdef READABLE_CACHE
++			if (TEXTURE_CACHE_ENTRY_SIZE + file_size == mImageSize)
++			  download_completed(filename, debug);
++#endif
+ 		}
+ 		else
+ 		{
+ 			mDataSize = 0; // no data written
+ 		}
+ 
++		if (debug)
++		  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning true." << LL_ENDL;
++
+ 		return true;
+ #endif
+ 	}
+ 	
++	if (debug)
++	  LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Leaving LLTextureCacheRemoteWorker::doWrite(), returning false." << LL_ENDL;
++
+ 	return false;
+ }
+ 
+@@ -1203,7 +1515,7 @@ void LLTextureCache::purgeTextures(bool validate)
+ 	for (S32 idx=0; idx<num_entries; idx++)
+ 	{
+ 		const LLUUID& id = entries[idx].mID;
+- 		LL_DEBUGS("TextureCache") << "Entry: " << id << " Size: " << entries[idx].mSize << " Time: " << entries[idx].mTime << LL_ENDL;
++ 		// Too much noise // LL_DEBUGS("TextureCache") << "Entry: " << id << " Size: " << entries[idx].mSize << " Time: " << entries[idx].mTime << LL_ENDL;
+ 		std::map<LLUUID, S32>::iterator iter = entry_idx_map.find(id);
+ 		if (iter != entry_idx_map.end())
+ 		{
+diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
+index ea38545..3c593e0 100644
+--- a/indra/newview/llviewermenu.cpp
++++ b/indra/newview/llviewermenu.cpp
+@@ -6118,7 +6118,9 @@ void handle_selected_texture_info(void*)
+ 			S32 height = img->getHeight();
+ 			S32 width = img->getWidth();
+ 			S32 components = img->getComponents();
+-			msg = llformat("%dx%d %s on face ",
++			std::string idstr = image_id.getString();
++			msg = llformat("%s %dx%d %s on face ",
++			    					idstr.c_str(),
+ 								width,
+ 								height,
+ 								(components == 4 ? "alpha" : "opaque"));
+-- 
+tg: (424b1d3..) topic/pandora/aleric (depends on: upstream)
diff --git a/doc/contributions.txt b/doc/contributions.txt
index f5f50a1..3608b52 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -13,9 +13,10 @@ Able Whitman
 Adam Marker
 	VWR-2755
 Aimee Trescothick
-  VWR-3336
+    VWR-3336
 	VWR-3903
 	VWR-4083
+	VWR-7109
 	VWR-9255
 Alejandro Rosenthal
 	VWR-1184
@@ -327,6 +328,8 @@ Peekay Semyorka
 	VWR-19
 	VWR-49
 	VWR-79
+Peter Lameth
+  VWR-7331
 princess niven
 	VWR-5733
         CT-85
@@ -397,6 +400,8 @@ TBBle Kurosawa
 	VWR-1892
 Tharax Ferraris
 	VWR-605
+Thickbrick Sleaford
+	VWR-7109
 Thraxis Epsilon
 	SVC-371
 	VWR-383
diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp
index 467dacf..0896814 100644
--- a/indra/linux_crash_logger/llcrashloggerlinux.cpp
+++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp
@@ -124,11 +124,20 @@ void LLCrashLoggerLinux::gatherPlatformSpecificFiles()
 
 bool LLCrashLoggerLinux::mainLoop()
 {
-	if(!do_ask_dialog())
+	bool send_logs = true;
+	if(CRASH_BEHAVIOR_ASK == getCrashBehavior())
 	{
-		return true;
+		send_logs = do_ask_dialog();
+	}
+	else if(CRASH_BEHAVIOR_NEVER_SEND == getCrashBehavior())
+	{
+		send_logs = false;
+	}
+
+	if(send_logs)
+	{
+		sendCrashLogs();
 	}
-	sendCrashLogs();
 	return true;
 }
 
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 6cb7b87..11401f2 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -34,7 +34,7 @@
 
 const S32 LL_VERSION_MAJOR = 1;
 const S32 LL_VERSION_MINOR = 22;
-const S32 LL_VERSION_PATCH = 5;
+const S32 LL_VERSION_PATCH = 7;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Release";
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 57d0a95..dc389c1 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -952,213 +952,16 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
 
 	U32 old_face_mask = mVolumep->mFaceMask;
 
-	S32 face_bit = 0;
-	S32 cur_mask = 0;
-
-	// grab copies of the old faces so we can determine the TE mappings...
-	std::vector<LLProfile::Face> old_faces; // list of old faces for remapping texture entries
-	LLTextureEntry old_tes[9];
-
-	for (S32 face = 0; face < mVolumep->getNumFaces(); face++)
-	{
-		old_faces.push_back(mVolumep->getProfile().mFaces[face]);
-	}
-
-	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[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;
-
-	/*
-	std::string old_mask_string;
-	for (i = 0; i < 9; i++)
+	U32 new_face_mask = mVolumep->mFaceMask;	
+	if (old_face_mask != new_face_mask) 
 	{
-		if (old_face_mask & (1 << i))
-		{
-			old_mask_string.append("1");
-		}
-		else
-		{
-			old_mask_string.append("0");
-		}
-	}
-	std::string new_mask_string;
-	for (i = 0; i < 9; i++)
-	{
-		if (new_face_mask & (1 << i))
-		{
-			new_mask_string.append("1");
-		}
-		else
-		{
-			new_mask_string.append("0");
-		}
-	}
-
-	llinfos << "old mask: " << old_mask_string << llendl;
-	llinfos << "new mask: " << new_mask_string << llendl;
-	*/
-
-
-	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;
-	}
-
-
-	S32 face_mapping[9];
-	for (face_bit = 0; face_bit < 9; face_bit++)
-	{
-		face_mapping[face_bit] = face_bit;
-	}
-
-	// Generate the face-type mappings
-	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++)
-	{
-		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[face_mapping[face_bit]]);
-		}
-	}
+	}	
+	
 	return TRUE;
 }
 
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 8195eee..6a142a7 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -61,8 +61,6 @@ S32 LLImageGL::sCount					= 0;
 BOOL LLImageGL::sGlobalUseAnisotropic	= FALSE;
 F32 LLImageGL::sLastFrameTime			= 0.f;
 
-S32 LLImageGL::sMaxTextureSize          = 0 ;
-
 std::set<LLImageGL*> LLImageGL::sImageList;
 
 //**************************************************************************************
@@ -378,16 +376,6 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents)
 {
 	if (width != mWidth || height != mHeight || ncomponents != mComponents)
 	{
-		if(width > 1024 || height > 1024)
-		{
-			llwarns << "texture size is big: width: " << width << " height: " << height << llendl ;
-			if(!sMaxTextureSize)
-			{
-				glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&sMaxTextureSize) ;
-			}
-			llwarns << "max texture size is: " << sMaxTextureSize << llendl ;
-		}
-
 		// Check if dimensions are a power of two!
 		if (!checkSize(width,height))
 		{
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index e8c0a4a..1965495 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -212,8 +212,6 @@ public:
 	static U32 sBindCount;					// Tracks number of texture binds for current frame
 	static U32 sUniqueCount;				// Tracks number of unique texture binds for current frame
 	static BOOL sGlobalUseAnisotropic;
-
-	static S32 sMaxTextureSize ;
 #if DEBUG_MISS
 	BOOL mMissed; // Missed on last bind?
 	BOOL getMissed() const { return mMissed; };
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 688dcab..d3519da 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -2577,7 +2577,7 @@
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
-      <integer>0</integer>
+      <integer>1</integer>
     </map>
     <key>FloaterActiveSpeakersSortColumn</key>
     <map>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 63711ba..e1a0fe2 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3206,8 +3206,6 @@ void LLAppViewer::idle()
 		return;
     }
 
-	gViewerWindow->handlePerFrameHover();
-
 	///////////////////////////////////////
 	// Agent and camera movement
 	//
@@ -3485,12 +3483,12 @@ void LLAppViewer::sendLogoutRequest()
 		if (mLogoutMarkerFile)
 		{
 			llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl;
+    		apr_file_close(mLogoutMarkerFile);
 		}
 		else
 		{
 			llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl;
 		}
-		apr_file_close(mLogoutMarkerFile);
 	}
 }
 
@@ -3711,6 +3709,11 @@ void LLAppViewer::forceErrorSoftwareException()
     throw; 
 }
 
+void LLAppViewer::forceErrorDriverCrash()
+{
+	glDeleteTextures(1, NULL);
+}
+
 void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
 {
 	if(!mMainloopTimeout)
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 98612ef..d1f7b13 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -114,6 +114,7 @@ public:
     virtual void forceErrorBadMemoryAccess();
     virtual void forceErrorInifiniteLoop();
     virtual void forceErrorSoftwareException();
+    virtual void forceErrorDriverCrash();
 
 	// *NOTE: There are currently 3 settings files: 
 	// "Global", "PerAccount" and "CrashSettings"
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index c0ef1a9..b68cad6 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -82,7 +82,7 @@ const std::string LLAppViewerWin32::sWindowClass = "Second Life";
 LONG WINAPI viewer_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop)
 {
     // *NOTE:Mani - this code is stolen from LLApp, where its never actually used.
-	
+	//OSMessageBox("Attach Debugger Now", "Error", OSMB_OK);
     // Translate the signals/exceptions into cross-platform stuff
 	// Windows implementation
     _tprintf( _T("Entering Windows Exception Handler...\n") );
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 6a7ff16..16b282b 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -498,7 +498,7 @@ F32 LLDrawable::updateXform(BOOL undamped)
 	F32 dist_squared = 0.f;
 	F32 camdist2 = (mDistanceWRTCamera * mDistanceWRTCamera);
 
-	if (damped && mDistanceWRTCamera > 0.0f)
+	if (damped && isVisible())
 	{
 		F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f);
 		LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt);
@@ -522,11 +522,19 @@ F32 LLDrawable::updateXform(BOOL undamped)
 		{
 			// snap to final position
 			dist_squared = 0.0f;
+			if (!isRoot())
+			{ //child prim snapping to some position, needs a rebuild
+				gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
+			}
 		}
 	}
 
 	if ((mCurrentScale != target_scale) ||
-		(!isRoot() && (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED) || !mVObjp->getAngularVelocity().isExactlyZero()))
+		(!isRoot() && 
+		 (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED) || 
+		 !mVObjp->getAngularVelocity().isExactlyZero() ||
+		 target_pos != mXform.getPosition() ||
+		 target_rot != mXform.getRotation()))
 	{ //child prim moving or scale change requires immediate rebuild
 		gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
 	}
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 6221bc8..56f1e4d 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -592,7 +592,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params)
 		if( bump_code < LLStandardBumpmap::sStandardBumpmapCount )
 		{
 			bump = gStandardBumpmapList[bump_code].mImage;
-			gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize, 1, 1);
+			gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize);
 		}
 		break;
 	}
@@ -734,14 +734,13 @@ LLBumpImageList::~LLBumpImageList()
 
 
 // Note: Does nothing for entries in gStandardBumpmapList that are not actually standard bump images (e.g. none, brightness, and darkness)
-void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id,
-									  F32 pixel_area, F32 texel_area_ratio, F32 cos_center_angle)
+void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id, F32 virtual_size)
 {
 	bump &= TEM_BUMP_MASK;
 	LLViewerImage* bump_image = gStandardBumpmapList[bump].mImage;
 	if( bump_image )
 	{
-		bump_image->addTextureStats(pixel_area, texel_area_ratio, cos_center_angle);
+		bump_image->addTextureStats(virtual_size);
 	}
 }
 
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index 16d26ed..7e82f7f 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -131,8 +131,7 @@ public:
 
 	LLImageGL*	getBrightnessDarknessImage(LLViewerImage* src_image, U8 bump_code);
 //	LLImageGL*	getTestImage();
-	void		addTextureStats(U8 bump, const LLUUID& base_image_id,
-								F32 pixel_area, F32 texel_area_ratio, F32 cos_center_angle);
+	void		addTextureStats(U8 bump, const LLUUID& base_image_id, F32 virtual_size);
 
 	static void onSourceBrightnessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
 	static void onSourceDarknessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index 845ae97..995c4e4 100644
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -31,9 +31,9 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "lleventpoll.h"
 #include "llappviewer.h"
 #include "llagent.h"
-#include "lleventpoll.h"
 
 #include "llhttpclient.h"
 #include "llhttpstatuscodes.h"
@@ -41,6 +41,7 @@
 #include "lltimer.h"
 #include "llviewerregion.h"
 #include "message.h"
+#include "lltrans.h"
 
 namespace
 {
@@ -225,11 +226,15 @@ namespace
 			// They are essentially disconnected from the region even though some things may still work.
 			// Since things won't get better until they relog we force a disconnect now.
 
-			// *NOTE:Mani - This force disconnect was causing logouts even when disconnected
-			// from neighboring regions.
-			// *FIX:Mani We may want to re enable forceDisconnect for the agents main region.  
-			// *FIX:Mani If reimplemting Translate!!!!
-			// LLAppViewer::instance()->forceDisconnect("You have been disconnected from the region you were in.");
+			// *NOTE:Mani - The following condition check to see if this failing event poll
+			// is attached to the Agent's main region. If so we disconnect the viewer.
+			// Else... its a child region and we just leave the dead event poll stopped and 
+			// continue running.
+			if(gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSender)
+			{
+				llwarns << "Forcing disconnect due to stalled main region event poll."  << llendl;
+				LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection"));
+			}
 		}
 	}
 
diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp
index 7839729..b94efb9 100644
--- a/indra/newview/llfloaterinspect.cpp
+++ b/indra/newview/llfloaterinspect.cpp
@@ -213,6 +213,12 @@ void LLFloaterInspect::refresh()
 		LLSD row;
 		char time[MAX_STRING];
 		std::string owner_name, creator_name;
+
+		if (obj->mCreationDate == 0)
+		{	// Don't have valid information from the server, so skip this one
+			continue;
+		}
+
 		time_t timestamp = (time_t) (obj->mCreationDate/1000000);
 		LLStringUtil::copy(time, ctime(&timestamp), MAX_STRING);
 		time[24] = '\0';
diff --git a/indra/newview/llfloaterlagmeter.cpp b/indra/newview/llfloaterlagmeter.cpp
index 33647ec..2367c4d 100644
--- a/indra/newview/llfloaterlagmeter.cpp
+++ b/indra/newview/llfloaterlagmeter.cpp
@@ -183,7 +183,7 @@ void LLFloaterLagMeter::determineClient()
 		{
 			mClientCause->setText( getString("client_texture_loading_cause_msg", mStringArgs) );
 		}
-		else if(LLViewerImage::sBoundTextureMemory > LLViewerImage::sMaxBoundTextureMem)
+		else if((LLViewerImage::sBoundTextureMemory >> 20) > LLViewerImage::sMaxBoundTextureMem)
 		{
 			mClientCause->setText( getString("client_texture_memory_cause_msg", mStringArgs) );
 		}
diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp
index 7192c4f..ad9d776 100644
--- a/indra/newview/llfloatervoicedevicesettings.cpp
+++ b/indra/newview/llfloatervoicedevicesettings.cpp
@@ -85,14 +85,15 @@ BOOL LLPanelVoiceDeviceSettings::postBuild()
 void LLPanelVoiceDeviceSettings::draw()
 {
 	// let user know that volume indicator is not yet available
-	childSetVisible("wait_text", !gVoiceClient->inTuningMode());
+	bool is_in_tuning_mode = gVoiceClient->inTuningMode();
+	childSetVisible("wait_text", !is_in_tuning_mode);
 
 	LLPanel::draw();
 
 	F32 voice_power = gVoiceClient->tuningGetEnergy();
 	S32 discrete_power = 0;
 
-	if (!gVoiceClient->inTuningMode())
+	if (!is_in_tuning_mode)
 	{
 		discrete_power = 0;
 	}
@@ -101,7 +102,7 @@ void LLPanelVoiceDeviceSettings::draw()
 		discrete_power = llmin(4, llfloor((voice_power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 4.f));
 	}
 	
-	if (gVoiceClient->inTuningMode())
+	if (is_in_tuning_mode)
 	{
 		for(S32 power_bar_idx = 0; power_bar_idx < 5; power_bar_idx++)
 		{
@@ -136,7 +137,11 @@ void LLPanelVoiceDeviceSettings::apply()
 	}
 
 	// assume we are being destroyed by closing our embedding window
-	gSavedSettings.setF32("AudioLevelMic", mMicVolume);
+	LLSlider* volume_slider = getChild<LLSlider>("mic_volume_slider");
+	if(volume_slider)
+	{
+		gSavedSettings.setF32("AudioLevelMic", (F32)volume_slider->getValue().asReal());
+	}
 }
 
 void LLPanelVoiceDeviceSettings::cancel()
@@ -149,6 +154,13 @@ void LLPanelVoiceDeviceSettings::cancel()
 
 	if(mCtrlOutputDevices)
 		mCtrlOutputDevices->setSimple(mOutputDevice);
+
+	gSavedSettings.setF32("AudioLevelMic", mMicVolume);
+	LLSlider* volume_slider = getChild<LLSlider>("mic_volume_slider");
+	if(volume_slider)
+	{
+		volume_slider->setValue(mMicVolume);
+	}
 }
 
 void LLPanelVoiceDeviceSettings::refresh()
@@ -156,8 +168,8 @@ void LLPanelVoiceDeviceSettings::refresh()
 	//grab current volume
 	LLSlider* volume_slider = getChild<LLSlider>("mic_volume_slider");
 	// set mic volume tuning slider based on last mic volume setting
-	mMicVolume = (F32)volume_slider->getValue().asReal();
-	gVoiceClient->tuningSetMicVolume(mMicVolume);
+	F32 current_volume = (F32)volume_slider->getValue().asReal();
+	gVoiceClient->tuningSetMicVolume(current_volume);
 
 	// Fill in popup menus
 	mCtrlInputDevices = getChild<LLComboBox>("voice_input_device");
@@ -247,13 +259,19 @@ void LLPanelVoiceDeviceSettings::onClose(bool app_quitting)
 // static
 void LLPanelVoiceDeviceSettings::onCommitInputDevice(LLUICtrl* ctrl, void* user_data)
 {
-	gSavedSettings.setString("VoiceInputAudioDevice", ctrl->getValue().asString());
+	if(gVoiceClient)
+	{
+		gVoiceClient->setCaptureDevice(ctrl->getValue().asString());
+	}
 }
 
 // static
 void LLPanelVoiceDeviceSettings::onCommitOutputDevice(LLUICtrl* ctrl, void* user_data)
 {
-	gSavedSettings.setString("VoiceOutputAudioDevice", ctrl->getValue().asString());
+	if(gVoiceClient)
+	{
+		gVoiceClient->setRenderDevice(ctrl->getValue().asString());
+	}
 }
 
 //
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 815282c..3e35151 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -743,7 +743,7 @@ void LLFloaterWorldMap::updateLocation()
 void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S32 y_coord, S32 z_coord)
 {
 	LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromName(region_name);
-	z_coord = llclamp(z_coord, 0, 1000);
+	z_coord = llclamp(z_coord, 0, 4096);
 	if (sim_info)
 	{
 		LLVector3 local_pos;
diff --git a/indra/newview/llhudeffectpointat.cpp b/indra/newview/llhudeffectpointat.cpp
index d4fc57d..35131cc 100644
--- a/indra/newview/llhudeffectpointat.cpp
+++ b/indra/newview/llhudeffectpointat.cpp
@@ -441,8 +441,10 @@ bool LLHUDEffectPointAt::calcTargetPosition()
 
 	mTargetPos -= mSourceObject->getRenderPosition();
 
-	if (!mTargetPos.isFinite())
+	if (!llfinite(mTargetPos.lengthSquared()))
+	{
 		return false;
+	}
 
 	if (mSourceObject->isAvatar())
 	{
diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp
index 3658b8e..bfc88de 100644
--- a/indra/newview/llhudicon.cpp
+++ b/indra/newview/llhudicon.cpp
@@ -273,7 +273,7 @@ BOOL LLHUDIcon::lineSegmentIntersect(const LLVector3& start, const LLVector3& en
 	LLVector3 dir = end-start;
 
 	if (LLTriangleRayIntersect(upper_right, upper_left, lower_right, start, dir, NULL, NULL, &t, FALSE) ||
-		LLTriangleRayIntersect(lower_left, lower_right, upper_left, start, dir, NULL, NULL, &t, FALSE))
+		LLTriangleRayIntersect(upper_left, lower_left, lower_right, start, dir, NULL, NULL, &t, FALSE))
 	{
 		if (intersection)
 		{
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 0c2c1be..95b626b 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -106,7 +106,8 @@ void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType
 {
 	if(!filename.size())
 	{
-		llerrs << "Filename is Empty!" << llendl;
+		llwarns << "Filename is Empty!" << llendl;
+		return ;
 	}
 
 	LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r");		/*Flawfinder: ignore*/
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index d00a8c8..a9bf4b3 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -71,6 +71,24 @@
 #include "llviewerobject.h" 
 #include "llviewerobjectlist.h"
 
+namespace 
+{
+	// This method is used to return an object to mute given an object id.
+	// Its used by the LLMute constructor and LLMuteList::isMuted.
+	LLViewerObject* get_object_to_mute_from_id(LLUUID object_id)
+	{
+		LLViewerObject *objectp = gObjectList.findObject(object_id);
+		if ((objectp) && (!objectp->isAvatar()))
+		{
+			LLViewerObject *parentp = (LLViewerObject *)objectp->getParent();
+			if (parentp && parentp->getID() != gAgent.getID())
+			{
+				objectp = parentp;
+			}
+		}
+		return objectp;
+	}
+}
 
 // "emptymutelist"
 class LLDispatchEmptyMuteList : public LLDispatchHandler
@@ -105,15 +123,21 @@ LLMute::LLMute(const LLUUID& id, const std::string& name, EType type, U32 flags)
 	mFlags(flags)
 {
 	// muting is done by root objects only - try to find this objects root
-	LLViewerObject *objectp = gObjectList.findObject(mID);
-	if ((objectp) && (!objectp->isAvatar()))
+	LLViewerObject* mute_object = get_object_to_mute_from_id(id);
+	if(mute_object && mute_object->getID() != id)
 	{
-		LLViewerObject *parentp = (LLViewerObject *)objectp->getParent();
-		if (parentp)
+		mID = mute_object->getID();
+		LLNameValue* firstname = mute_object->getNVPair("FirstName");
+		LLNameValue* lastname = mute_object->getNVPair("LastName");
+		if (firstname && lastname)
 		{
-			mID = parentp->getID();
+			mName.assign( firstname->getString() );
+			mName.append(" ");
+			mName.append( lastname->getString() );
 		}
+		mType = mute_object->isAvatar() ? AGENT : OBJECT;
 	}
+
 }
 
 
@@ -662,19 +686,10 @@ BOOL LLMuteList::saveToFile(const std::string& filename)
 
 BOOL LLMuteList::isMuted(const LLUUID& id, const std::string& name, U32 flags) const
 {
-	LLUUID id_to_check = id;
-	
 	// for objects, check for muting on their parent prim
-	LLViewerObject *objectp = gObjectList.findObject(id);
-	if ((objectp) && (!objectp->isAvatar()))
-	{
-		LLViewerObject *parentp = (LLViewerObject *)objectp->getParent();
-		if (parentp)
-		{
-			id_to_check = parentp->getID();
-		}
-	}
-	
+	LLViewerObject* mute_object = get_object_to_mute_from_id(id);
+	LLUUID id_to_check  = (mute_object) ? mute_object->getID() : id;
+
 	// don't need name or type for lookup
 	LLMute mute(id_to_check);
 	mute_set_t::const_iterator mute_it = mMutes.find(mute);
diff --git a/indra/newview/llnotify.cpp b/indra/newview/llnotify.cpp
index d584120..9e837a6 100644
--- a/indra/newview/llnotify.cpp
+++ b/indra/newview/llnotify.cpp
@@ -971,10 +971,12 @@ LLNotifyBox * LLNotifyBoxView::getFirstNontipBox() const
 			iter++)
 	{
 		// hack! *TODO: Integrate llnotify and llgroupnotify
-		LLView* view = *iter;
-		if (view->getName() == "groupnotify")
+		if(isGroupNotifyBox(*iter))
+		{
 			continue;
-		LLNotifyBox* box = static_cast<LLNotifyBox*>(view);
+		}
+		
+		LLNotifyBox* box = (LLNotifyBox*)(*iter);
 		if(!box->isTip() && !box->isDead())
 		{
 			return box;
@@ -988,13 +990,23 @@ void LLNotifyBoxView::showOnly(LLView * view)
 	if(view) 
 	{
 		// assumes that the argument is actually a child
-		LLNotifyBox * shown = static_cast<LLNotifyBox*>(view);
+		LLNotifyBox * shown = dynamic_cast<LLNotifyBox*>(view);
+		if(!shown)
+		{
+			return ;
+		}
+
 		// make every other notification invisible
 		for(child_list_const_iter_t iter = getChildList()->begin();
 			iter != getChildList()->end();
 			iter++)
 		{
-			LLNotifyBox * box = static_cast<LLNotifyBox*>(*iter);
+			if(isGroupNotifyBox(*iter))
+			{
+				continue;
+			}
+
+			LLNotifyBox * box = (LLNotifyBox*)(*iter);
 			if(box != view && box->getVisible() && !box->isTip())
 			{
 				box->setVisible(FALSE);
@@ -1014,6 +1026,11 @@ void LLNotifyBoxView::purgeMessagesMatching(const Matcher& matcher)
 		iter != notification_queue.end();
 		iter++)
 	{
+		if(isGroupNotifyBox(*iter))
+		{
+			continue;
+		}
+
 		LLNotifyBox* notification = (LLNotifyBox*)*iter;
 		if(matcher.matches(notification->getNotifyCallback(), notification->getUserData()))
 		{
@@ -1021,3 +1038,14 @@ void LLNotifyBoxView::purgeMessagesMatching(const Matcher& matcher)
 		}
 	}
 }
+
+bool LLNotifyBoxView::isGroupNotifyBox(const LLView* view) const
+{
+	if (view->getName() == "groupnotify")
+	{
+		return TRUE ;
+	}
+
+	return FALSE ;
+}
+
diff --git a/indra/newview/llnotify.h b/indra/newview/llnotify.h
index 6c598e1..a653d19 100644
--- a/indra/newview/llnotify.h
+++ b/indra/newview/llnotify.h
@@ -179,6 +179,9 @@ public:
 	// Walks the list and removes any stacked messages for which the given matcher returns TRUE.
 	// Useful when muting people and things in order to clear out any similar previously queued messages.
 	void purgeMessagesMatching(const Matcher& matcher);
+
+private:
+	bool isGroupNotifyBox(const LLView* view) const ;
 };
 
 // This view contains the stack of notification windows.
diff --git a/indra/newview/llpaneldisplay.cpp b/indra/newview/llpaneldisplay.cpp
index 0d7caac..d510775 100644
--- a/indra/newview/llpaneldisplay.cpp
+++ b/indra/newview/llpaneldisplay.cpp
@@ -797,7 +797,15 @@ void LLPanelDisplay::applyResolution()
 		gSavedSettings.setF32("FullScreenAspectRatio", mAspectRatio);
 	}
 	
-	gViewerWindow->requestResolutionUpdate(!mCtrlWindowed->get(), mCtrlFullScreen->getCurrentIndex());
+	// Screen resolution
+	S32 num_resolutions;
+	LLWindow::LLWindowResolution* supported_resolutions = 
+		gViewerWindow->getWindow()->getSupportedResolutions(num_resolutions);
+	U32 resIndex = mCtrlFullScreen->getCurrentIndex();
+	gSavedSettings.setS32("FullScreenWidth", supported_resolutions[resIndex].mWidth);
+	gSavedSettings.setS32("FullScreenHeight", supported_resolutions[resIndex].mHeight);
+
+	gViewerWindow->requestResolutionUpdate(!mCtrlWindowed->get());
 
 	send_agent_update(TRUE);
 
diff --git a/indra/newview/llprefsim.cpp b/indra/newview/llprefsim.cpp
index 35a3b47..1af6e86 100644
--- a/indra/newview/llprefsim.cpp
+++ b/indra/newview/llprefsim.cpp
@@ -73,7 +73,9 @@ protected:
 
 
 LLPrefsIMImpl::LLPrefsIMImpl()
-	: LLPanel(std::string("IM Prefs Panel"))
+	: LLPanel(std::string("IM Prefs Panel")),
+	  mGotPersonalInfo(false),
+	  mOriginalIMViaEmail(false)
 {
 	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_im.xml");
 }
diff --git a/indra/newview/llprefsvoice.cpp b/indra/newview/llprefsvoice.cpp
index 568e1be..ae7c921 100644
--- a/indra/newview/llprefsvoice.cpp
+++ b/indra/newview/llprefsvoice.cpp
@@ -139,10 +139,21 @@ void LLPrefsVoice::apply()
 	gSavedSettings.setBOOL("VoiceCallsFriendsOnly", childGetValue("voice_call_friends_only_check"));
 	gSavedSettings.setBOOL("PushToTalkToggle", childGetValue("push_to_talk_toggle_check"));
 	gSavedSettings.setS32("VoiceEarLocation", childGetValue("ear_location"));
+	
+	LLFloaterVoiceDeviceSettings* voice_device_settings = LLFloaterVoiceDeviceSettings::getInstance();
+	if(voice_device_settings)
+	{
+		voice_device_settings->apply();
+	}
 }
 
 void LLPrefsVoice::cancel()
 {
+	LLFloaterVoiceDeviceSettings* voice_device_settings = LLFloaterVoiceDeviceSettings::getInstance();
+	if(voice_device_settings)
+	{
+		voice_device_settings->cancel();
+	}
 }
 
 void LLPrefsVoice::setKey(KEY key)
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index e891599..0f5a98a 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -4968,6 +4968,7 @@ LLSelectNode::LLSelectNode(LLViewerObject* object, BOOL glow)
 	mSitName = LLStringUtil::null;
 	mSilhouetteExists = FALSE;
 	mDuplicated = FALSE;
+	mCreationDate = 0;
 
 	saveColors();
 }
@@ -5005,6 +5006,7 @@ LLSelectNode::LLSelectNode(const LLSelectNode& nodep)
 	mFromTaskID = nodep.mFromTaskID;
 	mTouchName = nodep.mTouchName;
 	mSitName = nodep.mSitName;
+	mCreationDate = nodep.mCreationDate;
 
 	mSilhouetteVertices = nodep.mSilhouetteVertices;
 	mSilhouetteNormals = nodep.mSilhouetteNormals;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 11882b2..24046cc 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -562,6 +562,14 @@ bool LLTextureFetchWorker::doWork(S32 param)
 	{
 		mFetchTimer.reset();
 	}
+
+	if (mImagePriority <= 0.0f)
+	{
+		if (mState < WRITE_TO_CACHE)
+		{
+			return true; // cancel request
+		}
+	}
 	
 	if (mState == INIT)
 	{
@@ -708,7 +716,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			mFetcher->lockQueue();
 			mFetcher->removeFromNetworkQueue(this);
 			mFetcher->unlockQueue();
-			if (!mFormattedImage->getDataSize())
+			if (mFormattedImage.isNull() || !mFormattedImage->getDataSize())
 			{
 				// processSimulatorPackets() failed
 // 				llwarns << "processSimulatorPackets() failed to load buffer" << llendl;
@@ -1050,17 +1058,22 @@ void LLTextureFetchWorker::removeFromCache()
 
 bool LLTextureFetchWorker::processSimulatorPackets()
 {
+	if (mFormattedImage.isNull() || mRequestedSize < 0)
+	{
+		// not sure how we got here, but not a valid state, abort!
+		mFormattedImage = NULL;
+		return true;
+	}
+	
 	if (mLastPacket >= mFirstPacket)
 	{
-		llassert_always(mFormattedImage) ;
 		S32 buffer_size = mFormattedImage->getDataSize();
 		for (S32 i = mFirstPacket; i<=mLastPacket; i++)
 		{
-			llassert_always(mPackets[i]) ;
+			llassert_always(mPackets[i]);
 			buffer_size += mPackets[i]->mSize;
 		}
 		bool have_all_data = mLastPacket >= mTotalPackets-1;
-		llassert_always(mRequestedSize > 0);
 		if (buffer_size >= mRequestedSize || have_all_data)
 		{
 			/// We have enough (or all) data
@@ -1227,7 +1240,12 @@ void LLTextureFetchWorker::callbackDecoded(bool success)
 
 bool LLTextureFetchWorker::decodeImage()
 {
-	llassert_always(mImageWorker);
+	if(!mImageWorker)
+	{
+		//LLTextureFetchWorker is aborted, skip image decoding.
+		return true ;
+	}
+
 	bool res = true;
 	if (mRawImage.isNull())
 	{
@@ -1641,7 +1659,7 @@ void LLTextureFetch::sendRequestListToSimulators()
 				S32 packet = req->mLastPacket + 1;
 				gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
 				gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID);
-				gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mSimRequestedDiscard);
+				gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mDesiredDiscard);
 				gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mImagePriority);
 				gMessageSystem->addU32Fast(_PREHASH_Packet, packet);
 				gMessageSystem->addU8Fast(_PREHASH_Type, req->mType);
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 10a8950..14f62dd 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -162,7 +162,7 @@ void LLTextureBar::draw()
 	{
 		color = LLColor4::magenta;
 	}
-	else if (mImagep->getDecodePriority() == 0.0f)
+	else if (mImagep->getDecodePriority() <= 0.0f)
 	{
 		color = LLColor4::grey; color[VALPHA] = .7f;
 	}
@@ -612,6 +612,7 @@ void LLTextureView::draw()
 			{
 				pri = imagep->getDecodePriority();
 			}
+			pri = llclamp(pri, 0.0f, HIGH_PRIORITY-1.f);
 			
 			if (sDebugImages.find(imagep) != sDebugImages.end())
 			{
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index cd9afeb..210fca4 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -555,6 +555,7 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("VivoxDebugServerName")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
 	gSavedSettings.getControl("VoiceInputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
 	gSavedSettings.getControl("VoiceOutputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
+	gSavedSettings.getControl("AudioLevelMic")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
 	gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));	
 }
 
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index f552e63..a4438a5 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -253,6 +253,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		gViewerWindow->performPick();
 	}
 	
+	gViewerWindow->handlePerFrameHover();
 
 	LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates");
 	LLGLState::checkStates();
diff --git a/indra/newview/llviewerimage.cpp b/indra/newview/llviewerimage.cpp
index 926de7d..33210cf 100644
--- a/indra/newview/llviewerimage.cpp
+++ b/indra/newview/llviewerimage.cpp
@@ -238,7 +238,6 @@ void LLViewerImage::init(bool firstinit)
 	mTexelsPerImage = 64.f*64.f;
 	mMaxVirtualSize = 0.f;
 	mDiscardVirtualSize = 0.f;
-	mMaxCosAngle = -1.f;
 	mRequestedDiscardLevel = -1;
 	mRequestedDownloadPriority = 0.f;
 	mFullyLoaded = FALSE;
@@ -422,20 +421,12 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/)
 
 //============================================================================
 
-void LLViewerImage::addTextureStats(F32 pixel_area,
-								    F32 texel_area_ratio, // = 1.0
-								    F32 cos_center_angle) const // = 1.0
+void LLViewerImage::addTextureStats(F32 virtual_size) const // = 1.0
 {
-	F32 virtual_size = pixel_area / texel_area_ratio;
 	if (virtual_size > mMaxVirtualSize)
 	{
 		mMaxVirtualSize = virtual_size;
 	}
-	cos_center_angle = llclamp(cos_center_angle, -1.f, 1.f);
-	if (cos_center_angle > mMaxCosAngle)
-	{
-		mMaxCosAngle = cos_center_angle;
-	}
 }
 
 void LLViewerImage::resetTextureStats(BOOL zero)
@@ -443,12 +434,10 @@ void LLViewerImage::resetTextureStats(BOOL zero)
 	if (zero)
 	{
 		mMaxVirtualSize = 0.0f;
-		mMaxCosAngle = -1.0f;
 	}
-	else if (getBoostLevel() != LLViewerImage::BOOST_SCULPTED) //don't decay sculpted prim textures
+	else
 	{
 		mMaxVirtualSize -= mMaxVirtualSize * .10f; // decay by 5%/update
-		mMaxCosAngle = -1.0f;
 	}
 }
 
@@ -548,7 +537,7 @@ void LLViewerImage::processTextureStats()
 		if ((sDesiredDiscardBias > 0.0f) &&
 			(current_discard >= 0 && mDesiredDiscardLevel >= current_discard))
 		{
-			if ( sBoundTextureMemory > sMaxBoundTextureMem*texmem_middle_bound_scale)
+			if ( (sBoundTextureMemory >> 20) > sMaxBoundTextureMem*texmem_middle_bound_scale)
 			{
 				// Limit the amount of GL memory bound each frame
 				if (mDesiredDiscardLevel > current_discard)
@@ -556,7 +545,7 @@ void LLViewerImage::processTextureStats()
 					increase_discard = TRUE;
 				}
 			}
-			if ( sTotalTextureMemory > sMaxTotalTextureMem*texmem_middle_bound_scale)
+			if ( (sTotalTextureMemory >> 20) > sMaxTotalTextureMem*texmem_middle_bound_scale)
 			{
 				// Only allow GL to have 2x the video card memory
 				if (!getBoundRecently())
@@ -598,7 +587,7 @@ F32 LLViewerImage::calcDecodePriority()
 	F32 priority;
 	S32 cur_discard = getDiscardLevel();
 	bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel));
-	F32 pixel_priority = fsqrtf(mMaxVirtualSize) * (1.f + mMaxCosAngle);
+	F32 pixel_priority = fsqrtf(mMaxVirtualSize);
 	const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame
 	mDecodeFrame++;
 	if (pixel_priority > 0.f)
@@ -638,17 +627,12 @@ F32 LLViewerImage::calcDecodePriority()
 			return mDecodePriority;
 		}
 	}
-	else if ((mBoostLevel == LLViewerImage::BOOST_SCULPTED) && !have_all_data)
-	{
-		// Sculpted images are small, treat them like they always have no data.
-		priority = 900000.f;
-	}
 	else if (cur_discard < 0)
 	{
-		// We don't have any data yet, so we don't know the size of the image, treat as 1024x1024
+		// We don't have any data yet, so we don't know the size of the image, treat as 32x32
 //		priority = 900000.f;
 		static const F64 log_2 = log(2.0);
-		F32 desired = (F32)(log(1024.0/pixel_priority) / log_2);
+		F32 desired = (F32)(log(32.0/pixel_priority) / log_2);
 		S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired + 1;
 		ddiscard = llclamp(ddiscard, 1, 9);
 		priority = ddiscard*100000.f;
@@ -702,14 +686,7 @@ F32 LLViewerImage::maxDecodePriority()
 void LLViewerImage::setDecodePriority(F32 priority)
 {
 	llassert(!mInImageList);
-	if (priority < 0.0f)
-	{
-		mDecodePriority = calcDecodePriority();
-	}
-	else
-	{
-		mDecodePriority = priority;
-	}
+	mDecodePriority = priority;
 }
 
 void LLViewerImage::setBoostLevel(S32 level)
@@ -766,6 +743,7 @@ bool LLViewerImage::updateFetch()
 	S32 current_discard = getDiscardLevel();
 	S32 desired_discard = getDesiredDiscardLevel();
 	F32 decode_priority = getDecodePriority();
+	decode_priority = llmax(decode_priority, 0.0f);
 	
 	if (mIsFetching)
 	{
@@ -783,7 +761,7 @@ bool LLViewerImage::updateFetch()
 		else
 		{
 			mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
-													   mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
+																		mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
 		}
 		
 		// We may have data ready regardless of whether or not we are finished (e.g. waiting on write)
@@ -817,7 +795,7 @@ bool LLViewerImage::updateFetch()
 		
 		if (!mIsFetching)
 		{
-			if (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL)
+			if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL))
 			{
 				// We finished but received no data
 				if (current_discard < 0)
@@ -840,9 +818,9 @@ bool LLViewerImage::updateFetch()
 				destroyRawImage();
 			}
 		}
-		else if (mDecodePriority >= 0.f)
+		else
 		{
-			LLAppViewer::getTextureFetch()->updateRequestPriority(mID, mDecodePriority);
+			LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority);
 		}
 	}
 
diff --git a/indra/newview/llviewerimage.h b/indra/newview/llviewerimage.h
index 82da8d2..c735cb0 100644
--- a/indra/newview/llviewerimage.h
+++ b/indra/newview/llviewerimage.h
@@ -187,27 +187,7 @@ public:
 
 	// New methods for determining image quality/priority
 	// texel_area_ratio is ("scaled" texel area)/(original texel area), approximately.
-	void addTextureStats(F32 pixel_area) const
-	{
-		mMaxCosAngle = 1.0f;
-		if (pixel_area > mMaxVirtualSize)
-		{
-			mMaxVirtualSize = pixel_area;
-		}
-	}
-	void addTextureStats(F32 pixel_area,
-						 F32 texel_area_ratio) const
-	{
-		mMaxCosAngle = 1.0f;
-		F32 virtual_size = pixel_area / texel_area_ratio;
-		if (virtual_size > mMaxVirtualSize)
-		{
-			mMaxVirtualSize = virtual_size;
-		}
-	}
-	void addTextureStats(F32 pixel_area,
-						 F32 texel_area_ratio,
-						 F32 cos_center_angle) const;
+	void addTextureStats(F32 virtual_size) const;
 	void resetTextureStats(BOOL zero = FALSE);
 
 	// Process image stats to determine priority/quality requirements.
@@ -304,7 +284,6 @@ public:
 
 	// Data used for calculating required image priority/quality level/decimation
 	mutable F32 mMaxVirtualSize;	// The largest virtual size of the image, in pixels - how much data to we need?
-	mutable F32 mMaxCosAngle;		// The largest cos of the angle between camera X vector and the object
 
 	F32 mTexelsPerImage;			// Texels per image.
 	F32 mDiscardVirtualSize;		// Virtual size used to calculate desired discard
diff --git a/indra/newview/llviewerimagelist.cpp b/indra/newview/llviewerimagelist.cpp
index 5dbfab0..e48f6ae 100644
--- a/indra/newview/llviewerimagelist.cpp
+++ b/indra/newview/llviewerimagelist.cpp
@@ -500,10 +500,10 @@ void LLViewerImageList::updateImages(F32 max_time)
 {
 	sNumImagesStat.addValue(sNumImages);
 	sNumRawImagesStat.addValue(LLImageRaw::sRawImageCount);
-	sGLTexMemStat.addValue(LLImageGL::sGlobalTextureMemory/(1024.f*1024.f));
-	sGLBoundMemStat.addValue(LLImageGL::sBoundTextureMemory/(1024.f*1024.f));
-	sRawMemStat.addValue(LLImageRaw::sGlobalRawMemory/(1024.f*1024.f));
-	sFormattedMemStat.addValue(LLImageFormatted::sGlobalFormattedMemory/(1024.f*1024.f));
+	sGLTexMemStat.addValue((F32)(LLImageGL::sGlobalTextureMemory >> 20));
+	sGLBoundMemStat.addValue((F32)(LLImageGL::sBoundTextureMemory >> 20));
+	sRawMemStat.addValue((F32)(LLImageRaw::sGlobalRawMemory >> 20));
+	sFormattedMemStat.addValue((F32)(LLImageFormatted::sGlobalFormattedMemory >> 20));
 	
 	updateImagesDecodePriorities();
 	max_time -= updateImagesFetchTextures(max_time);
@@ -588,9 +588,12 @@ void LLViewerImageList::updateImagesDecodePriorities()
 			
 			imagep->processTextureStats();
 			F32 old_priority = imagep->getDecodePriority();
+			F32 old_priority_test = llmax(old_priority, 0.0f);
 			F32 decode_priority = imagep->calcDecodePriority();
+			F32 decode_priority_test = llmax(decode_priority, 0.0f);
 			// Ignore < 20% difference
-			if ((decode_priority < old_priority * .8f || decode_priority > old_priority * 1.25f))
+			if ((decode_priority_test < old_priority_test * .8f) ||
+				(decode_priority_test > old_priority_test * 1.25f))
 			{
 				removeImageFromList(imagep);
 				imagep->setDecodePriority(decode_priority);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 2d64712..023c758 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -403,6 +403,7 @@ void force_error_llerror(void *);
 void force_error_bad_memory_access(void *);
 void force_error_infinite_loop(void *);
 void force_error_software_exception(void *);
+void force_error_driver_crash(void *);
 
 void handle_stopall(void*);
 //void handle_hinge(void*);
@@ -936,6 +937,7 @@ void init_client_menu(LLMenuGL* menu)
 		sub->append(new LLMenuItemCallGL("Force LLError And Crash", &force_error_llerror));
         sub->append(new LLMenuItemCallGL("Force Bad Memory Access", &force_error_bad_memory_access));
 		sub->append(new LLMenuItemCallGL("Force Infinite Loop", &force_error_infinite_loop));
+		sub->append(new LLMenuItemCallGL("Force Driver Crash", &force_error_driver_crash));
 		sub->append(new LLMenuItemCallGL("Force Disconnect Viewer", &handle_disconnect_viewer));
 		// *NOTE:Mani this isn't handled yet... sub->append(new LLMenuItemCallGL("Force Software Exception", &force_error_unhandled_exception)); 
 		sub->createJumpKeys();
@@ -6921,6 +6923,11 @@ void force_error_software_exception(void *)
     LLAppViewer::instance()->forceErrorSoftwareException();
 }
 
+void force_error_driver_crash(void *)
+{
+    LLAppViewer::instance()->forceErrorDriverCrash();
+}
+
 class LLToolsUseSelectionForGrid : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp
index 529ec4d..c303fc5 100644
--- a/indra/newview/llviewerpartsim.cpp
+++ b/indra/newview/llviewerpartsim.cpp
@@ -53,6 +53,7 @@ const F32 PART_SIM_BOX_RAD = 0.5f*F_SQRT3*PART_SIM_BOX_SIDE;
 //static
 S32 LLViewerPartSim::sMaxParticleCount = 0;
 S32 LLViewerPartSim::sParticleCount = 0;
+S32 LLViewerPartSim::sParticleCount2 = 0;
 // This controls how greedy individual particle burst sources are allowed to be, and adapts according to how near the particle-count limit we are.
 F32 LLViewerPartSim::sParticleAdaptiveRate = 0.0625f;
 F32 LLViewerPartSim::sParticleBurstRate = 0.5f;
@@ -84,12 +85,16 @@ LLViewerPart::LLViewerPart() :
 {
 	LLMemType mt(LLMemType::MTYPE_PARTICLES);
 	mPartSourcep = NULL;
+
+	++LLViewerPartSim::sParticleCount2 ;
 }
 
 LLViewerPart::~LLViewerPart()
 {
 	LLMemType mt(LLMemType::MTYPE_PARTICLES);
 	mPartSourcep = NULL;
+
+	--LLViewerPartSim::sParticleCount2 ;
 }
 
 void LLViewerPart::init(LLPointer<LLViewerPartSource> sourcep, LLViewerImage *imagep, LLVPCallback cb)
@@ -263,6 +268,8 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)
 	
 	LLVector3 gravity(0.f, 0.f, GRAVITY);
 
+	LLViewerPartSim::checkParticleCount(mParticles.size());
+
 	LLViewerRegion *regionp = getRegion();
 	S32 end = (S32) mParticles.size();
 	for (S32 i = 0 ; i < (S32)mParticles.size();)
@@ -416,6 +423,8 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)
 		gObjectList.killObject(mVOPartGroupp);
 		mVOPartGroupp = NULL;
 	}
+
+	LLViewerPartSim::checkParticleCount() ;
 }
 
 
@@ -451,6 +460,19 @@ void LLViewerPartGroup::removeParticlesByID(const U32 source_id)
 //
 //
 
+//static
+void LLViewerPartSim::checkParticleCount(U32 size)
+{
+	if(LLViewerPartSim::sParticleCount2 != LLViewerPartSim::sParticleCount)
+	{
+		llerrs << "sParticleCount: " << LLViewerPartSim::sParticleCount << " ; sParticleCount2: " << LLViewerPartSim::sParticleCount2 << llendl ;
+	}
+
+	if(size > (U32)LLViewerPartSim::sParticleCount2)
+	{
+		llerrs << "curren particle size: " << LLViewerPartSim::sParticleCount2 << " array size: " << size << llendl ;
+	}
+}
 
 LLViewerPartSim::LLViewerPartSim()
 {
@@ -509,6 +531,12 @@ void LLViewerPartSim::addPart(LLViewerPart* part)
 	{
 		put(part);
 	}
+	else
+	{
+		//delete the particle if can not add it in
+		delete part ;
+		part = NULL ;
+	}
 }
 
 
@@ -544,7 +572,7 @@ LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart* part)
 		if(!return_group)
 		{
 			llassert_always(part->mPosAgent.isFinite());
-	LLViewerPartGroup *groupp = createViewerPartGroup(part->mPosAgent, desired_size, part->mFlags & LLPartData::LL_PART_HUD);
+			LLViewerPartGroup *groupp = createViewerPartGroup(part->mPosAgent, desired_size, part->mFlags & LLPartData::LL_PART_HUD);
 			groupp->mUniformParticles = (part->mScale.mV[0] == part->mScale.mV[1] && 
 									!(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK));
 			if (!groupp->addPart(part))
diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h
index 2524d6b..81394e6 100644
--- a/indra/newview/llviewerpartsim.h
+++ b/indra/newview/llviewerpartsim.h
@@ -197,6 +197,12 @@ protected:
 	static const F32 PART_THROTTLE_RESCALE;
 	static const F32 PART_ADAPT_RATE_MULT;
 	static const F32 PART_ADAPT_RATE_MULT_RECIP;
+
+//debug use only
+public:
+	static S32 sParticleCount2;
+
+	static void checkParticleCount(U32 size = 0) ;
 };
 
 #endif // LL_LLVIEWERPARTSIM_H
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 111fc14..0b4c0f3 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -40,6 +40,7 @@
 #include "llappviewer.h"
 
 #include "pipeline.h" 
+#include "lltexturefetch.h" 
 #include "llviewerobjectlist.h" 
 #include "llviewerimagelist.h" 
 #include "lltexlayer.h"
@@ -562,15 +563,12 @@ void update_statistics(U32 frame_count)
 	LLViewerStats::getInstance()->mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f);
 	gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
 
-	static S32 tex_bits_idle_count = 0;
-	if (LLViewerImageList::sTextureBits == 0)
+	if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
 	{
-		if (++tex_bits_idle_count >= 30)
-			gDebugTimers[0].pause();
+		gDebugTimers[0].pause();
 	}
 	else
 	{
-		tex_bits_idle_count = 0;
 		gDebugTimers[0].unpause();
 	}
 	
@@ -761,12 +759,15 @@ void send_stats()
 // 	misc["int_2"] = LLFloaterDirectory::sNewSearchCount; // Steve: 1.18.6
 // 	misc["int_1"] = LLSD::Integer(gSavedSettings.getU32("RenderQualityPerformance")); // Steve: 1.21
 // 	misc["int_2"] = LLSD::Integer(gFrameStalls); // Steve: 1.21
-	F32 unbaked_time = LLVOAvatar::sUnbakedTime / gFrameTime;
-	misc["int_1"] = LLSD::Integer(unbaked_time * 1000.f); // Steve: 1.22
-	F32 grey_time = LLVOAvatar::sGreyTime / gFrameTime;
-	misc["int_2"] = LLSD::Integer(grey_time * 1000.f); // Steve: 1.22
+
+	F32 unbaked_time = LLVOAvatar::sUnbakedTime * 1000.f / gFrameTimeSeconds;
+	misc["int_1"] = LLSD::Integer(unbaked_time); // Steve: 1.22
+	F32 grey_time = LLVOAvatar::sGreyTime * 1000.f / gFrameTimeSeconds;
+	misc["int_2"] = LLSD::Integer(grey_time); // Steve: 1.22
+
+	llinfos << "Misc Stats: int_1: " << misc["int_1"] << " int_2: " << misc["int_2"] << llendl;
+	llinfos << "Misc Stats: string_1: " << misc["string_1"] << " string_2: " << misc["string_2"] << llendl;
 	
 	LLViewerStats::getInstance()->addToMessage(body);
-
 	LLHTTPClient::post(url, body, new ViewerStatsResponder());
 }
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 2f49b67..1a9a208 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -918,7 +918,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK
 
 	// *HACK: this should be rolled into the composite tool logic, not
 	// hardcoded at the top level.
-	if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode())
+	if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance())
 	{
 		// If the current tool didn't process the click, we should show
 		// the pie menu.  This can be done by passing the event to the pie
@@ -2098,12 +2098,7 @@ void LLViewerWindow::reshape(S32 width, S32 height)
 		gSavedSettings.setBOOL("FullScreen", mWantFullscreen);
 
 		// store new settings for the mode we are in, regardless
-		if (mWindow->getFullscreen())
-		{
-			gSavedSettings.setS32("FullScreenWidth", width);
-			gSavedSettings.setS32("FullScreenHeight", height);
-		}
-		else
+		if (!mWindow->getFullscreen())
 		{
 			// Only save size if not maximized
 			BOOL maximized = mWindow->getMaximized();
@@ -3586,6 +3581,16 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
 	// world coordinates of mouse
 	LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
 	LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
+	
+	//get near clip plane
+	LLVector3 n = LLViewerCamera::getInstance()->getAtAxis();
+	LLVector3 p = mouse_point_global + n * LLViewerCamera::getInstance()->getNear();
+
+	//project mouse point onto plane
+	LLVector3 pos;
+	line_plane(mouse_point_global, mouse_direction_global, p, n, pos);
+	mouse_point_global = pos;
+
 	LLVector3 mouse_world_start = mouse_point_global;
 	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
 
@@ -4695,79 +4700,13 @@ void LLViewerWindow::getTargetWindow(BOOL& fullscreen, S32& width, S32& height)
 	}
 }
 
-bool LLViewerWindow::updateResolution()
-{
-	if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio"))
-	{
-		getWindow()->setNativeAspectRatio(0.f);
-	}
-	else
-	{
-		getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio"));
-	}
-	
-	reshape(getWindowDisplayWidth(), getWindowDisplayHeight());
-	
-	// Screen resolution
-	S32 num_resolutions;
-	LLWindow::LLWindowResolution* supported_resolutions = getWindow()->getSupportedResolutions(num_resolutions);
-	
-	// check if resolution has changed
-	BOOL targetFullscreen;
-	S32 targetWidth;
-	S32 targetHeight;
-	
-	getTargetWindow(targetFullscreen, targetWidth, targetHeight);
-	
-	if ((mIsFullscreenChecked != (bool) targetFullscreen) ||
-		(mIsFullscreenChecked &&
-		 (supported_resolutions[mCurrResolutionIndex].mWidth != targetWidth ||
-		  supported_resolutions[mCurrResolutionIndex].mHeight != targetHeight)
-		 ))
-	{
-		// change fullscreen resolution or switch in/out of windowed mode
-		BOOL result;
-		
-		BOOL logged_in = (LLStartUp::getStartupState() >= STATE_STARTED);
-		if (mIsFullscreenChecked)
-		{
-			result = changeDisplaySettings(TRUE, 
-											LLCoordScreen(	supported_resolutions[mCurrResolutionIndex].mWidth, 
-															supported_resolutions[mCurrResolutionIndex].mHeight), 
-											gSavedSettings.getBOOL("DisableVerticalSync"),
-											logged_in);
-		}
-		else
-		{
-			result = changeDisplaySettings(FALSE, 
-											LLCoordScreen(gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight")), 
-											TRUE,
-											logged_in);
-		}
-		if (!result)
-		{
-			
-			// GL is non-existent at this point, so we can't continue.
-			llerrs << "LLPanelDisplay::apply() failed" << llendl;
-		}
-	}
-	
-	// force aspect ratio
-	if (mIsFullscreenChecked)
-	{
-		LLViewerCamera::getInstance()->setAspect( getDisplayAspectRatio() );
-	}
-	return true;
-}
-
-void LLViewerWindow::requestResolutionUpdate(bool fullscreen_checked, U32 resolution_index)
+void LLViewerWindow::requestResolutionUpdate(bool fullscreen_checked)
 {
 	mResDirty = true;
+	mWantFullscreen = fullscreen_checked;
 	mIsFullscreenChecked = fullscreen_checked;
-	mCurrResolutionIndex = resolution_index;
 }
 
-
 BOOL LLViewerWindow::checkSettings()
 {
 	if (mStatesDirty)
@@ -4780,42 +4719,70 @@ BOOL LLViewerWindow::checkSettings()
 	// We want to update the resolution AFTER the states getting refreshed not before.
 	if (mResDirty)
 	{
-		updateResolution();
+		if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio"))
+		{
+			getWindow()->setNativeAspectRatio(0.f);
+		}
+		else
+		{
+			getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio"));
+		}
+		
+		reshape(getWindowDisplayWidth(), getWindowDisplayHeight());
+
+		// force aspect ratio
+		if (mIsFullscreenChecked)
+		{
+			LLViewerCamera::getInstance()->setAspect( getDisplayAspectRatio() );
+		}
+
 		mResDirty = false;
 		// This will force a state update the next frame.
 		mStatesDirty = true;
 	}
 		
 	BOOL is_fullscreen = mWindow->getFullscreen();
-	if (is_fullscreen && !mWantFullscreen)
-	{
-		changeDisplaySettings(FALSE, 
-							  LLCoordScreen(gSavedSettings.getS32("WindowWidth"),
-											gSavedSettings.getS32("WindowHeight")),
-							  TRUE,
-							  mShowFullscreenProgress);
-		mStatesDirty = true;
-		return TRUE;
+	if(mWantFullscreen)
+	{
+		LLCoordScreen screen_size;
+		LLCoordScreen desired_screen_size(gSavedSettings.getS32("FullScreenWidth"),
+								   gSavedSettings.getS32("FullScreenHeight"));
+		getWindow()->getSize(&screen_size);
+		if(!is_fullscreen || 
+		    screen_size.mX != desired_screen_size.mX 
+			|| screen_size.mY != desired_screen_size.mY)
+		{
+			if (!LLStartUp::canGoFullscreen())
+			{
+				return FALSE;
+			}
+			
+			LLGLState::checkStates();
+			LLGLState::checkTextureChannels();
+			changeDisplaySettings(TRUE, 
+								  desired_screen_size,
+								  gSavedSettings.getBOOL("DisableVerticalSync"),
+								  mShowFullscreenProgress);
+
+			LLGLState::checkStates();
+			LLGLState::checkTextureChannels();
+			mStatesDirty = true;
+			return TRUE;
+		}
 	}
-	else if (!is_fullscreen && mWantFullscreen)
+	else
 	{
-		if (!LLStartUp::canGoFullscreen())
+		if(is_fullscreen)
 		{
-			return FALSE;
+			// Changing to windowed mode.
+			changeDisplaySettings(FALSE, 
+								  LLCoordScreen(gSavedSettings.getS32("WindowWidth"),
+												gSavedSettings.getS32("WindowHeight")),
+								  TRUE,
+								  mShowFullscreenProgress);
+			mStatesDirty = true;
+			return TRUE;
 		}
-		
-		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		changeDisplaySettings(TRUE, 
-							  LLCoordScreen(gSavedSettings.getS32("FullScreenWidth"),
-											gSavedSettings.getS32("FullScreenHeight")),
-							  gSavedSettings.getBOOL("DisableVerticalSync"),
-							  mShowFullscreenProgress);
-
-		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		mStatesDirty = true;
-		return TRUE;
 	}
 	return FALSE;
 }
@@ -4846,13 +4813,9 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
 	BOOL old_fullscreen = mWindow->getFullscreen();
 	if (!old_fullscreen && fullscreen && !LLStartUp::canGoFullscreen())
 	{
-		// we can't do this now, so do it later
-		
-		gSavedSettings.setS32("FullScreenWidth", size.mX);
-		gSavedSettings.setS32("FullScreenHeight", size.mY);
-		//gSavedSettings.setBOOL("DisableVerticalSync", disable_vsync);
-		
-		return TRUE;	// a lie..., because we'll get to it later
+		// Not allowed to switch to fullscreen now, so exit early.
+		// *NOTE: This case should never be reached, but just-in-case.
+		return TRUE;
 	}
 
 	U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
@@ -4939,7 +4902,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
 #if LL_WINDOWS
 		// Only trigger a reshape after switching to fullscreen; otherwise rely on the windows callback
 		// (otherwise size is wrong; this is the entire window size, reshape wants the visible window size)
-		if (fullscreen)
+		if (fullscreen && result_first_try)
 #endif
 		{
 			reshape(size.mX, size.mY);
@@ -5310,7 +5273,16 @@ void LLPickInfo::fetchResults()
 	//{
 	//	mPickType = PICK_PARCEL_WALL;
 	//}
-	if (objectp)
+	if (hit_icon && 
+		(!objectp || 
+		icon_dist < (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec()))
+	{
+		// was this name referring to a hud icon?
+		mHUDIcon = hit_icon;
+		mPickType = PICK_ICON;
+		mPosGlobal = mHUDIcon->getPositionGlobal();
+	}
+	else if (objectp)
 	{
 		if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
 		{
@@ -5362,16 +5334,7 @@ void LLPickInfo::fetchResults()
 			}
 		}
 	}
-	if (hit_icon && 
-		(!objectp || 
-		icon_dist < (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec()))
-	{
-		// was this name referring to a hud icon?
-		mHUDIcon = hit_icon;
-		mPickType = PICK_ICON;
-		mPosGlobal = mHUDIcon->getPositionGlobal();
-	}
-
+	
 	if (mPickCallback)
 	{
 		mPickCallback(*this);
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 49fa3c4..c83c57b 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -344,8 +344,7 @@ public:
 	void			toggleFullscreen(BOOL show_progress);
 
 	// handle shutting down GL and bringing it back up
-	bool			updateResolution(void);
-	void			requestResolutionUpdate(bool fullscreen_checked, U32 resolution_index);
+	void			requestResolutionUpdate(bool fullscreen_checked);
 	BOOL			checkSettings();
 	void			restartDisplay(BOOL show_progress_bar);
 	BOOL			changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 42976ed..e29ea78 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -288,7 +288,9 @@ BOOL LLVOAvatar::sJointDebug = FALSE;
 S32 LLVOAvatar::sCurJoint = 0;
 S32 LLVOAvatar::sCurVolume = 0;
 F32 LLVOAvatar::sUnbakedTime = 0.f;
+F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
 F32 LLVOAvatar::sGreyTime = 0.f;
+F32 LLVOAvatar::sGreyUpdateTime = 0.f;
 
 struct LLAvatarTexData
 {
@@ -4721,7 +4723,7 @@ void LLVOAvatar::addLocalTextureStats( LLVOAvatar::ELocTexIndex idx, LLViewerIma
 				desired_pixels = llmin(mPixelArea, (F32)LOCTEX_IMAGE_AREA_OTHER );
 				imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR);
 			}
-			imagep->addTextureStats( desired_pixels, texel_area_ratio );
+			imagep->addTextureStats( desired_pixels / texel_area_ratio );
 			if (imagep->getDiscardLevel() < 0)
 			{
 				mHasGrey = TRUE; // for statistics gathering
@@ -4743,7 +4745,7 @@ void LLVOAvatar::addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F3
 {
 	mMaxPixelArea = llmax(pixel_area, mMaxPixelArea);
 	mMinPixelArea = llmin(pixel_area, mMinPixelArea);
-	imagep->addTextureStats(pixel_area, texel_area_ratio);
+	imagep->addTextureStats(pixel_area / texel_area_ratio);
 	imagep->setBoostLevel(boost_level);
 }
 
@@ -9171,9 +9173,19 @@ void LLVOAvatar::cullAvatarsByPixelArea()
 	}
 	else
 	{
-		sUnbakedTime += gFrameTimeSeconds;
+		if (gFrameTimeSeconds != sUnbakedUpdateTime) // only update once per frame
+		{
+			sUnbakedUpdateTime = gFrameTimeSeconds;
+			sUnbakedTime += gFrameIntervalSeconds;
+		}
 		if (grey_avatars > 0)
-			sGreyTime += gFrameTimeSeconds;
+		{
+			if (gFrameTimeSeconds != sGreyUpdateTime) // only update once per frame
+			{
+				sGreyUpdateTime = gFrameTimeSeconds;
+				sGreyTime += gFrameIntervalSeconds;
+			}
+		}
 	}
 }
 
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 81cfc6f..9806ceb 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -914,7 +914,9 @@ public:
 	static ETextureIndex sBakedTextureIndices[BAKED_TEXTURE_COUNT];
 
 	static F32 		sUnbakedTime; // Total seconds with >=1 unbaked avatars
+	static F32 		sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) 
 	static F32 		sGreyTime; // Total seconds with >=1 grey avatars
+	static F32 		sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) 
 	
 	//--------------------------------------------------------------------
 	// Texture Layer Sets and Global Colors
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index b1bf989..3bec16f 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -932,6 +932,8 @@ void LLVoiceClient::updateSettings()
 	setCaptureDevice(inputDevice);
 	std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
 	setRenderDevice(outputDevice);
+	F32 mic_level = gSavedSettings.getF32("AudioLevelMic");
+	setMicGain(mic_level);
 	setLipSyncEnabled(gSavedSettings.getBOOL("LipSyncEnabled"));
 }
 
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index e5e5c2e..a91b59f 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -180,6 +180,8 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
 	F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio();
 	pixel_meter_ratio *= pixel_meter_ratio;
 
+	LLViewerPartSim::checkParticleCount(mViewerPartGroupp->mParticles.size()) ;
+
 	S32 count=0;
 	mDepth = 0.f;
 	S32 i = 0 ;
diff --git a/indra/newview/llvotextbubble.cpp b/indra/newview/llvotextbubble.cpp
index f9a12a4..ba53bd3 100644
--- a/indra/newview/llvotextbubble.cpp
+++ b/indra/newview/llvotextbubble.cpp
@@ -118,30 +118,16 @@ BOOL LLVOTextBubble::idleUpdate(LLAgent &agent, LLWorld	&world, const F64 &time)
 void LLVOTextBubble::updateTextures(LLAgent &agent)
 {
 	// Update the image levels of all textures...
-	// First we do some quick checks.
-	U32 i;
 
-	// This doesn't take into account whether the object is in front
-	// or behind...
-
-	LLVector3 position_local = getPositionAgent() - agent.getCameraPositionAgent();
-	F32 dot_product = position_local * agent.getFrameAgent().getAtAxis();
-	F32 cos_angle = dot_product / position_local.length();
-
-	if (cos_angle > 1.f)
-	{
-		cos_angle = 1.f;
-	}
-
-	for (i = 0; i < getNumTEs(); i++)
+	for (U32 i = 0; i < getNumTEs(); i++)
 	{
 		const LLTextureEntry *te = getTE(i);
 		F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
-
+		texel_area_ratio = llclamp(texel_area_ratio, .125f, 16.f);
 		LLViewerImage *imagep = getTEImage(i);
 		if (imagep)
 		{
-			imagep->addTextureStats(mPixelArea, texel_area_ratio, cos_angle);
+			imagep->addTextureStats(mPixelArea / texel_area_ratio);
 		}
 	}
 }
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 46af322..6baff85 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -68,8 +68,7 @@
 const S32 MIN_QUIET_FRAMES_COALESCE = 30;
 const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
 const F32 FORCE_CULL_AREA = 8.f;
-// sadly - we can't lower sculptie rez below b/c residents have a LOT of content that depends on the 128
-const S32 SCULPT_REZ = 128;
+const S32 MAX_SCULPT_REZ = 128;
 
 BOOL gAnimateTextures = TRUE;
 extern BOOL gHideSelectedObjects;
@@ -498,6 +497,7 @@ void LLVOVolume::updateTextures()
 		else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
 		{
 			F32 pri = imagep->getDecodePriority();
+			pri = llmax(pri, 0.0f);
 			if (pri < min_vsize) min_vsize = pri;
 			if (pri > max_vsize) max_vsize = pri;
 		}
@@ -516,7 +516,10 @@ void LLVOVolume::updateTextures()
 		mSculptTexture = gImageList.getImage(id);
 		if (mSculptTexture.notNull())
 		{
-			mSculptTexture->addTextureStats(SCULPT_REZ * SCULPT_REZ);
+			S32 lod = llmin(mLOD, 3);
+			F32 lodf = ((F32)(4-lod)/4.f); // 0 -> 1.0, 3 -> .25
+			F32 tex_size = lodf * MAX_SCULPT_REZ;
+			mSculptTexture->addTextureStats(2.f * tex_size * tex_size);
 			mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(),
 												(S32)LLViewerImage::BOOST_SCULPTED));
 		}
@@ -1946,6 +1949,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 		return FALSE;
 	}
 
+	BOOL ret = FALSE;
+
 	LLVolume* volume = getVolume();
 	if (volume)
 	{	
@@ -2001,6 +2006,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 			if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit)
 			{
 				LLFace* face = mDrawable->getFace(face_hit);
+				v_end = p;
+
 				if (pick_transparent || !face->getTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))
 				{
 					if (face_hitp != NULL)
@@ -2030,13 +2037,13 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 						*tex_coord = tc;
 					}
 					
-					return TRUE;
+					ret = TRUE;
 				}
 			}
 		}
 	}
 		
-	return FALSE;
+	return ret;
 }
 
 U32 LLVOVolume::getPartitionType() const
diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp
index 7d44fcd..b595073 100644
--- a/indra/newview/llwindebug.cpp
+++ b/indra/newview/llwindebug.cpp
@@ -122,7 +122,9 @@ MODULE32_NEST	Module32Next_;
 #define	NL				L"\r\n"	//new line
 
 BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr);
-
+void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, 
+						   const CONTEXT* context_record, 
+						   LLSD& info);
 
 void printError( CHAR* msg )
 {
@@ -185,69 +187,6 @@ BOOL GetProcessThreadIDs(DWORD process_id, std::vector<DWORD>& thread_ids)
   return( TRUE );
 }
 
-void WINAPI GetCallStackData(const CONTEXT* context_struct, LLSD& info)
-{	
-    // Fill Str with call stack info.
-    // pException can be either GetExceptionInformation() or NULL.
-    // If pException = NULL - get current call stack.
-
-    LPWSTR	Module_Name = new WCHAR[MAX_PATH];
-	PBYTE	Module_Addr = 0;
-	
-	typedef struct STACK
-	{
-		STACK *	Ebp;
-		PBYTE	Ret_Addr;
-		DWORD	Param[0];
-	} STACK, * PSTACK;
-
-	PSTACK	Ebp;
-
-    if(context_struct)
-    {
-        Ebp = (PSTACK)context_struct->Ebp;
-    }
-    else
-    {
-        // The context struct is NULL, 
-        // so we will use the current stack.
-        Ebp = (PSTACK)&context_struct - 1;
-
-        // Skip frame of GetCallStackData().
-		if (!IsBadReadPtr(Ebp, sizeof(PSTACK)))
-			Ebp = Ebp->Ebp;		//caller ebp
-    }
-
-	// Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX.
-	// Break trace on wrong stack frame.
-	for (int Ret_Addr_I = 0, i = 0;
-		(Ret_Addr_I < CALL_TRACE_MAX) && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr));
-		Ret_Addr_I++, Ebp = Ebp->Ebp, ++i)
-	{
-		// If module with Ebp->Ret_Addr found.
-
-		if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr))
-		{
-			// Save module's address and full path.
-			info["CallStack"][i]["ModuleName"] = ll_convert_wide_to_string(Module_Name);
-			info["CallStack"][i]["ModuleAddress"] = (int)Module_Addr;
-			info["CallStack"][i]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr);
-
-			LLSD params;
-			// Save 5 params of the call. We don't know the real number of params.
-			if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD)))
-			{
-				for(int j = 0; j < 5; ++j)
-				{
-					params[j] = (int)Ebp->Param[j];
-				}
-			}
-			info["CallStack"][i]["Parameters"] = params;
-		}
-		info["CallStack"][i]["ReturnAddress"] = (int)Ebp->Ret_Addr;			
-	}
-}
-
 BOOL GetThreadCallStack(DWORD thread_id, LLSD& info)
 {
     if(GetCurrentThreadId() == thread_id)
@@ -272,7 +211,7 @@ BOOL GetThreadCallStack(DWORD thread_id, LLSD& info)
         context_struct.ContextFlags = CONTEXT_FULL;
         if(GetThreadContext(thread_handle, &context_struct))
         {
-            GetCallStackData(&context_struct, info);
+            Get_Call_Stack(NULL, &context_struct, info);
             result = true;
         }
         ResumeThread(thread_handle);
@@ -327,16 +266,98 @@ BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & M
 	return found;
 } //Get_Module_By_Ret_Addr
 
+bool has_valid_call_before(PDWORD cur_stack_loc)
+{
+	PBYTE p_first_byte = (PBYTE)(*cur_stack_loc - 1);
+	PBYTE p_second_byte = (PBYTE)(*cur_stack_loc -2);
+	PBYTE p_fifth_byte = (PBYTE)(*cur_stack_loc - 5);
+	PBYTE p_sixth_byte = (PBYTE)(*cur_stack_loc - 6);
+
+	// make sure we can read it
+	if(IsBadReadPtr(p_sixth_byte, 6 * sizeof(BYTE)))
+	{
+		return false;
+	}
+
+	// check for 9a + 4 bytes
+	if(*p_fifth_byte == 0x9A)
+	{
+		return true;
+	}
+
+	// Check for E8 + 4 bytes and last byte is 00 or FF
+	if(*p_fifth_byte == 0xE8 && (*p_first_byte == 0x00 || *p_first_byte == 0xFF))
+	{
+		return true;
+	}
+	
+	// the other is six bytes
+	if(*p_sixth_byte == 0xFF || *p_second_byte == 0xFF)
+	{
+		return true;
+	}
+
+	return false;
+}
+
+PBYTE get_valid_frame(PBYTE esp)
+{
+	PDWORD cur_stack_loc = NULL;
+	const int max_search = 400;
+	WCHAR	module_name[MAX_PATH];
+	PBYTE	module_addr = 0;
+
+	// round to highest multiple of four
+	esp = (esp + (4 - ((int)esp % 4)) % 4);
+
+	// scroll through stack a few hundred places.
+	for (cur_stack_loc = (PDWORD) esp; cur_stack_loc < (PDWORD)esp + max_search; cur_stack_loc += 1)
+	{
+		// if you can read the pointer,
+		if (IsBadReadPtr(cur_stack_loc, sizeof(PDWORD)))
+		{
+			continue;
+		}
+
+		//  check if it's in a module
+		if (!Get_Module_By_Ret_Addr((PBYTE)*cur_stack_loc, module_name, module_addr))
+		{
+			continue;
+		}
+
+		// check if the code before the instruction ptr is a call 
+		if(!has_valid_call_before(cur_stack_loc))
+		{
+			continue;
+		}
+		
+		// if these all pass, return that ebp, otherwise continue till we're dead
+		return (PBYTE)(cur_stack_loc - 1);
+	}
+
+	return NULL;
+}
 //******************************************************************
-void WINAPI Get_Call_Stack(PEXCEPTION_POINTERS pException, LLSD& info)
+void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, 
+						   const CONTEXT* context_record, 
+						   LLSD& info)
 //******************************************************************
 // Fill Str with call stack info.
 // pException can be either GetExceptionInformation() or NULL.
 // If pException = NULL - get current call stack.
-{	
+{
 	LPWSTR	Module_Name = new WCHAR[MAX_PATH];
 	PBYTE	Module_Addr = 0;
-	
+	LLSD params;
+	PBYTE	Esp = NULL;
+	LLSD tmp_info;
+
+	bool fake_frame = false;
+	bool ebp_used = false;
+	const int HEURISTIC_MAX_WALK = 10;
+	int heuristic_walk_i = 0;
+	int Ret_Addr_I = 0;
+
 	typedef struct STACK
 	{
 		STACK *	Ebp;
@@ -347,15 +368,23 @@ void WINAPI Get_Call_Stack(PEXCEPTION_POINTERS pException, LLSD& info)
 	STACK	Stack = {0, 0};
 	PSTACK	Ebp;
 
-	if (pException)		//fake frame for exception address
+	if (exception_record && context_record)		//fake frame for exception address
 	{
-		Stack.Ebp = (PSTACK)pException->ContextRecord->Ebp;
-		Stack.Ret_Addr = (PBYTE)pException->ExceptionRecord->ExceptionAddress;
+		Stack.Ebp = (PSTACK)(context_record->Ebp);
+		Stack.Ret_Addr = (PBYTE)exception_record->ExceptionAddress;
 		Ebp = &Stack;
+		Esp = (PBYTE) context_record->Esp;
+		fake_frame = true;
+	}
+	else if(context_record)
+	{
+        Ebp = (PSTACK)(context_record->Ebp);
+		Esp = (PBYTE)(context_record->Esp);
 	}
 	else
 	{
-		Ebp = (PSTACK)&pException - 1;	//frame addr of Get_Call_Stack()
+		Ebp = (PSTACK)&exception_record - 1;	//frame addr of Get_Call_Stack()
+		Esp = (PBYTE)&exception_record;
 
 		// Skip frame of Get_Call_Stack().
 		if (!IsBadReadPtr(Ebp, sizeof(PSTACK)))
@@ -364,22 +393,21 @@ void WINAPI Get_Call_Stack(PEXCEPTION_POINTERS pException, LLSD& info)
 
 	// Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX.
 	// Break trace on wrong stack frame.
-	for (int Ret_Addr_I = 0, i = 0;
-		(Ret_Addr_I < CALL_TRACE_MAX) && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr));
-		Ret_Addr_I++, Ebp = Ebp->Ebp, ++i)
+	for (Ret_Addr_I = 0;
+		heuristic_walk_i < HEURISTIC_MAX_WALK && 
+		Ret_Addr_I < CALL_TRACE_MAX && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr));
+		Ret_Addr_I++)
 	{
 		// If module with Ebp->Ret_Addr found.
-
 		if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr))
 		{
 			// Save module's address and full path.
-			info["CallStack"][i]["ModuleName"] = ll_convert_wide_to_string(Module_Name);
-			info["CallStack"][i]["ModuleAddress"] = (int)Module_Addr;
-			info["CallStack"][i]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr);
+			tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name);
+			tmp_info["CallStack"][Ret_Addr_I]["ModuleAddress"] = (int)Module_Addr;
+			tmp_info["CallStack"][Ret_Addr_I]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr);
 
-			LLSD params;
 			// Save 5 params of the call. We don't know the real number of params.
-			if (pException && !Ret_Addr_I)	//fake frame for exception address
+			if (fake_frame && !Ret_Addr_I)	//fake frame for exception address
 				params[0] = "Exception Offset";
 			else if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD)))
 			{
@@ -388,10 +416,62 @@ void WINAPI Get_Call_Stack(PEXCEPTION_POINTERS pException, LLSD& info)
 					params[j] = (int)Ebp->Param[j];
 				}
 			}
-			info["CallStack"][i]["Parameters"] = params;
+			tmp_info["CallStack"][Ret_Addr_I]["Parameters"] = params;
+		}
+
+		tmp_info["CallStack"][Ret_Addr_I]["ReturnAddress"] = (int)Ebp->Ret_Addr;
+
+		// get ready for next frame
+		// Set ESP to just after return address.  Not the real esp, but just enough after the return address
+		if(!fake_frame) {
+			Esp = (PBYTE)Ebp + 8;
+		} 
+		else
+		{
+			fake_frame = false;
+		}
+
+		// is next ebp valid?
+		// only run if we've never found a good ebp
+		if(	!ebp_used && 
+			(IsBadReadPtr(Ebp->Ebp, sizeof(PSTACK)) || 
+			IsBadCodePtr(FARPROC(Ebp->Ebp->Ret_Addr)) ||
+			!Get_Module_By_Ret_Addr(Ebp->Ebp->Ret_Addr, Module_Name, Module_Addr)))
+		{
+			heuristic_walk_i++;
+			PBYTE new_ebp = get_valid_frame(Esp);
+			if (new_ebp != NULL)
+			{
+				Ebp = (PSTACK)new_ebp;
+			}
+		}
+		else
+		{
+			ebp_used = true;
+			Ebp = Ebp->Ebp;
 		}
-		info["CallStack"][i]["ReturnAddress"] = (int)Ebp->Ret_Addr;			
 	}
+
+	// Now go back through and edit out heuristic stacks that could very well be bogus.
+	// Leave the top and the last stack chosen by the heuristic, however.
+	if(heuristic_walk_i > 2)
+	{
+		info["CallStack"][0] = tmp_info["CallStack"][0];
+		std::string ttest = info["CallStack"][0]["ModuleName"];
+		for(int cur_frame = 1; 
+			(cur_frame + heuristic_walk_i - 2 < Ret_Addr_I); 
+			++cur_frame)
+		{
+			// edit out the middle heuristic found frames
+			info["CallStack"][cur_frame] = tmp_info["CallStack"][cur_frame + heuristic_walk_i - 2];
+		}
+	}
+	else
+	{
+		info = tmp_info;
+	}
+
+
 } //Get_Call_Stack
 
 //***********************************
@@ -508,7 +588,7 @@ LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException)
 	} //if (pException)
 	
 	// Save call stack info.
-	Get_Call_Stack(pException, info);
+	Get_Call_Stack(pException->ExceptionRecord, pException->ContextRecord, info);
 
 	return info;
 } //Get_Exception_Info
@@ -565,7 +645,7 @@ LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(
 
 	llinfos << "Someone tried to set the exception filter. Listing call stack modules" << llendl;
 	LLSD cs_info;
-	GetCallStackData(NULL, cs_info);
+	Get_Call_Stack(NULL, NULL, cs_info);
 	
 	if(cs_info.has("CallStack") && cs_info["CallStack"].isArray())
 	{
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 3fa9098..13d8d09 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -4092,55 +4092,52 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start,
 				
 		const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f;
 
-		if (!drawable || !drawable->getVObj()->isAttachment())
-		{ //check against avatars
-				sPickAvatar = TRUE;
-				for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-						iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+		//check against avatars
+		sPickAvatar = TRUE;
+		for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+				iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+		{
+			LLViewerRegion* region = *iter;
+
+			LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
+			if (part && hasRenderType(part->mDrawableType))
+			{
+				LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
+				if (hit)
 				{
-					LLViewerRegion* region = *iter;
+					if (!drawable || 
+						!drawable->getVObj()->isAttachment() ||
+						(position-local_end).magVec() > ATTACHMENT_OVERRIDE_DIST)
+					{ //avatar overrides if previously hit drawable is not an attachment or 
+					  //attachment is far enough away from detected intersection
+						drawable = hit;
+						local_end = position;						
+					}
+					else
+					{ //prioritize attachments over avatars
+						position = local_end;
 
-					LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
-					if (part && hasRenderType(part->mDrawableType))
-					{
-						LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
-						if (hit)
+						if (face_hit)
 						{
-							if (!drawable || 
-								!drawable->getVObj()->isAttachment() ||
-								(position-local_end).magVec() > ATTACHMENT_OVERRIDE_DIST)
-							{ //avatar overrides if previously hit drawable is not an attachment or 
-							  //attachment is far enough away from detected intersection
-								drawable = hit;
-								local_end = position;						
-							}
-							else
-							{ //prioritize attachments over avatars
-								position = local_end;
-
-								if (face_hit)
-								{
-									*face_hit = local_face_hit;
-								}
-								if (tex_coord)
-								{
-									*tex_coord = local_texcoord;
-								}
-								if (bi_normal)
-								{
-									*bi_normal = local_binormal;
-								}
-								if (normal)
-								{
-									*normal = local_normal;
-								}
-							}
+							*face_hit = local_face_hit;
+						}
+						if (tex_coord)
+						{
+							*tex_coord = local_texcoord;
+						}
+						if (bi_normal)
+						{
+							*bi_normal = local_binormal;
+						}
+						if (normal)
+						{
+							*normal = local_normal;
 						}
 					}
 				}
 			}
 		}
-
+	}
 
 	//check all avatar nametags (silly, isn't it?)
 	for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin();
diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml
index 7c9b242..1b7722f 100644
--- a/indra/newview/skins/default/xui/de/floater_about.xml
+++ b/indra/newview/skins/default/xui/de/floater_about.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater name="floater_about" title="Über Second Life">
 	<text_editor name="credits_editor">
-		Second Life wird Ihnen präsentiert von Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ und vielen anderen.
+		Second Life wird Ihnen präsentiert von Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les und vielen anderen.
 
-Vielen Dank den folgenden Einwohnern, die uns geholfen haben, dies zur bisher besten Version zu machen: Aminom Marvin, ava ganache, Balthazar Fouroux, CrystalShard Foo, Davec Horsforth, Drew Dwi, Ellla McMahon, Gellan Glenelg, Harleen Gretzky, istephanija munro, Iustinian Tomsen, JC Glimmer, Joeseph Albanese, kelly young, Latif Khalifa, Lex Neva, McCabe Maxsted, Michi Lumin, moni duettmann, Moon Metty, motor loon, Opensource Obscure, Sky Hye, Soap Clawtooth, velveeta biedermann, zeebster colasanti
+Vielen Dank den folgenden Einwohnern, die uns geholfen haben, dies zur bisher besten Version zu machen: afon shepherd, Aimee Trescothick, Alexandrea Fride, Alissa Sabre, Amber DeCuir, Asuka Neely, Auron Forcella, Blue Revolution, Bocan Undercroft, Boroondas Gupte, Brandon Shinobu, Bri Gufler, Buckaroo Mu, Celierra Darling, Christos Atlantis, Coder Kas, Cummere Mayo, dakota schwade, Dirk Talamasca, Dizzy Banjo, Drew Dwi, Duckling Kwak, Ellla McMahon, Erikah Jameson, Erinyse Planer, Eyana Yohkoh, Ezian Ecksol, Faron Karu, Fenoe Lowey, Fox Hwasung, Francisca Biedermann, Gally Young, Gellan Glenelg, Geneko Nemeth, Glenn Rotaru, Hagar Qinan, Harleen Gretzky, Holger Gilruth, hotrodjohnny gears, IAm Zabelin, Inigo Catteneo, Iustinian Tomsen, Jacek Antonell, James Benedek, Jim Kupferberg, Joeseph Albanese, JPT62089 Agnon, Kardargo Adamczyk, Kirstenlee Cinquetti, Latif Khalifa, lea Parnall, Lex Neva, Lillith Anatine, Lilly Zenovka, Lim Catteneo, Lindal Kidd, Mark Rosenbaum, MasterJ Chaplin, McCabe Maxsted, Melvin Starbrook, Meni Kaiousei, Mero Collas, Minakothegothicgeisha Kamachi, Moon Metty, neofilo aabye, Neutron Chesnokov, Nomad Ingwer, norritt Xi, Opensource Obscure, Oracle Weatherwax, Ourasi Ferraris, Pabl0 Roffo, Peyton Aleixandre, Phli Foxchase, Psi Merlin, r2d2 Wunderlich, Regi Yifu, Saijanai Kuhn, Sandor Balczo, Sarkan Dreamscape, Scree Raymaker, Sedona Mills, Selena Beale, Sheet Spotter, Shibari Twine, Silver Key, Simon Kline, SLB Wirefly, Stacy Wombat, Sugarcult Dagger, Tayra Dagostino, Tetsuryu Vlodovic, ThaBiGGDoGG Richez, Timo Gufler, tx Oh, wayfinder wishbringer, Wizzytoe McCullough, Wundur Primbee, Yann Dufaux, Yuu Nakamichi
 
 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
 APR Copyright (C) 2000-2004 The Apache Software Foundation
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_im.xml b/indra/newview/skins/default/xui/de/panel_preferences_im.xml
index 0744495..0e760e6 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_im.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_im.xml
@@ -15,10 +15,8 @@
 	<check_box label="Zeitstempel in IM anzeigen" name="show_timestamps_check"/>
 	<check_box label="Online-Freundbenachrichtigungen anzeigen" name="friends_online_notify_checkbox"/>
 	<text length="1" name="text_box3" type="string">
-		Protokolloptionen:
-	</text>
-	<text length="1" name="text_box3" type="string">
-		Protokolloptionen:
+		Antwort für 
+Beschäftigt-Modus:
 	</text>
 	<text name="text_box4">
 		Protokolloptionen:
diff --git a/indra/newview/skins/default/xui/de/role_actions.xml b/indra/newview/skins/default/xui/de/role_actions.xml
index 26042bd..95eb6c5 100644
--- a/indra/newview/skins/default/xui/de/role_actions.xml
+++ b/indra/newview/skins/default/xui/de/role_actions.xml
@@ -4,157 +4,157 @@
 	     description="Diese Fähigkeiten ermöglichen das Hinzufügen und Entfernen von Mitgliedern sowie den Beitritt ohne Einladung."
 	     name="Membership">
 		<action description="Personen in diese Gruppe einladen"
-		     longdescription="Personen zu dieser Gruppe einladen können Sie mit &apos;Neue Person einladen...&apos; unter &apos;Mitglieder und Rollen&apos; &gt; &apos;Mitglieder&apos;."
+		     longdescription="Personen zu dieser Gruppe einladen können Sie mit „Neue Person einladen...“ unter „Mitglieder und Rollen“ &gt; „Mitglieder“."
 		     name="member invite" />
 		<action description="Mitglieder aus dieser Gruppe werfen"
-		     longdescription="Mitglieder von der Gruppe ausschließen können Sie mit &apos;Aus Gruppe werfen&apos; unter &apos;Mitglieder und Rollen&apos; &gt; &apos;Mitglieder&apos;. Ein Eigentümer kann jeden, außer einen anderen Eigentümer, ausschließen. Wenn Sie kein Eigentümer sind, können Sie ein Mitglied nur dann von der Gruppe ausschließen, wenn es die Rolle &apos;Jeder&apos; innehat, aber KEINE ANDERE Rolle. Um Mitgliedern Rollen entziehen zu können, müssen Sie über die Fähigkeit &apos;Mitgliedern Rollen entziehen&apos; verfügen."
+		     longdescription="Mitglieder von der Gruppe ausschließen können Sie mit „Aus Gruppe werfen“ unter „Mitglieder und Rollen“ &gt; „Mitglieder“. Ein Eigentümer kann jeden, außer einen anderen Eigentümer, ausschließen. Wenn Sie kein Eigentümer sind, können Sie ein Mitglied nur dann von der Gruppe ausschließen, wenn es die Rolle „Jeder“ innehat, aber KEINE ANDERE Rolle. Um Mitgliedern Rollen entziehen zu können, müssen Sie über die Fähigkeit „Mitgliedern Rollen entziehen“ verfügen."
 		     name="member eject" />
 		<action
-		     description="&apos;Registrierung offen&apos; einstellen und &apos;Beitrittsgebühr&apos; ändern"
-		     longdescription="&apos;Beitritt möglich&apos; erlaubt den Beitritt zur Gruppe ohne vorhergehende Einladung. Die &apos;Beitrittsgebühr&apos; wird in den Gruppeneinstellungen auf der Registerkarte &apos;Allgemein&apos; festgelegt."
+		     description="„Registrierung offen“ einstellen und „Beitrittsgebühr“ ändern"
+		     longdescription="„Beitritt möglich“ erlaubt den Beitritt zur Gruppe ohne vorhergehende Einladung. Die „Beitrittsgebühr“ wird in den Gruppeneinstellungen auf der Registerkarte „Allgemein“ festgelegt."
 		     name="member options" />
 	</action_set>
 	<action_set
 	     description="Diese Fähigkeiten ermöglichen das Hinzufügen, Entfernen und Ändern von Gruppenrollen, das Zuweisen und Entfernen von Rollen und das Zuweisen von Fähigkeiten zu Rollen."
 	     name="Roles">
 		<action description="Neue Rollen erstellen"
-		     longdescription="Neue Rollen erstellen Sie unter &apos;Mitglieder und Rollen&apos; &gt; &apos;Rollen&apos;."
+		     longdescription="Neue Rollen erstellen Sie unter „Mitglieder und Rollen“ &gt; „Rollen“."
 		     name="role create" />
 		<action description="Rollen löschen"
-		     longdescription="Rollen löschen können Sie unter &apos;Mitglieder und Rollen&apos; &gt; &apos;Rollen&apos;."
+		     longdescription="Rollen löschen können Sie unter „Mitglieder und Rollen“ &gt; „Rollen“."
 		     name="role delete" />
 		<action description="Rollennamen, Titel und Beschreibung ändern"
-		     longdescription="Namen, Titel und Beschreibungen von Rollen können Sie nach Auswahl einer Rolle unten auf der Registerkarte &apos;Mitglieder und Rollen&apos; &gt; &apos;Rollen&apos; ändern."
+		     longdescription="Namen, Titel und Beschreibungen von Rollen können Sie nach Auswahl einer Rolle unten auf der Registerkarte „Mitglieder und Rollen“ &gt; „Rollen“ ändern."
 		     name="role properties" />
 		<action description="Mitgliedern nur eigene Rollen zuweisen"
-		     longdescription="Mitgliedern nur eigene Rollen zuweisen können Sie im Bereich &apos;Zugewiesene Rollen&apos; auf der Registerkarte &apos;Mitglieder und Rollen&apos; &gt; &apos;Mitglieder&apos;. Ein Mitglied mit dieser Fähigkeit kann anderen Mitgliedern nur die eigenen Rollen zuweisen."
+		     longdescription="Mitgliedern nur eigene Rollen zuweisen können Sie im Bereich „Zugewiesene Rollen“ auf der Registerkarte „Mitglieder und Rollen“ &gt; „Mitglieder“. Ein Mitglied mit dieser Fähigkeit kann anderen Mitgliedern nur die eigenen Rollen zuweisen."
 		     name="role assign member limited" />
 		<action description="Mitgliedern beliebige Rolle zuweisen"
-		     longdescription="Mitgliedern beliebige Rolle zuweisen können Sie im Bereich &apos;Zugewiesene Rollen&apos; auf der Registerkarte &apos;Mitglieder und Rollen&apos; &gt; &apos;Mitglieder&apos;. *WARNUNG* Jedes Mitglied in einer Rolle mit dieser Fähigkeit kann sich selbst und jedem anderen Mitglied (außer dem Eigentümer) Rollen mit weitreichenden Fähigkeiten zuweisen und damit fast Eigentümerrechte erreichen. Überlegen Sie sich, wem Sie diese Fähigkeit verleihen."
+		     longdescription="Mitgliedern beliebige Rolle zuweisen können Sie im Bereich „Zugewiesene Rollen“ auf der Registerkarte „Mitglieder und Rollen“ &gt; „Mitglieder“. *WARNUNG* Jedes Mitglied in einer Rolle mit dieser Fähigkeit kann sich selbst und jedem anderen Mitglied (außer dem Eigentümer) Rollen mit weitreichenden Fähigkeiten zuweisen und damit fast Eigentümerrechte erreichen. Überlegen Sie sich, wem Sie diese Fähigkeit verleihen."
 		     name="role assign member" />
 		<action description="Mitgliedern Rollen entziehen"
-		     longdescription="Mitgliedern Rollen entziehen können Sie im Bereich &apos;Rollen&apos; auf der Registerkarte &apos;Mitglieder und Rollen&apos; &gt; &apos;Mitglieder&apos;. Eigentümer können nicht entfernt werden."
+		     longdescription="Mitgliedern Rollen entziehen können Sie im Bereich „Rollen“ auf der Registerkarte „Mitglieder und Rollen“ &gt; „Mitglieder“. Eigentümer können nicht entfernt werden."
 		     name="role remove member" />
 		<action description="Rollenfähigkeiten zuweisen und entfernen"
-		     longdescription="Rollenfähigkeiten zuweisen und entfernen können Sie im Bereich &apos;Zulässige Fähigkeiten&apos; auf der Registerkarte &apos;Mitglieder und Rollen&apos; &gt; &apos;Rollen&apos;. *WARNUNG* Jedes Mitglied in einer Rolle mit dieser Fähigkeit kann sich selbst und jedem anderen Mitglied (außer dem Eigentümer) alle Fähigkeiten zuweisen und damit fast Eigentümerrechte erreichen. Überlegen Sie sich, wem Sie diese Fähigkeit verleihen."
+		     longdescription="Rollenfähigkeiten zuweisen und entfernen können Sie im Bereich „Zulässige Fähigkeiten“ auf der Registerkarte „Mitglieder und Rollen“ &gt; „Rollen“. *WARNUNG* Jedes Mitglied in einer Rolle mit dieser Fähigkeit kann sich selbst und jedem anderen Mitglied (außer dem Eigentümer) alle Fähigkeiten zuweisen und damit fast Eigentümerrechte erreichen. Überlegen Sie sich, wem Sie diese Fähigkeit verleihen."
 		     name="role change actions" />
 	</action_set>
 	<action_set
 	     description="Diese Fähigkeiten ermöglichen es, die Gruppenidentität zu ändern, z. B. öffentliche Sichtbarkeit, Charta und Insignien."
 	     name="Group Identity">
 		<action
-		     description="Charta, Insignien und &apos;Im Web veröffentlichen&apos; ändern und festlegen, welche Mitglieder in der Gruppeninfo öffentlich sichtbar sind."
-		     longdescription="Charta, Insignien und &apos;Im Web veröffentlichen&apos; ändern und festlegen, welche Mitglieder in der Gruppeninfo öffentlich sichtbar sind. Diese Einstellungen finden Sie auf der Registerkarte &apos;Allgemein&apos;."
+		     description="Charta, Insignien und „Im Web veröffentlichen“ ändern und festlegen, welche Mitglieder in der Gruppeninfo öffentlich sichtbar sind."
+		     longdescription="Charta, Insignien und „Im Web veröffentlichen“ ändern und festlegen, welche Mitglieder in der Gruppeninfo öffentlich sichtbar sind. Diese Einstellungen finden Sie auf der Registerkarte „Allgemein“."
 		     name="group change identity" />
 	</action_set>
 	<action_set
-	     description="Diese Fähigkeiten ermöglichen es, gruppeneigenes Land zu übertragen, zu bearbeiten und zu verkaufen. Klicken Sie mit rechts auf den Boden und wählen Sie &apos;Land-Info...&apos; oder klicken Sie in der Menüleiste auf den Parzellennamen."
+	     description="Diese Fähigkeiten ermöglichen es, gruppeneigenes Land zu übertragen, zu bearbeiten und zu verkaufen. Klicken Sie mit rechts auf den Boden und wählen Sie „Land-Info...“ oder klicken Sie in der Menüleiste auf den Parzellennamen."
 	     name="Parcel Management">
 		<action description="Land übertragen und für Gruppe kaufen"
-		     longdescription="Land übertragen und für Gruppe kaufen. Diese Einstellung finden Sie unter &apos;Land-Info&apos; &gt; &apos;Allgemein&apos;."
+		     longdescription="Land übertragen und für Gruppe kaufen. Diese Einstellung finden Sie unter „Land-Info“ &gt; „Allgemein“."
 		     name="land deed" />
 		<action description="Land Governor Linden überlassen"
-		     longdescription="Land Governor Linden überlassen. *WARNUNG* Jedes Mitglied in einer Rolle mit dieser Fähigkeit kann gruppeneigenes Land unter &apos;Land-Info&apos; &gt; &apos;Allgemein&apos; aufgeben und es ohne Verkauf in das Eigentum von Linden zurückführen! Überlegen Sie sich, wem Sie diese Fähigkeit verleihen."
+		     longdescription="Land Governor Linden überlassen. *WARNUNG* Jedes Mitglied in einer Rolle mit dieser Fähigkeit kann gruppeneigenes Land unter „Land-Info“ &gt; „Allgemein“ aufgeben und es ohne Verkauf in das Eigentum von Linden zurückführen! Überlegen Sie sich, wem Sie diese Fähigkeit verleihen."
 		     name="land release" />
 		<action description="Land.zu.verkaufen-Info einstellen"
-		     longdescription="Land zu verkaufen-Info einstellen. *WARNUNG* Mitglieder in einer Rolle mit dieser Fähigkeit können gruppeneigenes Land jederzeit unter &apos;Land-Info&apos; &gt; &apos;Allgemein&apos; verkaufen! Überlegen Sie sich, wem Sie diese Fähigkeit verleihen."
+		     longdescription="Land zu verkaufen-Info einstellen. *WARNUNG* Mitglieder in einer Rolle mit dieser Fähigkeit können gruppeneigenes Land jederzeit unter „Land-Info“ &gt; „Allgemein“ verkaufen! Überlegen Sie sich, wem Sie diese Fähigkeit verleihen."
 		     name="land set sale info" />
 		<action description="Parzellen teilen und zusammenlegen"
-		     longdescription="Parzellen teilen und zusammenlegen. Klicken Sie dazu mit rechts auf den Boden, wählen sie &apos;Terrain bearbeiten&apos; und ziehen Sie die Maus auf das Land, um eine Auswahl zu treffen. Zum Teilen treffen Sie eine Auswahl und klicken auf &apos;Unterteilen...&apos;. Zum Zusammenlegen von zwei oder mehr angrenzenden Parzellen klicken Sie auf &apos;Zusammenlegen...&apos;."
+		     longdescription="Parzellen teilen und zusammenlegen. Klicken Sie dazu mit rechts auf den Boden, wählen sie „Terrain bearbeiten“ und ziehen Sie die Maus auf das Land, um eine Auswahl zu treffen. Zum Teilen treffen Sie eine Auswahl und klicken auf „Unterteilen...“. Zum Zusammenlegen von zwei oder mehr angrenzenden Parzellen klicken Sie auf „Zusammenlegen...“."
 		     name="land divide join" />
 	</action_set>
 	<action_set
 	     description="Diese Fähigkeiten ermöglichen es, den Parzellennamen und die Veröffentlichungseinstellungen sowie die Anzeige des Suchverzeichnisses, den Landepunkt und die TP-Routenoptionen festzulegen."
 	     name="Parcel Identity">
 		<action
-		     description="&apos;In &quot;Orte suchen&quot; anzeigen&apos; ein-/ausschalten und Kategorie festlegen"
-		     longdescription="Auf der Registerkarte &apos;Optionen&apos; unter &apos;Land-Info&apos; können Sie &apos;In &quot;Orte suchen&quot; anzeigen&apos; ein- und ausschalten und die Parzellenkategorie festlegen."
+		     description="„In Orte suchen anzeigen“ ein-/ausschalten und Kategorie festlegen"
+		     longdescription="Auf der Registerkarte „Optionen“ unter „Land-Info“ können Sie „In Orte suchen anzeigen“ ein- und ausschalten und die Parzellenkategorie festlegen."
 		     name="land find places" />
 		<action
-		     description="Name und Beschreibung der Parzelle und Einstellungen für &apos;Im Web veröffentlichen&apos; ändern"
-		     longdescription="Name und Beschreibung der Parzelle und Einstellungen für &apos;Im Web veröffentlichen&apos; ändern. Diese Einstellungen finden Sie unter &apos;Land-Info&apos; &gt; &apos;Optionen&apos;."
+		     description="Name und Beschreibung der Parzelle und Einstellungen für „Im Web veröffentlichen“ ändern"
+		     longdescription="Name und Beschreibung der Parzelle und Einstellungen für „Im Web veröffentlichen“ ändern. Diese Einstellungen finden Sie unter „Land-Info“ &gt; „Optionen“."
 		     name="land change identity" />
 		<action description="Landepunkt und Teleport-Route festlegen"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer gruppeneigenen Parzelle einen Landepunkt für ankommende Teleports und Teleport-Routen festlegen. Diese Einstellungen finden Sie unter &apos;Land-Info&apos; &gt; &apos;Optionen&apos;."
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer gruppeneigenen Parzelle einen Landepunkt für ankommende Teleports und Teleport-Routen festlegen. Diese Einstellungen finden Sie unter „Land-Info“ &gt; „Optionen“."
 		     name="land set landing point" />
 	</action_set>
 	<action_set
-	     description="Diese Fähigkeiten ermöglichen es, Parzellenoptionen wie &apos;Objekte erstellen&apos;, &apos;Terrain bearbeiten&apos; sowie Musik- und Medieneinstellungen zu ändern."
+	     description="Diese Fähigkeiten ermöglichen es, Parzellenoptionen wie „Objekte erstellen“, „Terrain bearbeiten“ sowie Musik- und Medieneinstellungen zu ändern."
 	     name="Parcel Settings">
 		<action description="Musik- und Medieneinstellungen ändern"
-		     longdescription="Die Einstellungen für Streaming-Musik und Filme finden Sie unter &apos;Land-Info&apos; &gt; &apos;Medien&apos;."
+		     longdescription="Die Einstellungen für Streaming-Musik und Filme finden Sie unter „Land-Info“ &gt; „Medien“."
 		     name="land change media" />
-		<action description="&apos;Terrain bearbeiten&apos; ein/aus"
-		     longdescription="&apos;Terrain bearbeiten&apos; ein/aus. *WARNUNG* &apos;Land-Info&apos; &gt; &apos;Optionen&apos; &gt; &apos;Terrain bearbeiten&apos; ermöglicht jedem das Terraformen Ihres Grundstücks und das Setzen und Verschieben von Linden-Pflanzen. Überlegen Sie sich, wem Sie diese Fähigkeit verleihen. Diese Einstellung finden Sie unter &apos;Land-Info&apos; &gt; &apos;Optionen&apos;."
+		<action description="„Terrain bearbeiten“ ein/aus"
+		     longdescription="„Terrain bearbeiten“ ein/aus. *WARNUNG* „Land-Info“ &gt; „Optionen“ &gt; „Terrain bearbeiten“ ermöglicht jedem das Terraformen Ihres Grundstücks und das Setzen und Verschieben von Linden-Pflanzen. Überlegen Sie sich, wem Sie diese Fähigkeit verleihen. Diese Einstellung finden Sie unter „Land-Info“ &gt; „Optionen“."
 		     name="land edit" />
-		<action description="&apos;Land-Info&apos;-Optionen einstellen"
-		     longdescription="Auf der Registerkarte &apos;Optionen&apos; unter &apos;Land-Info&apos; können Sie &apos;Sicher (kein Schaden)&apos; und &apos;Fliegen&apos; ein- und ausschalten und Einwohnern folgende Aktionen auf gruppeneigenem Land erlauben: &apos;Objekte erstellen&apos;, &apos;Terrain bearbeiten&apos;, &apos;Landmarken erstellen&apos; und &apos;Skripts ausführen&apos;."
+		<action description="„Land-Info“-Optionen einstellen"
+		     longdescription="Auf der Registerkarte „Optionen“ unter „Land-Info“ können Sie „Sicher (kein Schaden)“ und „Fliegen“ ein- und ausschalten und Einwohnern folgende Aktionen auf gruppeneigenem Land erlauben: „Objekte erstellen“, „Terrain bearbeiten“, „Landmarken erstellen“ und „Skripts ausführen“."
 		     name="land options" />
 	</action_set>
 	<action_set
 	     description="Diese Fähigkeiten ermöglichen es, Mitgliedern das Umgehen von Restriktionen auf gruppeneigenen Parzellen zu erlauben."
 	     name="Parcel Powers">
-		<action description="&apos;Terrain bearbeiten&apos; zulassen"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer gruppeneigenen Parzelle das Terrain bearbeiten, selbst wenn diese Option unter &apos;Land-Info&apos; &gt; &apos;Optionen&apos; deaktiviert ist."
+		<action description="„Terrain bearbeiten“ zulassen"
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer gruppeneigenen Parzelle das Terrain bearbeiten, selbst wenn diese Option unter „Land-Info“ &gt; „Optionen“ deaktiviert ist."
 		     name="land allow edit land" />
-		<action description="&apos;Fliegen&apos; zulassen"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer gruppeneigenen Parzelle fliegen, selbst wenn diese Option unter &apos;Land-Info&apos; &gt; &apos;Optionen&apos; deaktiviert ist."
+		<action description="„Fliegen“ zulassen"
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer gruppeneigenen Parzelle fliegen, selbst wenn diese Option unter „Land-Info“ &gt; „Optionen“ deaktiviert ist."
 		     name="land allow fly" />
-		<action description="&apos;Objekte erstellen&apos; zulassen"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer gruppeneigenen Parzelle Objekte erstellen, selbst wenn diese Option unter &apos;Land-Info&apos; &gt; &apos;Optionen&apos; deaktiviert ist."
+		<action description="„Objekte erstellen“ zulassen"
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer gruppeneigenen Parzelle Objekte erstellen, selbst wenn diese Option unter „Land-Info“ &gt; „Optionen“ deaktiviert ist."
 		     name="land allow create" />
-		<action description="&apos;Landmarke erstellen&apos; zulassen"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können für eine gruppeneigene Parzelle eine Landmarke erstellen, selbst wenn diese Option unter &apos;Land-Info&apos; &gt; &apos;Optionen&apos; deaktiviert ist."
+		<action description="„Landmarke erstellen“ zulassen"
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können für eine gruppeneigene Parzelle eine Landmarke erstellen, selbst wenn diese Option unter „Land-Info“ &gt; „Optionen“ deaktiviert ist."
 		     name="land allow landmark" />
-		<action description="&apos;Hier als Zuhause wählen&apos; auf Gruppenland zulassen"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer an diese Gruppe übertragenen Parzelle die Funktion &apos;Welt&apos; &gt; &apos;Hier als Zuhause wählen&apos; verwenden."
+		<action description="„Hier als Zuhause wählen“ auf Gruppenland zulassen"
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer an diese Gruppe übertragenen Parzelle die Funktion „Welt“ &gt; „Hier als Zuhause wählen“ verwenden."
 		     name="land allow set home" />
 	</action_set>
 	<action_set
 	     description="Diese Fähigkeiten ermöglichen es, den Zugang auf gruppeneigenen Parzellen zu steuern. Dazu gehört das Einfrieren und Ausschließen von Einwohnern."
 	     name="Parcel Access">
 		<action description="Parzellen-Zugangslisten verwalten"
-		     longdescription="Parzellen-Zugangslisten bearbeiten Sie unter &apos;Land-Info&apos; &gt; &apos;Zugang&apos;."
+		     longdescription="Parzellen-Zugangslisten bearbeiten Sie unter „Land-Info“ &gt; „Zugang“."
 		     name="land manage allowed" />
 		<action description="Parzellen-Bannlisten verwalten"
-		     longdescription="Parzellen-Bannlisten bearbeiten Sie unter &apos;Land-Info&apos; &gt; &apos;Verbannen&apos;."
+		     longdescription="Parzellen-Bannlisten bearbeiten Sie unter „Land-Info“ &gt; „Verbannen“."
 		     name="land manage banned" />
 		<action
-		     description="Parzelleneinstellungen für &apos;Pässe verkaufen...&apos; ändern"
-		     longdescription="Die Parzellen-Einstellungen für &apos;Pässe verkaufen...&apos; ändern Sie unter &apos;Land-Info&apos; &gt; &apos;Zugang&apos;."
+		     description="Parzelleneinstellungen für „Pässe verkaufen...“ ändern"
+		     longdescription="Die Parzellen-Einstellungen für „Pässe verkaufen...“ ändern Sie unter „Land-Info“ &gt; „Zugang“."
 		     name="land manage passes" />
 		<action description="Einwohner aus Parzellen werfen und einfrieren"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können gegen unerwünschte Personen auf einer gruppeneigenen Parzelle Maßnahmen ergreifen. Klicken Sie die Person mit rechts an und wählen Sie &apos;Mehr&apos; &gt;, dann &apos;Ausschließen...&apos; oder &apos;Einfrieren...&apos;."
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können gegen unerwünschte Personen auf einer gruppeneigenen Parzelle Maßnahmen ergreifen. Klicken Sie die Person mit rechts an und wählen Sie „Mehr“ &gt;, dann „Ausschließen...“ oder „Einfrieren...“."
 		     name="land admin" />
 	</action_set>
 	<action_set
 	     description="Diese Fähigkeiten ermöglichen es, Mitgliedern das Zurückgeben von Objekten sowie das Platzieren und Verschieben von Linden-Pflanzen zu erlauben. Mitglieder können das Grundstück aufräumen und an der Landschaftsgestaltung mitwirken. Aber Vorsicht: Zurückgegebene Objekte können nicht mehr zurückgeholt werden."
 	     name="Parcel Content">
 		<action description="Gruppeneigene Objekte zurückgeben"
-		     longdescription="Gruppeneigene Objekte auf gruppeneigenen Parzellen können Sie unter &apos;Land-Info&apos; &gt; &apos;Objekte&apos; zurückgeben."
+		     longdescription="Gruppeneigene Objekte auf gruppeneigenen Parzellen können Sie unter „Land-Info“ &gt; „Objekte“ zurückgeben."
 		     name="land return group owned" />
 		<action description="Gruppenobjekte zurückgeben"
-		     longdescription="Gruppenobjekte auf gruppeneigenen Parzellen können Sie unter &apos;Land-Info&apos; &gt; &apos;Objekte&apos; zurückgeben."
+		     longdescription="Gruppenobjekte auf gruppeneigenen Parzellen können Sie unter „Land-Info“ &gt; „Objekte“ zurückgeben."
 		     name="land return group set" />
 		<action description="Gruppenfremde Objekte zurückgeben"
-		     longdescription="Objekte von gruppenfremden Personen auf gruppeneigenen Parzellen können Sie unter &apos;Land-Info&apos; &gt; &apos;Objekte&apos; zurückgeben."
+		     longdescription="Objekte von gruppenfremden Personen auf gruppeneigenen Parzellen können Sie unter „Land-Info“ &gt; „Objekte“ zurückgeben."
 		     name="land return non group" />
 		<action description="Landschaftsgestaltung mit Linden-Pflanzen"
-		     longdescription="Die Fähigkeit zur Landschaftsgestaltung ermöglicht das Platzieren und Verschieben von Linden-Bäumen, -Pflanzen und -Gräsern. Diese Objekte finden Sie im Bibliotheksordner des Inventars unter &apos;Objekte&apos;. Sie lassen sich auch mit der Schaltfläche &apos;Erstellen&apos; erzeugen."
+		     longdescription="Die Fähigkeit zur Landschaftsgestaltung ermöglicht das Platzieren und Verschieben von Linden-Bäumen, -Pflanzen und -Gräsern. Diese Objekte finden Sie im Bibliotheksordner des Inventars unter „Objekte“. Sie lassen sich auch mit der Schaltfläche „Erstellen“ erzeugen."
 		     name="land gardening" />
 	</action_set>
 	<action_set
-	     description="Diese Fähigkeiten ermöglichen es, gruppeneigene Objekte zu übertragen, zu bearbeiten und zu verkaufen. Änderungen werden unter &apos;Auswahl-Tool&apos; &gt; &apos;Bearbeiten&apos; auf der Registerkarte &apos;Allgemein&apos; vorgenommen. Klicken Sie mit rechts auf ein Objekt und wählen Sie &apos;Bearbeiten&apos;, um seine Einstellungen anzuzeigen."
+	     description="Diese Fähigkeiten ermöglichen es, gruppeneigene Objekte zu übertragen, zu bearbeiten und zu verkaufen. Änderungen werden unter „Auswahl-Tool“ &gt; „Bearbeiten“ auf der Registerkarte „Allgemein“ vorgenommen. Klicken Sie mit rechts auf ein Objekt und wählen Sie „Bearbeiten“, um seine Einstellungen anzuzeigen."
 	     name="Object Management">
 		<action description="Objekte an Gruppe übertragen"
-		     longdescription="Objekte an eine Gruppe übertragen können Sie unter &apos;Auswahl-Tool&apos; &gt; &apos;Bearbeiten&apos; auf der Registerkarte &apos;Allgemein&apos;."
+		     longdescription="Objekte an eine Gruppe übertragen können Sie unter „Auswahl-Tool“ &gt; „Bearbeiten“ auf der Registerkarte „Allgemein“."
 		     name="object deed" />
 		<action
 		     description="Gruppeneigene Objekte manipulieren (verschieben, kopieren, bearbeiten)"
-		     longdescription="Gruppeneigene Objekte lassen sich unter &apos;Auswahl-Tool&apos; &gt; &apos;Bearbeiten&apos; auf der Registerkarte &apos;Allgemein&apos; manipulieren (verschieben, kopieren, bearbeiten)."
+		     longdescription="Gruppeneigene Objekte lassen sich unter „Auswahl-Tool“ &gt; „Bearbeiten“ auf der Registerkarte „Allgemein“ manipulieren (verschieben, kopieren, bearbeiten)."
 		     name="object manipulate" />
 		<action description="Gruppeneigene Objekte zum Verkauf freigeben"
-		     longdescription="Gruppeneigene Objekte zum Verkauf freigeben können Sie unter &apos;Auswahl-Tool&apos; &gt; &apos;Bearbeiten&apos; auf der Registerkarte &apos;Allgemein&apos;."
+		     longdescription="Gruppeneigene Objekte zum Verkauf freigeben können Sie unter „Auswahl-Tool“ &gt; „Bearbeiten“ auf der Registerkarte „Allgemein“."
 		     name="object set sale" />
 	</action_set>
 	<action_set
@@ -168,20 +168,20 @@
 	     description="Diese Fähigkeiten ermöglichen es, Mitgliedern das Senden, Empfangen und Anzeigen von Gruppennachrichten zu erlauben."
 	     name="Notices">
 		<action description="Mitteilungen senden"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können in der Gruppeninfo unter &apos;Mitteilungen&apos; Mitteilungen senden."
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können in der Gruppeninfo unter „Mitteilungen“ Mitteilungen senden."
 		     name="notices send" />
 		<action description="Mitteilungen erhalten und ältere Mitteilungen anzeigen"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können Mitteilungen erhalten und in der Gruppeninfo unter &apos;Mitteilungen&apos; ältere Mitteilungen einsehen."
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können Mitteilungen erhalten und in der Gruppeninfo unter „Mitteilungen“ ältere Mitteilungen einsehen."
 		     name="notices receive" />
 	</action_set>
 	<action_set
 	     description="Diese Fähigkeiten ermöglichen es, Mitgliedern das Erstellen von Anfragen, das Abstimmen über Anfragen und das Anzeigen des Abstimmprotokolls zu erlauben."
 	     name="Proposals">
 		<action description="Neue Anfragen"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können Anfragen stellen, über die auf der Registerkarte &apos;Anfragen&apos; in der Gruppeninfo abgestimmt werden kann."
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können Anfragen stellen, über die auf der Registerkarte „Anfragen“ in der Gruppeninfo abgestimmt werden kann."
 		     name="proposal start" />
 		<action description="Über Anfragen abstimmen"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können in der Gruppeninfo unter &apos;Anfragen&apos; über Anfragen abstimmen."
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können in der Gruppeninfo unter „Anfragen“ über Anfragen abstimmen."
 		     name="proposal vote" />
 	</action_set>
 	<action_set
@@ -191,7 +191,7 @@
 		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können Gruppen-Chat und Gruppen-Voice-Chat beitreten."
 		     name="join group chat" />
 		<action description="Gruppen-Voice-Chat beitreten"
-		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können Gruppen-Voice-Chat beitreten.HINWEIS:Sie benötigen die Fähigkeit &apos;Gruppen-Chat beitreten&apos;, um Zugang zu dieser Voice-Chat-Sitzung zu erhalten."
+		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können Gruppen-Voice-Chat beitreten. HINWEIS: Sie benötigen die Fähigkeit „Gruppen-Chat beitreten“, um Zugang zu dieser Voice-Chat-Sitzung zu erhalten."
 		     name="join voice chat" />
 		<action description="Gruppen-Chat moderieren"
 		     longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können den Zugang zu und die Teilnahme an Gruppen-Chat- und Voice-Chat-Sitzungen steuern."
diff --git a/indra/newview/skins/default/xui/en-us/floater_about.xml b/indra/newview/skins/default/xui/en-us/floater_about.xml
index 2f1156e..056f97b 100644
--- a/indra/newview/skins/default/xui/en-us/floater_about.xml
+++ b/indra/newview/skins/default/xui/en-us/floater_about.xml
@@ -7,9 +7,9 @@
 	     follows="left|top|right|bottom" font="SansSerifSmall" height="168" left="6"
   max_length="65536" mouse_opaque="true" name="credits_editor" width="458"
   word_wrap="true">
-  Second Life is brought to you by Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ and many others.
+  Second Life is brought to you by Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les and many others.
 
-  Thank you to the following residents for helping to ensure that this is the best version yet: Aimee Trescothick, Alexandrea Fride, Amber DeCuir, Bocan Undercroft, Boroondas Gupte, Brandon Shinobu, Bri Gufler, Buckaroo Mu, Celierra Darling, Christos Atlantis, Coder Kas, Cummere mayo, Dirk Talamasca, Drew Dwi, Ellla McMahon, Erinyse Planer, Eyana Yohkoh, Ezian Ecksol, faron karu, fenoe low, Gellan Glenelg, Harleen Gretzky, Holger Gilruth, Iustinian Tomsen, Jacek Antonell, Jim Kupferberg, Joeseph Albanese, Kirstenlee Cinquetti, lea Parnall, Lex Neva, Lilly Zenovka, Lim Catteneo, McCabe Maxsted, Minakothegothicgeisha Kamachi, Moon Metty, neofilo aabye, Neutron Chesnokov, Nomad Ingwer, norritt Xi, Opensource Obscure, Oracle Weatherwax, Pabl0 Roffo, Peyton Aleixandre, Phli Foxchase, Psi Merlin, Selena Beale, Sheet Spotter, Shibari Twine, Silver Key, Simon Kline, Stacy Wombat, Sugarcult Dagger, Tayra dagostino, ThaBiGGDoGG Richez, tx Oh, Wundur Primbee, Yuu Nakamichi
+  Thank you to the following residents for helping to ensure that this is the best version yet: afon shepherd, Aimee Trescothick, Alexandrea Fride, Alissa Sabre, Amber DeCuir, Asuka Neely, Auron Forcella, Blue Revolution, Bocan Undercroft, Boroondas Gupte, Brandon Shinobu, Bri Gufler, Buckaroo Mu, Celierra Darling, Christos Atlantis, Coder Kas, Cummere Mayo, dakota schwade, Dirk Talamasca, Dizzy Banjo, Drew Dwi, Duckling Kwak, Ellla McMahon, Erikah Jameson, Erinyse Planer, Eyana Yohkoh, Ezian Ecksol, Faron Karu, Fenoe Lowey, Fox Hwasung, Francisca Biedermann, Gally Young, Gellan Glenelg, Geneko Nemeth, Glenn Rotaru, Hagar Qinan, Harleen Gretzky, Holger Gilruth, hotrodjohnny gears, IAm Zabelin, Inigo Catteneo, Iustinian Tomsen, Jacek Antonell, James Benedek, Jim Kupferberg, Joeseph Albanese, JPT62089 Agnon, Kardargo Adamczyk, Kirstenlee Cinquetti, Latif Khalifa, lea Parnall, Lex Neva, Lillith Anatine, Lilly Zenovka, Lim Catteneo, Lindal Kidd, Mark Rosenbaum, MasterJ Chaplin, McCabe Maxsted, Melvin Starbrook, Meni Kaiousei, Mero Collas, Minakothegothicgeisha Kamachi, Moon Metty, neofilo aabye, Neutron Chesnokov, Nomad Ingwer, norritt Xi, Opensource Obscure, Oracle Weatherwax, Ourasi Ferraris, Pabl0 Roffo, Peyton Aleixandre, Phli Foxchase, Psi Merlin, r2d2 Wunderlich, Regi Yifu, Saijanai Kuhn, Sandor Balczo, Sarkan Dreamscape, Scree Raymaker, Sedona Mills, Selena Beale, Sheet Spotter, Shibari Twine, Silver Key, Simon Kline, SLB Wirefly, Stacy Wombat, Sugarcult Dagger, Tayra Dagostino, Tetsuryu Vlodovic, ThaBiGGDoGG Richez, Timo Gufler, tx Oh, wayfinder wishbringer, Wizzytoe McCullough, Wundur Primbee, Yann Dufaux, Yuu Nakamichi
 
   3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
   APR Copyright (C) 2000-2004 The Apache Software Foundation
@@ -33,7 +33,7 @@
   Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
 
 
-  We can only see a short distance ahead, but we can see plenty there that needs to be done. --Alan Turing</text_editor>
+  I get by with a little help from my friends. --Richard Starkey</text_editor>
 
 	<text_editor bottom_delta="174" embedded_items="false"
 	     follows="left|top|right|bottom" font="SansSerif" height="238" left="6"
diff --git a/indra/newview/skins/default/xui/fr/alerts.xml b/indra/newview/skins/default/xui/fr/alerts.xml
index 18557bb..a8ea588 100644
--- a/indra/newview/skins/default/xui/fr/alerts.xml
+++ b/indra/newview/skins/default/xui/fr/alerts.xml
@@ -2334,7 +2334,7 @@ Céder ces [AREA] m² de terrain au groupe [GROUP_NAME] ?
 	</alert>
 	<alert name="DisplaySetToRecommended">
 		<message name="message">
-			Le niveau de sécurité de vos paramètres d&apos;affichage dépend de votre configuration système.
+			Vos paramètres d&apos;affichage ont été réglés avec une marge de sécurité en fonction de votre configuration système.
 		</message>
 	</alert>
 	<alert name="UnableToConnect">
diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml
index 3f6d47c..716ce10 100644
--- a/indra/newview/skins/default/xui/fr/floater_about.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <floater name="floater_about" title="A propos de Second Life">
 	<text_editor name="credits_editor">
-		Second Life existe grâce aux efforts de Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ et de nombreuses autres personnes.
+		Second Life existe grâce aux efforts de Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les et de nombreuses autres personnes.
 
-  Tous nos remerciements aux résidents suivants pour avoir testé cette version (la meilleure qui soit jusqu&apos;à présent) :  Aminom Marvin, ava ganache, Balthazar Fouroux, CrystalShard Foo, Davec Horsforth, Drew Dwi, Ellla McMahon, Gellan Glenelg, Harleen Gretzky, istephanija munro, Iustinian Tomsen, JC Glimmer, Joeseph Albanese, kelly young, Latif Khalifa, Lex Neva, McCabe Maxsted, Michi Lumin, moni duettmann, Moon Metty, motor loon, Opensource Obscure, Sky Hye, Soap Clawtooth, velveeta biedermann, zeebster colasanti
+  Tous nos remerciements aux résidents suivants pour avoir testé cette version (la meilleure qui soit jusqu&apos;à présent) :  afon shepherd, Aimee Trescothick, Alexandrea Fride, Alissa Sabre, Amber DeCuir, Asuka Neely, Auron Forcella, Blue Revolution, Bocan Undercroft, Boroondas Gupte, Brandon Shinobu, Bri Gufler, Buckaroo Mu, Celierra Darling, Christos Atlantis, Coder Kas, Cummere Mayo, dakota schwade, Dirk Talamasca, Dizzy Banjo, Drew Dwi, Duckling Kwak, Ellla McMahon, Erikah Jameson, Erinyse Planer, Eyana Yohkoh, Ezian Ecksol, Faron Karu, Fenoe Lowey, Fox Hwasung, Francisca Biedermann, Gally Young, Gellan Glenelg, Geneko Nemeth, Glenn Rotaru, Hagar Qinan, Harleen Gretzky, Holger Gilruth, hotrodjohnny gears, IAm Zabelin, Inigo Catteneo, Iustinian Tomsen, Jacek Antonell, James Benedek, Jim Kupferberg, Joeseph Albanese, JPT62089 Agnon, Kardargo Adamczyk, Kirstenlee Cinquetti, Latif Khalifa, lea Parnall, Lex Neva, Lillith Anatine, Lilly Zenovka, Lim Catteneo, Lindal Kidd, Mark Rosenbaum, MasterJ Chaplin, McCabe Maxsted, Melvin Starbrook, Meni Kaiousei, Mero Collas, Minakothegothicgeisha Kamachi, Moon Metty, neofilo aabye, Neutron Chesnokov, Nomad Ingwer, norritt Xi, Opensource Obscure, Oracle Weatherwax, Ourasi Ferraris, Pabl0 Roffo, Peyton Aleixandre, Phli Foxchase, Psi Merlin, r2d2 Wunderlich, Regi Yifu, Saijanai Kuhn, Sandor Balczo, Sarkan Dreamscape, Scree Raymaker, Sedona Mills, Selena Beale, Sheet Spotter, Shibari Twine, Silver Key, Simon Kline, SLB Wirefly, Stacy Wombat, Sugarcult Dagger, Tayra Dagostino, Tetsuryu Vlodovic, ThaBiGGDoGG Richez, Timo Gufler, tx Oh, wayfinder wishbringer, Wizzytoe McCullough, Wundur Primbee, Yann Dufaux, Yuu Nakamichi
 
   3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
   APR Copyright (C) 2000-2004 The Apache Software Foundation
diff --git a/indra/newview/skins/default/xui/ja/alerts.xml b/indra/newview/skins/default/xui/ja/alerts.xml
index 48b7a64..4fe99b6 100644
--- a/indra/newview/skins/default/xui/ja/alerts.xml
+++ b/indra/newview/skins/default/xui/ja/alerts.xml
@@ -200,7 +200,7 @@ Studio exhibitのウェブ・ページで確認してください。
 	</alert>
 	<alert name="GroupCreateSuccess">
 		<message name="message">
-			グループの作成が正常に終了しました。
+			グループの作成が正常に行われました。
 		</message>
 	</alert>
 	<alert name="UnableToCreateGroup">
@@ -878,7 +878,7 @@ L$が不足しているのでこのグループに参加することができま
 	</alert>
 	<alert name="GoToAuctionPage">
 		<message name="message">
-			[SECOND_LIFE]ウェブ・ページに移動し、入札あるいはオークションの詳細を確認しますか?
+			[SECOND_LIFE]ウェブ・ページに移動し、 入札あるいはオークションの詳細を確認しますか?
 		</message>
 		<option name="GotoPage">
 			OK
diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml
index 9027f84..86b8883 100644
--- a/indra/newview/skins/default/xui/ja/floater_about.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater name="floater_about" title="Second Lifeについて">
 	<text_editor name="credits_editor">
-		Second Lifeは、 Philip、Tessa、Andrew、Cory、James、Ben、Char、Charlie、Colin、Dan、Daniel、Doug、Eric、Hamlet、Haney、Eve、Hunter、Ian、Jeff、Jennifer、Jim、John、Lee、Mark、Peter、Phoenix、Richard、Robin、Xenon、Steve、Tanya、Eddie、Avi、Frank、Bruce、Aaron、Alice、Bob、Debra、Eileen、Helen、Janet、Louie、Leviathania、Stefan、Ray、Kevin、Tom、Mikeb、MikeT、Burgess、Elena、Tracy、Bill、Todd、Ryan、Zach、Sarah、Nova、Tim、Stephanie、Michael、Evan、Nicolas、Catherine、Rachelle、Dave、Holly、Bub、Kelly、Magellan、Ramzi、Don、Sabin、Jill、Rheya、Jeska、Torley、Kona、Callum、Charity、Ventrella、Jack、Vektor、Iris、Chris、Nicole、Mick、Reuben、Blue、Babbage、Yedwab、Deana、Lauren、Brent、Pathfinder、Chadrick、Altruima、Jesse、Teeny、Monroe、Icculus、David、Tess、Lizzie、Patsy、Isaac、Lawrence、Cyn、Bo、Gia、Annette、Marius、Tbone、Jonathan、Karen、Ginsu、Satoko、Yuko、Makiko、Thomas、Harry、Seth、Alexei、Brian、Guy、Runitai、Ethan、Data、Cornelius、Kenny、Swiss、Zero、Natria、Wendy、Stephen、Teeple、Thumper、Lucy、Dee、Mia、Liana、Warren、Branka、Aura、beez、Milo、Hermia、Red、Thrax、Joe、Sally、Magenta、Mogura、Paul、Jose、Rejean、Henrik、Lexie、Amber、Logan、Xan、Nora、Morpheus、Donovan、Leyla、MichaelFrancis、Beast、Cube、Bucky、Joshua、Stryfe、Harmony、Teresa、Claudia、Walker、Glenn、Fritz、Fordak、June、Cleopetra、Jean、Ivy、Betsy、Roosevelt、Spike、Ken、Which、Tofu、Chiyo、Rob、Zee、dustin、George、Del、Matthew、Cat、Jacqui、Lightfoot、Adrian、Viola、Alfred、Noel、Irfan、Sunil、Yool、Rika、Jane、Xtreme、Frontier、a2、Neo、Siobhan、Yoz、Justin、Elle、Qarl、Benjamin、Isabel、Gulliver、Everett、Christopher、Izzy、Stephany、Garry、Sejong、Sean、Tobin、Iridium、Meta、Anthony、Jeremy、JP、Jake、Maurice、Madhavi、Leopard、Kyle、Joon、Kari、Bert、Belinda、Jon、Kristi、Bridie、Pramod、KJ、Socrates、Maria、Ivan、Aric、Yamasaki、Adreanne、Jay、MitchK、Ceren、Coco、Durl、Jenny、Periapse、Kartic、Storrs、Lotte、Sandy、Rohn、Colossus、Zen、BigPapi、Brad、Pastrami、Kurz、Mani、Neuro、Jaime、MJ、Rowan、Sgt、Elvis、Gecko、Samuel、Sardonyx、Leo、Bryan、Niko、Soft、Poppy、Rachel、Aki、Angelo、Banzai、Alexa、Sue、CeeLo、Bender、CG、Gillian、Pelle、Nick、Echo、Zara、Christine、Shamiran、Emma、Blake、Keiko、Plexus、Joppa、Sidewinder、Erica、Ashlei、Twilight、Kristen、Brett、Q、Enus、Simon、Bevis、Kraft、Kip、Chandler、Ron、LauraP、Ram、KyleJM、Scouse、Prospero、Melissa、Marty、Nat、Hamilton、Kend、Lordan、Jimmy、Kosmo、Seraph、Green、Ekim、Wiggo、JT、Rome、Doris、Miz、Benoc、Whump、Trinity、Patch、Kate、TJ、Bao、Joohwan、Christy、Sofia、Matias、Cogsworth、Johan、Oreh、Cheah、Angela、Brandy、Mango、Lan、Aleks、Gloria、Heidy、Mitchell、Space、Colton、Bambers、Einstein、Maggie、Malbers、Rose、Winnie、Stella、Milton、Rothman、Niall、Marin、Allison、Katie、Dawn、Katt、Dusty、Kalpana、Judy、Andrea、Ambroff、Infinity、Gail、Rico、Raymond、Yi、William、Christa、M、Teagan、Scout、Molly、Dante、Corr、Dynamike、Usi、Kaylee、Vidtuts、Lil、Danica、Sascha、Kelv、Jacob、Nya、Rodney、Brandon、Elsie、Blondin、Grant、Katrin、Nyx、Gabriel、Locklainn、Claire、Devin、Minerva、Monty、Austin、Bradford、Si、Keira、H、Caitlin、Dita、Makai、Jenn、Ann、Meredith、Clare、Joy、Praveen、Cody、Edmund、Ruthe、Sirena、Gayathri、Spider、FJ、Davidoff、Tian、Jennie、Louise、Oskar、Landon、Noelle、Jarv、Ingrid、Al、Sommer、Doc、Aria、Huin、Gray、Lili、Vir、DJと、その他多数の人達によって作成されました。
+		Second Lifeは、 Philip、Tessa、Andrew、Cory、James、Ben、Char、Charlie、Colin、Dan、Daniel、Doug、Eric、Hamlet、Haney、Eve、Hunter、Ian、Jeff、Jennifer、Jim、John、Lee、Mark、Peter、Phoenix、Richard、Robin、Xenon、Steve、Tanya、Eddie、Avi、Frank、Bruce、Aaron、Alice、Bob、Debra、Eileen、Helen、Janet、Louie、Leviathania、Stefan、Ray、Kevin、Tom、Mikeb、MikeT、Burgess、Elena、Tracy、Bill、Todd、Ryan、Zach、Sarah、Nova、Tim、Stephanie、Michael、Evan、Nicolas、Catherine、Rachelle、Dave、Holly、Bub、Kelly、Magellan、Ramzi、Don、Sabin、Jill、Rheya、Jeska、Torley、Kona、Callum、Charity、Ventrella、Jack、Vektor、Iris、Chris、Nicole、Mick、Reuben、Blue、Babbage、Yedwab、Deana、Lauren、Brent、Pathfinder、Chadrick、Altruima、Jesse、Teeny、Monroe、Icculus、David、Tess、Lizzie、Patsy、Isaac、Lawrence、Cyn、Bo、Gia、Annette、Marius、Tbone、Jonathan、Karen、Ginsu、Satoko、Yuko、Makiko、Thomas、Harry、Seth、Alexei、Brian、Guy、Runitai、Ethan、Data、Cornelius、Kenny、Swiss、Zero、Natria、Wendy、Stephen、Teeple、Thumper、Lucy、Dee、Mia、Liana、Warren、Branka、Aura、beez、Milo、Hermia、Red、Thrax、Joe、Sally、Magenta、Mogura、Paul、Jose、Rejean、Henrik、Lexie、Amber、Logan、Xan、Nora、Morpheus、Donovan、Leyla、MichaelFrancis、Beast、Cube、Bucky、Joshua、Stryfe、Harmony、Teresa、Claudia、Walker、Glenn、Fritz、Fordak、June、Cleopetra、Jean、Ivy、Betsy、Roosevelt、Spike、Ken、Which、Tofu、Chiyo、Rob、Zee、dustin、George、Del、Matthew、Cat、Jacqui、Lightfoot、Adrian、Viola、Alfred、Noel、Irfan、Sunil、Yool、Rika、Jane、Xtreme、Frontier、a2、Neo、Siobhan、Yoz、Justin、Elle、Qarl、Benjamin、Isabel、Gulliver、Everett、Christopher、Izzy、Stephany、Garry、Sejong、Sean、Tobin、Iridium、Meta、Anthony、Jeremy、JP、Jake、Maurice、Madhavi、Leopard、Kyle、Joon、Kari、Bert、Belinda、Jon、Kristi、Bridie、Pramod、KJ、Socrates、Maria、Ivan、Aric、Yamasaki、Adreanne、Jay、MitchK、Ceren、Coco、Durl、Jenny、Periapse、Kartic、Storrs、Lotte、Sandy、Rohn、Colossus、Zen、BigPapi、Brad、Pastrami、Kurz、Mani、Neuro、Jaime、MJ、Rowan、Sgt、Elvis、Gecko、Samuel、Sardonyx、Leo、Bryan、Niko、Soft、Poppy、Rachel、Aki、Angelo、Banzai、Alexa、Sue、CeeLo、Bender、CG、Gillian、Pelle、Nick、Echo、Zara、Christine、Shamiran、Emma、Blake、Keiko、Plexus、Joppa、Sidewinder、Erica、Ashlei、Twilight、Kristen、Brett、Q、Enus、Simon、Bevis、Kraft、Kip、Chandler、Ron、LauraP、Ram、KyleJM、Scouse、Prospero、Melissa、Marty、Nat、Hamilton、Kend、Lordan、Jimmy、Kosmo、Seraph、Green、Ekim、Wiggo、JT、Rome、Doris、Miz、Benoc、Whump、Trinity、Patch、Kate、TJ、Bao、Joohwan、Christy、Sofia、Matias、Cogsworth、Johan、Oreh、Cheah、Angela、Brandy、Mango、Lan、Aleks、Gloria、Heidy、Mitchell、Space、Colton、Bambers、Einstein、Maggie、Malbers、Rose、Winnie、Stella、Milton、Rothman、Niall、Marin、Allison、Katie、Dawn、Katt、Dusty、Kalpana、Judy、Andrea、Ambroff、Infinity、Gail、Rico、Raymond、Yi、William、Christa、M、Teagan、Scout、Molly、Dante、Corr、Dynamike、Usi、Kaylee、Vidtuts、Lil、Danica、Sascha、Kelv、Jacob、Nya、Rodney、Brandon、Elsie、Blondin、Grant、Katrin、Nyx、Gabriel、Locklainn、Claire、Devin、Minerva、Monty、Austin、Bradford、Si、Keira、H、Caitlin、Dita、Makai、Jenn、Ann、Meredith、Clare、Joy、Praveen、Cody、Edmund、Ruthe、Sirena、Gayathri、Spider、FJ、Davidoff、Tian、Jennie、Louise、Oskar、Landon、Noelle、Jarv、Ingrid、Al、Sommer、Doc、Aria、Huin、Gray、Lili、Vir、DJ、Yang、T、Simone、Maestro、Scott、Charlene、Quixote、Amanda、Susan、Zed、Anne、Enkidu、Esbee、Joroan、Katelin、Roxie、Tay、Scarlet、Kevin、Johnny、Wolfgang、Andren、Bob、Howard、Merov、Rand、Ray、Michon、Newell、Galen、Dessie、Lesと、その他多数の人達によって作成されました。
 
-  このバージョンをこれまでで最高のものになるようご協力をいただいた以下の住人の皆様に深く感謝いたします。 Aminom Marvin、ava ganache、Balthazar Fouroux、CrystalShard Foo、Davec Horsforth、Drew Dwi、Ellla McMahon、Gellan Glenelg、Harleen Gretzky、istephanija munro、Iustinian Tomsen、JC Glimmer、Joeseph Albanese、kelly young、Latif Khalifa、Lex Neva、McCabe Maxsted、Michi Lumin、moni duettmann、Moon Metty、motor loon、Opensource Obscure、Sky Hye、Soap Clawtooth、velveeta biedermann、zeebster colasanti
+  このバージョンをこれまでで最高のものになるようご協力をいただいた以下の住人の皆様に深く感謝いたします。 afon shepherd、Aimee Trescothick、Alexandrea Fride、Alissa Sabre、Amber DeCuir、Asuka Neely、Auron Forcella、Blue Revolution、Bocan Undercroft、Boroondas Gupte、Brandon Shinobu、Bri Gufler、Buckaroo Mu、Celierra Darling、Christos Atlantis、Coder Kas、Cummere Mayo、dakota schwade、Dirk Talamasca、Dizzy Banjo、Drew Dwi、Duckling Kwak、Ellla McMahon、Erikah Jameson、Erinyse Planer、Eyana Yohkoh、Ezian Ecksol、Faron Karu、Fenoe Lowey、Fox Hwasung、Francisca Biedermann、Gally Young、Gellan Glenelg、Geneko Nemeth、Glenn Rotaru、Hagar Qinan、Harleen Gretzky、Holger Gilruth、hotrodjohnny gears、IAm Zabelin、Inigo Catteneo、Iustinian Tomsen、Jacek Antonell、James Benedek、Jim Kupferberg、Joeseph Albanese、JPT62089 Agnon、Kardargo Adamczyk、Kirstenlee Cinquetti、Latif Khalifa、lea Parnall、Lex Neva、Lillith Anatine、Lilly Zenovka、Lim Catteneo、Lindal Kidd、Mark Rosenbaum、MasterJ Chaplin、McCabe Maxsted、Melvin Starbrook、Meni Kaiousei、Mero Collas、Minakothegothicgeisha Kamachi、Moon Metty、neofilo aabye、Neutron Chesnokov、Nomad Ingwer、norritt Xi、Opensource Obscure、Oracle Weatherwax、Ourasi Ferraris、Pabl0 Roffo、Peyton Aleixandre、Phli Foxchase、Psi Merlin、r2d2 Wunderlich、Regi Yifu、Saijanai Kuhn、Sandor Balczo、Sarkan Dreamscape、Scree Raymaker、Sedona Mills、Selena Beale、Sheet Spotter、Shibari Twine、Silver Key、Simon Kline、SLB Wirefly、Stacy Wombat、Sugarcult Dagger、Tayra Dagostino、Tetsuryu Vlodovic、ThaBiGGDoGG Richez、Timo Gufler、tx Oh、wayfinder wishbringer、Wizzytoe McCullough、Wundur Primbee、Yann Dufaux、Yuu Nakamichi
 
   3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
   APR Copyright (C) 2000-2004 The Apache Software Foundation
diff --git a/indra/newview/skins/default/xui/ja/floater_about_land.xml b/indra/newview/skins/default/xui/ja/floater_about_land.xml
index c6f6e12..eda8fe8 100644
--- a/indra/newview/skins/default/xui/ja/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about_land.xml
@@ -92,7 +92,7 @@
 				プロフィール...
 			</string>
 			<string name="info_text">
-				インフォ...
+				情報...
 			</string>
 			<string name="public_text">
 				(公共)
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
index 3079d45..a532640 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
@@ -35,13 +35,13 @@
 		データを取得しています...
 	</text>
 	<text name="balance_label">
-		現在所有している額
+		現在所有している金額
 	</text>
 	<text name="balance_amount">
 		L$ [AMT]
 	</text>
 	<text name="buying_label">
-		購入する額
+		購入する金額
 	</text>
 	<text name="buying_amount">
 		L$ [AMT]
diff --git a/indra/newview/skins/default/xui/ja/floater_inspect.xml b/indra/newview/skins/default/xui/ja/floater_inspect.xml
index fe2f075..c831201 100644
--- a/indra/newview/skins/default/xui/ja/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/ja/floater_inspect.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="inspect" title="オブジェクト検査">
+<floater name="inspect" title="オブジェクト検査" min_width="450" >
 	<scroll_list name="object_list"
 	     tool_tip="このリストからオブジェクトを選択し、この世界で強調表示します。">
 		<column label="オブジェクト名" name="object_name" />
diff --git a/indra/newview/skins/default/xui/ja/floater_inventory.xml b/indra/newview/skins/default/xui/ja/floater_inventory.xml
index db90c4e..6804968 100644
--- a/indra/newview/skins/default/xui/ja/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/ja/floater_inventory.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater name="Inventory" title="持ち物">
-	<search_editor label="ここにタイプして検索" name="inventory search editor" />
+	<search_editor label="ここに入力して検索" name="inventory search editor" />
 	<tab_container name="inventory filter tabs">
 		<inventory_panel label="すべて" name="All Items" />
 		<inventory_panel label="最近の入手アイテム" name="Recent Items" />
@@ -37,7 +37,7 @@
 				<menu_item_call label="新しい眼" name="New Eyes" />
 			</menu>
 		</menu>
-		<menu label="振り分け" name="Sort">
+		<menu label="並べ替え" name="Sort">
 			<menu_item_check label="名前" name="By Name" />
 			<menu_item_check label="日付" name="By Date" />
 			<menu_item_check label="フォルダは常に名前順" name="Folders Always By Name" />
diff --git a/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml
index 7ec92e4..be2710c 100644
--- a/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml
@@ -49,7 +49,7 @@
 	</text>
 	<check_box label="グループ分担" name="CheckShareWithGroup" />
 	<check_box label="誰に対してもコピーを許可" name="CheckEveryoneCopy" />
-	<text name="NextOwnerLabel">
+	<text name="NextOwnerLabel" width="158">
 		次のオーナーができること:
 	</text>
 	<check_box label="修正" name="CheckNextOwnerModify" />
diff --git a/indra/newview/skins/default/xui/ja/floater_land_holdings.xml b/indra/newview/skins/default/xui/ja/floater_land_holdings.xml
index 49d7f16..949031d 100644
--- a/indra/newview/skins/default/xui/ja/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/ja/floater_land_holdings.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater name="land holdings floater" title="自分の土地">
 	<scroll_list name="parcel list">
-		<column label="Name" name="name" />
-		<column label="Location" name="location" />
-		<column label="Area" name="area" />
+		<column name="name" />
+		<column name="location" />
+		<column name="area" />
 		<column label="" name="hidden" />
 	</scroll_list>
 	<button label="テレポート" label_selected="テレポート" name="Teleport"
@@ -15,28 +15,28 @@
 		あなたのグループへの貢献:
 	</text>
 	<scroll_list name="grant list">
-		<column label="Group" name="group" />
-		<column label="Area" name="area" />
+		<column name="group" />
+		<column name="area" />
 	</scroll_list>
 	<text name="allowed_label">
 		現在の支払いプランでの許可された保有地:
 	</text>
 	<text name="allowed_text">
-		[AREA]平方メートル
+		[AREA]平方メートル
 	</text>
 	<text name="current_label">
 		現在の保有地:
 	</text>
 	<text name="current_text">
-		[AREA]平方メートル
+		[AREA]平方メートル
 	</text>
 	<text name="available_label">
 		土地購入可:
 	</text>
 	<text name="available_text">
-		[AREA]平方メートル
+		[AREA]平方メートル
 	</text>
 	<string name="area_string">
-		[AREA]平方メートル
+		[AREA]平方メートル
 	</string>
 </floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_media_browser.xml b/indra/newview/skins/default/xui/ja/floater_media_browser.xml
index a002991..3870ae1 100644
--- a/indra/newview/skins/default/xui/ja/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/ja/floater_media_browser.xml
@@ -4,15 +4,15 @@
 		<layout_panel name="nav_controls">
 			<button label="戻る" name="back" />
 			<button label="進む" name="forward" />
-			<button label="再ロード" name="reload" />
-			<button label="行く" name="go" />
+			<button label="更新" name="reload" />
+			<button label="閲覧" name="go" />
 		</layout_panel>
 		<layout_panel name="parcel_owner_controls">
 			<button label="現在の URL を区画に送信" name="assign" />
 		</layout_panel>
 		<layout_panel name="external_controls">
 			<button label="自分の Web ブラウザーで開く" name="open_browser" />
-			<check_box label="常にマイブラウザーで開く" name="open_always" />
+			<check_box label="常に自分の Web ブラウザーで開く" name="open_always" />
 			<button label="閉じる" name="close" />
 		</layout_panel>
 	</layout_stack>
diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml
index b888051..7968847 100644
--- a/indra/newview/skins/default/xui/ja/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml
@@ -114,10 +114,10 @@
 		<menu_item_call label="アニメーションをすべて停止" name="Stop All Animations"/>
 		<menu_item_call label="キー制御を解除" name="Release Keys"/>
 		<menu_item_separator label="-----------" name="separator4"/>
-		<menu_item_call label="口座履歴..." name="Account History...">
+		<menu_item_call label="アカウントの履歴..." name="Account History...">
 			<on_click name="AccountHistory_url" userdata="WebLaunchAccountHistory,http://secondlife.com/account/transactions.php?lang=ja" />
 		</menu_item_call>
-		<menu_item_call label="自分の口座の管理..." name="Manage My Account...">
+		<menu_item_call label="マイアカウントの管理..." name="Manage My Account...">
 			<on_click name="ManageMyAccount_url" userdata="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=ja" />
 		</menu_item_call>
 		<menu_item_call label="L$(リンデン・ドル)を購入" name="Buy and Sell L$..."/>
diff --git a/indra/newview/skins/default/xui/ja/notify.xml b/indra/newview/skins/default/xui/ja/notify.xml
index 4039637..f587868 100644
--- a/indra/newview/skins/default/xui/ja/notify.xml
+++ b/indra/newview/skins/default/xui/ja/notify.xml
@@ -403,7 +403,7 @@
 	</notify>
 	<notify name="ScriptsNotRunning">
 		<message name="message">
-			この地域はスクリプトを1つも起動していません。
+			この地域ではスクリプトの使用が禁止されています
 		</message>
 	</notify>
 	<notify name="NoOutsideScripts">
@@ -441,7 +441,7 @@
 			破棄
 		</option>
 		<option name="Mute">
-			無視リスト
+			無視リストへ
 		</option>
 	</notify>
 	<notify name="ObjectGiveItemUnknownUser">
@@ -455,7 +455,7 @@
 			破棄
 		</option>
 		<option name="Mute">
-			無視リスト
+			無視リストへ
 		</option>
 	</notify>
 	<notify name="UserGiveItem">
@@ -469,7 +469,7 @@
 			破棄
 		</option>
 		<option name="Mute">
-			無視リスト
+			無視リストへ
 		</option>
 	</notify>
 	<notify name="GodMessage">
@@ -569,7 +569,7 @@
 	</notify>
 	<notify name="OfferFriendship">
 		<message name="message">
-			[NAME]は、フレンド登録を申し込んでいます。
+			[NAME]は、フレンド 登録を申し込んでいます。
  
 [MESSAGE]
  
@@ -584,7 +584,7 @@
 	</notify>
 	<notify name="OfferFriendshipNoMessage">
 		<message name="message">
-			[NAME]は、フレンド登録を申し込んでいます。
+			[NAME]は、フレンド 登録を申し込んでいます。
 
 (デフォルトでお互いのオンライン・ステータスを見ることができるようになります。)
 		</message>
@@ -597,12 +597,12 @@
 	</notify>
 	<notify name="FriendshipAccepted">
 		<message name="message">
-			[NAME]は、フレンド登録を受け入れました。
+			[NAME]は、フレンド 登録を受け入れました。
 		</message>
 	</notify>
 	<notify name="FriendshipDeclined">
 		<message name="message">
-			[NAME]は、フレンド登録を断りました。
+			[NAME]は、フレンド 登録を断りました。
 		</message>
 	</notify>
 	<notify name="OfferCallingCard">
@@ -693,7 +693,7 @@
 	</notify>
 	<notify name="AttachToYourAvatar">
 		<message name="message">
-			あなたのアバターに装着添付
+			あなたのアバターに装着
 		</message>
 	</notify>
 	<notify name="ReleaseOwnership">
@@ -740,7 +740,7 @@
 			いいえ
 		</option>
 		<option name="Mute">
-			無視リスト
+			無視リストに追加
 		</option>
 	</notify>
 	<notify name="ScriptQuestionCautionChatGranted">
@@ -799,13 +799,13 @@
 		<message name="message">
 			L$[AMOUNT]を受け取りました。
 オブジェクトおよび他のユーザーがあなたにお金を支払ったようです。
-あなたの残高は画面の右上に表示されています。
+あなたの残高は画面の右上に表示されて います。
 		</message>
 	</notify>
 	<notify name="FirstBalanceDecrease">
 		<message name="message">
 			L$[AMOUNT]を支払いました。
-あなたの残高は画面の右上に表示されています。
+あなたの残高は画面の右上に表示されて います。
 		</message>
 	</notify>
 	<notify name="FirstSit">
@@ -926,17 +926,17 @@ Mキーを押して変更します。
 	</notify>
 	<notify name="AutoUnmuteByIM">
 		<message name="message">
-			[FIRST] [LAST]にインスタント・メッセージが送信され、無視設定が自動的に解除されました。
+			[FIRST] [LAST]にインスタント・メッセージが送信され、 無視設定が自動的に解除されました。
 		</message>
 	</notify>
 	<notify name="AutoUnmuteByMoney">
 		<message name="message">
-			[FIRST] [LAST]にお金を渡したため、無視設定が自動的に解除されました。
+			[FIRST] [LAST]にお金を渡したため、 無視設定が自動的に解除されました。
 		</message>
 	</notify>
 	<notify name="AutoUnmuteByInventory">
 		<message name="message">
-			[FIRST] [LAST]に持ち物を渡したため、無視設定が自動的に解除されました。
+			[FIRST] [LAST]に持ち物を渡したため、 無視設定が自動的に解除されました。
 		</message>
 	</notify>
 	<notify name="VoiceInviteGroup">
@@ -1051,7 +1051,7 @@ Mキーを押して変更します。
 	</notify>
 	<notify name="ServerVersionChanged">
 		<message name="message">
-			入力した地域は異なるシミュレーターのバージョンで実行されています。 詳細についてはこのメッセージをクリックしてください。
+			到着した地域は異なるシミュレーターのバージョンで実行されています。 詳細についてはこのメッセージをクリックしてください。
 		</message>
 	</notify>
 	<notify name="UnableToOpenCommandURL">
diff --git a/indra/newview/skins/default/xui/ja/panel_audio.xml b/indra/newview/skins/default/xui/ja/panel_audio.xml
index 02be06d..0d93e73 100644
--- a/indra/newview/skins/default/xui/ja/panel_audio.xml
+++ b/indra/newview/skins/default/xui/ja/panel_audio.xml
@@ -6,6 +6,6 @@
 	<slider label="メディア" name="Media Volume" label_width="80" />
 	<slider label="ボイス" name="Voice Volume" label_width="80" />
 	<slider label="サウンド" name="SFX Volume" label_width="80" />
-	<slider label="アンビエント" name="Wind Volume" label_width="80" />
+	<slider label="風の音量" name="Wind Volume" label_width="80" />
 	<slider label="UI" name="UI Volume" label_width="80" />
 </panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_general.xml b/indra/newview/skins/default/xui/ja/panel_group_general.xml
index bed2bed..ee2d093 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_general.xml
@@ -11,11 +11,8 @@
 		グループ設定が変更されました。
 	</string>
 	<button label="?" label_selected="?" name="help_button" />
-	<line_editor label="あなたの新しいグループ名を記入してください"
-	     name="group_name_editor">
-		新しいグループ名をここに入力してください。
-	</line_editor>
-	<text name="group_name">
+	<line_editor label="新しいグループ名をここに入力してください。" name="group_name_editor" width="330"/>
+	<text name="group_name" width="330">
 		新しいグループ名をここに入力してください。
 	</text>
 	<text name="prepend_founded_by">
@@ -25,12 +22,12 @@
 		(待機中)
 	</text>
 	<text name="group_charter_label">
-		グループ特権
+		グループ憲章
 	</text>
 	<texture_picker label="グループ記章" name="insignia"
 	     tool_tip="写真をクリックして選択" />
 	<text_editor name="charter">
-		グループ特権
+		グループ憲章
 	</text_editor>
 	<button label="参加する(L$0)" label_selected="参加する(L$0)"
 	     name="join_button" />
@@ -48,9 +45,9 @@
 		(オーナーは太字で表示されています)
 	</text>
 	<name_list name="visible_members">
-		<column label="Member Name" name="name" />
-		<column label="Title" name="title" />
-		<column label="Last Login" name="online" />
+		<column name="name" />
+		<column name="title" />
+		<column name="online" />
 	</name_list>
 	<text name="text_group_preferences">
 		グループ環境設定
@@ -61,26 +58,26 @@
 	<text name="confirm_group_create_str">
 		このグループの作成にはL$100かかります。 
 このグループの作成にL$100ものお金をかけてもかまいませんか? 慎重に判断してください。
-48 時間以内に誰もこのグループに参加しなかった場合、グループは解体され、グループの名前は今後使用できなくなります。
+48時間以内に誰もこのグループに参加しなかった場合、グループは解体され、グループの名前は今後使用できなくなります。
 	</text>
 	<text>
 		グループの環境設定
 	</text>
 	<panel name="preferences_container">
 		<check_box label="検索に表示" name="show_in_group_list"
-		     tool_tip="検索結果で、このグループを人に見せる" />
+		     tool_tip="このグループを検索結果に表示させます" />
 		<check_box label="ウェブ上で公開" name="publish_on_web"
-		     tool_tip="このグループの情報をウェブ上で公開できるようにするかどうかを指定します。" />
+		     tool_tip="このグループの情報をウェブ上で公開できるようにするかどうかを指定します" />
 		<check_box label="会員募集" name="open_enrollement"
-		     tool_tip="このグループに招待状なしで新しいメンバーを受け入れるかどうかを指定します。" />
+		     tool_tip="招待状なしに自由にこのグループに加入することを許可するかどうかを指定します" />
 		<check_box label="入会費:L$" name="check_enrollment_fee"
-		     tool_tip="このグループへの参加に入会費を必須とするかどうかを指定します。" />
+		     tool_tip="このグループへの参加に入会費を必須とするかどうかを指定します" />
 		<spinner name="spin_enrollment_fee"
-		     tool_tip="「入会費」がチェックされている場合、新規会員は入会時にこの費用を支払う必要があります。" />
+		     tool_tip="「入会費」がチェックされている場合、新規会員は入会時にここに指定された金額を支払う必要があります" />
 		<check_box label="成人向けグループ" name="mature"
-		     tool_tip="あなたのグループ情報が成人向けとみなされるかどうかを指定します。" />
+		     tool_tip="あなたのグループ情報が成人向けとみなされるかどうかを指定します" />
 		<combo_box name="group_mature_check"
-		     tool_tip="あなたのグループ情報が成人向けとみなされるかどうかを指定します。">
+		     tool_tip="あなたのグループ情報が成人向けとみなされるかどうかを指定します">
 			<combo_item name="select_mature">
 				-成熟度を選択-
 			</combo_item>
@@ -95,13 +92,12 @@
 			<text name="active_title_label">
 				私のアクティブ・タイトル
 			</text>
-			<combo_box name="active_title"
-			     tool_tip="Sets the title that appears in your avatar&apos;s name tag   when this group is active." />
+			<combo_box name="active_title" />
 		</panel>
 		<check_box label="グループ通知を受信" name="receive_notices"
-		     tool_tip="グループからの通知をあなたが受信するかどうかを指定します。 このグループがスパム行為をしている場合は、このボックスのチェックを外してください。" />
-		<check_box label="プロフィールにグループをリストする"
+		     tool_tip="グループからの通知を受信するかどうかを指定します。 このグループがスパム行為をしている場合は、このボックスのチェックを外してください" />
+		<check_box label="プロフィールにグループを表示"
 		     name="list_groups_in_profile"
-		     tool_tip="このグループをあなたのプロフィールにリストするかどうかを設定します。" />
+		     tool_tip="このグループをあなたのプロフィールに表示するかどうかを設定します" />
 	</panel>
 </panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_land_money.xml b/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
index 53ea61a..9d76935 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
@@ -21,9 +21,9 @@
 		グループの保有地
 	</text>
 	<scroll_list name="group_parcel_list">
-		<column label="Parcel Name" name="name" />
-		<column label="Region" name="location" />
-		<column label="Area" name="area" />
+		<column name="name" />
+		<column name="location" />
+		<column name="area" />
 		<column label="" name="hidden" />
 	</scroll_list>
 	<button label="地図上に表示" label_selected="地図上に表示"
@@ -31,20 +31,20 @@
 	<text name="total_contributed_land_label">
 		寄付総額:
 	</text>
-	<text name="total_contributed_land_value">
-		[AREA]平方メートル
+	<text name="total_contributed_land_value" width="150">
+		[AREA]平方メートル
 	</text>
 	<text name="total_land_in_use_label">
 		土地利用の合計:
 	</text>
-	<text name="total_land_in_use_value">
-		[AREA]平方メートル
+	<text name="total_land_in_use_value" width="150">
+		[AREA]平方メートル
 	</text>
 	<text name="land_available_label">
 		利用可の土地:
 	</text>
-	<text name="land_available_value">
-		[AREA]平方メートル
+	<text name="land_available_value" width="150">
+		[AREA]平方メートル
 	</text>
 	<text name="your_contribution_label">
 		あなたの貢献:
@@ -74,19 +74,19 @@
 			<text_editor name="group_money_details_text">
 				計算中…
 			</text_editor>
-			<button label="<前" label_selected="<前" name="earlier_details_button"
-			     tool_tip="時間を戻す" />
-			<button label="あとで>" label_selected="あとで>" name="later_details_button"
-			     tool_tip="時間を進める" />
+			<button label="前の週" label_selected="前の週" name="earlier_details_button"
+			     tool_tip="前の週の履歴" />
+			<button label="次の週" label_selected="次の週" name="later_details_button"
+			     tool_tip="次の週の履歴" />
 		</panel>
 		<panel label="販売" name="group_money_sales_tab">
 			<text_editor name="group_money_sales_text">
 				計算中…
 			</text_editor>
-			<button label="<前" label_selected="<前" name="earlier_sales_button"
-			     tool_tip="時間を戻す" />
-			<button label="あとで>" label_selected="あとで>" name="later_sales_button"
-			     tool_tip="時間を進める" />
+			<button label="前の週" label_selected="前の週" name="earlier_sales_button"
+			     tool_tip="前の週の履歴" />
+			<button label="次の週" label_selected="次の週" name="later_sales_button"
+			     tool_tip="次の週の履歴" />
 		</panel>
 	</tab_container>
 </panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_notices.xml b/indra/newview/skins/default/xui/ja/panel_group_notices.xml
index 2bdc45f..66ef789 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_notices.xml
@@ -21,9 +21,9 @@
 	</text>
 	<scroll_list name="notice_list">
 		<column label="" name="icon" />
-		<column label="Subject" name="subject" />
-		<column label="From" name="from" />
-		<column label="Date" name="date" />
+		<column name="subject" />
+		<column name="from" />
+		<column name="date" />
 	</scroll_list>
 	<text name="notice_list_none_found">
 		何も見つかりませんでした。
@@ -53,8 +53,7 @@
 		<button label="添付物を削除" label_selected="添付物を削除"
 		     name="remove_attachment" />
 		<button label="通知を送信" label_selected="通知を送信" name="send_notice" />
-		<panel name="drop_target"
-		     tool_tip="Drag an inventory item onto the message box to send it with the notice. You must have permission to copy and transfer the object to send it with the notice." />
+		<panel name="drop_target" />
 	</panel>
 	<panel label="過去の通知を表示" name="panel_view_past_notice">
 		<text name="lbl">
diff --git a/indra/newview/skins/default/xui/ja/panel_group_roles.xml b/indra/newview/skins/default/xui/ja/panel_group_roles.xml
index 4640600..0208331 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_roles.xml
@@ -51,7 +51,7 @@
 			<button label="全てを表示" name="show_all_button" />
 			<name_list name="member_list">
 				<column label="メンバー名" name="name" />
-				<column label="Donated Tier" name="donated" />
+				<column name="donated" />
 				<column label="前回のログイン" name="online" />
 			</name_list>
 			<button label="新しい人を招待..." name="member_invite" />
@@ -67,7 +67,7 @@ Ctrl キーを押しながらメンバー名をクリックすると
 			<button label="すべてを表示" name="show_all_button" />
 			<scroll_list name="role_list">
 				<column label="役割名" name="name" />
-				<column label="Title" name="title" />
+				<column label="肩書き" name="title" />
 				<column label="メンバー" name="members" />
 			</scroll_list>
 			<button label="新しい役割を作成..." name="role_create" />
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_audio.xml b/indra/newview/skins/default/xui/ja/panel_preferences_audio.xml
index dca2be9..9a8d175 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_audio.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_audio.xml
@@ -39,7 +39,7 @@
 	<slider label="遠隔要因" name="Distance Factor" />
 	<slider label="ロールオフ係数" name="Rolloff Factor" />
 	<spinner label="L$変更基準点" name="L$ Change Threshold" />
-	<spinner label="健康変化基準点" name="Health Change Threshold" />
+	<spinner label="ヘルス変化基準点" name="Health Change Threshold" />
 	<text type="string" length="1" name="doppler_effect_text">
 		オーディオ環境設定:
 	</text>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/ja/panel_preferences_graphics1.xml
index 7b987d5..167bc2a 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_graphics1.xml
@@ -69,7 +69,7 @@
 	</text>
 	<check_box label="解像度単独スケールを使用" name="ui_auto_scale" />
 	<spinner label="描画距離:" name="draw_distance" />
-	<check_box label="アバターをマウスルックで表示" name="avfp" />
+	<check_box label="アバターを一人称視点(マウスルック)で表示" name="avfp" />
 	<text name="HigherText">
 		品質および
 	</text>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_im.xml b/indra/newview/skins/default/xui/ja/panel_preferences_im.xml
index b6c82b7..e9044e2 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_im.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_im.xml
@@ -8,7 +8,7 @@
 		IMオプション:
 	</text>
 	<text name="log_in_to_change">
-		変更時にログイン
+		ログインして変更してください
 	</text>
 	<check_box label="IMを電子メール([EMAIL])へ送信" name="send_im_to_email"/>
 	<check_box label="ローカルチャットにIMを含める" name="include_im_in_chat_history"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_input.xml b/indra/newview/skins/default/xui/ja/panel_preferences_input.xml
index 75e9051..c84ae62 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_input.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_input.xml
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="操作とカメラ" name="Input panel">
 	<text name=" Mouselook Options:">
-		マウスルック:
+		一人称視点
+(マウスルック):
 	</text>
 	<text name=" Mouse Sensitivity:">
 		感度:
@@ -28,7 +29,7 @@
 	<text name="text2">
 		アバター表示:
 	</text>
-	<check_box label="アバターをマウスルックで表示" name="first_person_avatar_visible"/>
+	<check_box label="アバターを一人称視点(マウスルック)で表示" name="first_person_avatar_visible"/>
 	<text name="text5">
 		ジョイスティック
 オプション:
diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
index eb06ad7..08c6618 100644
--- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="status">
-	<text length="1" name="ParcelNameText" tool_tip="あなたが立っている土地区画の名前。 「土地情報」をクリックしてください。" type="string">
+	<text length="1" name="ParcelNameText" tool_tip="あなたが立っている土地区画の名 前。クリックすると「土地情報」が開きます。" type="string">
 		区画名はここです
 	</text>
 	<text length="1" name="BalanceText" tool_tip="口座残高" type="string">
@@ -25,7 +25,7 @@
 	<button label="" label_selected="" name="build" tool_tip="作成禁止"/>
 	<button label="" label_selected="" name="scripts" tool_tip="スクリプトなし"/>
 	<button name="no_fly" tool_tip="飛行禁止"/>
-	<button name="no_build" tool_tip="制作/REZ禁止"/>
+	<button name="no_build" tool_tip="制作/Rez禁止"/>
 	<button name="no_scripts" tool_tip="スクリプト禁止"/>
 	<button label="" label_selected="" name="restrictpush" tool_tip="プッシングを制限"/>
 	<button name="status_voice" tool_tip="ボイス有効"/>
diff --git a/indra/newview/skins/default/xui/ko/floater_about.xml b/indra/newview/skins/default/xui/ko/floater_about.xml
index bebb237..c7e884e 100644
--- a/indra/newview/skins/default/xui/ko/floater_about.xml
+++ b/indra/newview/skins/default/xui/ko/floater_about.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater name="floater_about" title="세컨드라이프 정보">
 	<text_editor name="credits_editor">
-		세컨드라이프 제작자들: Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, 그 외에 많은 분들이 수고해 주셨습니다.
+		세컨드라이프 제작자들: Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, 그 외에 많은 분들이 수고해 주셨습니다.
 
-  현재 버전이 최상의 버전이 될 수 있도록 도와주신 여러분께 감사드립니다: Aminom Marvin, ava ganache, Balthazar Fouroux, CrystalShard Foo, Davec Horsforth, Drew Dwi, Ellla McMahon, Gellan Glenelg, Harleen Gretzky, istephanija munro, Iustinian Tomsen, JC Glimmer, Joeseph Albanese, kelly young, Latif Khalifa, Lex Neva, McCabe Maxsted, Michi Lumin, moni duettmann, Moon Metty, motor loon, Opensource Obscure, Sky Hye, Soap Clawtooth, velveeta biedermann, zeebster colasanti
+  현재 버전이 최상의 버전이 될 수 있도록 도와주신 여러분께 감사드립니다: afon shepherd, Aimee Trescothick, Alexandrea Fride, Alissa Sabre, Amber DeCuir, Asuka Neely, Auron Forcella, Blue Revolution, Bocan Undercroft, Boroondas Gupte, Brandon Shinobu, Bri Gufler, Buckaroo Mu, Celierra Darling, Christos Atlantis, Coder Kas, Cummere Mayo, dakota schwade, Dirk Talamasca, Dizzy Banjo, Drew Dwi, Duckling Kwak, Ellla McMahon, Erikah Jameson, Erinyse Planer, Eyana Yohkoh, Ezian Ecksol, Faron Karu, Fenoe Lowey, Fox Hwasung, Francisca Biedermann, Gally Young, Gellan Glenelg, Geneko Nemeth, Glenn Rotaru, Hagar Qinan, Harleen Gretzky, Holger Gilruth, hotrodjohnny gears, IAm Zabelin, Inigo Catteneo, Iustinian Tomsen, Jacek Antonell, James Benedek, Jim Kupferberg, Joeseph Albanese, JPT62089 Agnon, Kardargo Adamczyk, Kirstenlee Cinquetti, Latif Khalifa, lea Parnall, Lex Neva, Lillith Anatine, Lilly Zenovka, Lim Catteneo, Lindal Kidd, Mark Rosenbaum, MasterJ Chaplin, McCabe Maxsted, Melvin Starbrook, Meni Kaiousei, Mero Collas, Minakothegothicgeisha Kamachi, Moon Metty, neofilo aabye, Neutron Chesnokov, Nomad Ingwer, norritt Xi, Opensource Obscure, Oracle Weatherwax, Ourasi Ferraris, Pabl0 Roffo, Peyton Aleixandre, Phli Foxchase, Psi Merlin, r2d2 Wunderlich, Regi Yifu, Saijanai Kuhn, Sandor Balczo, Sarkan Dreamscape, Scree Raymaker, Sedona Mills, Selena Beale, Sheet Spotter, Shibari Twine, Silver Key, Simon Kline, SLB Wirefly, Stacy Wombat, Sugarcult Dagger, Tayra Dagostino, Tetsuryu Vlodovic, ThaBiGGDoGG Richez, Timo Gufler, tx Oh, wayfinder wishbringer, Wizzytoe McCullough, Wundur Primbee, Yann Dufaux, Yuu Nakamichi
 
   3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
   APR Copyright (C) 2000-2004 The Apache Software Foundation
diff --git a/indra/newview/skins/default/xui/pt/mime_types.xml b/indra/newview/skins/default/xui/pt/mime_types.xml
index de3d958..be20865 100644
--- a/indra/newview/skins/default/xui/pt/mime_types.xml
+++ b/indra/newview/skins/default/xui/pt/mime_types.xml
@@ -49,7 +49,7 @@
 			Há um audio neste local
 		</tooltip>
 		<playtip name="audio_playtip">
-			Iniciar audio disponípivel nest local
+			Iniciar audio disponível nest local
 		</playtip>
 	</widgetset>
 	<scheme name="rtsp">
diff --git a/indra/newview/skins/default/xui/zh/floater_about.xml b/indra/newview/skins/default/xui/zh/floater_about.xml
index 6fe2b40..8147d89 100644
--- a/indra/newview/skins/default/xui/zh/floater_about.xml
+++ b/indra/newview/skins/default/xui/zh/floater_about.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater name="floater_about" title="关于第二人生">
 	<text_editor name="credits_editor">
-		第二人生的推出应感谢以下人物的贡献: Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ 以及更多人。 
+		第二人生的推出应感谢以下人物的贡献: Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les 以及更多人。 
 
-感谢以下居民,他们的帮助保证了这次第二人生的版本是有史以来最出色的: Aminom Marvin, ava ganache, Balthazar Fouroux, CrystalShard Foo, Davec Horsforth, Drew Dwi, Ellla McMahon, Gellan Glenelg, Harleen Gretzky, istephanija munro, Iustinian Tomsen, JC Glimmer, Joeseph Albanese, kelly young, Latif Khalifa, Lex Neva, McCabe Maxsted, Michi Lumin, moni duettmann, Moon Metty, motor loon, Opensource Obscure, Sky Hye, Soap Clawtooth, velveeta biedermann, zeebster colasanti
+感谢以下居民,他们的帮助保证了这次第二人生的版本是有史以来最出色的: afon shepherd, Aimee Trescothick, Alexandrea Fride, Alissa Sabre, Amber DeCuir, Asuka Neely, Auron Forcella, Blue Revolution, Bocan Undercroft, Boroondas Gupte, Brandon Shinobu, Bri Gufler, Buckaroo Mu, Celierra Darling, Christos Atlantis, Coder Kas, Cummere Mayo, dakota schwade, Dirk Talamasca, Dizzy Banjo, Drew Dwi, Duckling Kwak, Ellla McMahon, Erikah Jameson, Erinyse Planer, Eyana Yohkoh, Ezian Ecksol, Faron Karu, Fenoe Lowey, Fox Hwasung, Francisca Biedermann, Gally Young, Gellan Glenelg, Geneko Nemeth, Glenn Rotaru, Hagar Qinan, Harleen Gretzky, Holger Gilruth, hotrodjohnny gears, IAm Zabelin, Inigo Catteneo, Iustinian Tomsen, Jacek Antonell, James Benedek, Jim Kupferberg, Joeseph Albanese, JPT62089 Agnon, Kardargo Adamczyk, Kirstenlee Cinquetti, Latif Khalifa, lea Parnall, Lex Neva, Lillith Anatine, Lilly Zenovka, Lim Catteneo, Lindal Kidd, Mark Rosenbaum, MasterJ Chaplin, McCabe Maxsted, Melvin Starbrook, Meni Kaiousei, Mero Collas, Minakothegothicgeisha Kamachi, Moon Metty, neofilo aabye, Neutron Chesnokov, Nomad Ingwer, norritt Xi, Opensource Obscure, Oracle Weatherwax, Ourasi Ferraris, Pabl0 Roffo, Peyton Aleixandre, Phli Foxchase, Psi Merlin, r2d2 Wunderlich, Regi Yifu, Saijanai Kuhn, Sandor Balczo, Sarkan Dreamscape, Scree Raymaker, Sedona Mills, Selena Beale, Sheet Spotter, Shibari Twine, Silver Key, Simon Kline, SLB Wirefly, Stacy Wombat, Sugarcult Dagger, Tayra Dagostino, Tetsuryu Vlodovic, ThaBiGGDoGG Richez, Timo Gufler, tx Oh, wayfinder wishbringer, Wizzytoe McCullough, Wundur Primbee, Yann Dufaux, Yuu Nakamichi
 
 
   3Dconnexion SDK Copyright © 1992-2007 3Dconnexion
diff --git a/scripts/install.py b/scripts/install.py
index 983eb84..f886a6e 100755
--- a/scripts/install.py
+++ b/scripts/install.py
@@ -758,7 +758,9 @@ def _get_platform():
                 # the form os/arch/compiler/compiler_version for the download
                 # and extract stage
                 #this_platform = 'linux/i686/gcc/4.1'
-                this_platform = 'linux32'
+                # NOTE: disabled linux32 as it hasn't been tested well
+                #this_platform = 'linux32'
+                this_platform = this_platform
     return this_platform
 
 def _getuser():

-- 
A client for connecting to 3D metaverses such as Linden Labs Secondlife(tm) and OpenSim grids



More information about the Pkg-games-commits mailing list