diff options
Diffstat (limited to 'indra')
157 files changed, 15523 insertions, 4835 deletions
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 279d577a27..9b836aac5f 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -37,6 +37,7 @@ set(cmake_SOURCE_FILES GLOD.cmake GStreamer010Plugin.cmake GooglePerfTools.cmake + Hunspell.cmake JPEG.cmake LLAddBuildTest.cmake LLAudio.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 394db362b1..9f05c4cff2 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -41,6 +41,7 @@ if(WINDOWS) libeay32.dll libcollada14dom22-d.dll glod.dll + libhunspell.dll ) set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") @@ -53,12 +54,13 @@ if(WINDOWS) libeay32.dll libcollada14dom22.dll glod.dll + libhunspell.dll ) - if(USE_GOOGLE_PERFTOOLS) + if(USE_TCMALLOC) set(debug_files ${debug_files} libtcmalloc_minimal-debug.dll) set(release_files ${release_files} libtcmalloc_minimal.dll) - endif(USE_GOOGLE_PERFTOOLS) + endif(USE_TCMALLOC) if (FMOD) set(debug_files ${debug_files} fmod.dll) @@ -212,11 +214,12 @@ elseif(DARWIN) libexpat.1.5.2.dylib libexpat.dylib libGLOD.dylib - libllqtwebkit.dylib - libminizip.a + libllqtwebkit.dylib + libminizip.a libndofdev.dylib + libhunspell-1.3.0.dylib libexception_handler.dylib - libcollada14dom.dylib + libcollada14dom.dylib ) # fmod is statically linked on darwin @@ -257,24 +260,28 @@ elseif(LINUX) libdb-5.1.so libexpat.so libexpat.so.1 - libglod.so + libglod.so libgmock_main.so libgmock.so.0 libgmodule-2.0.so libgobject-2.0.so libgtest_main.so libgtest.so.0 - libminizip.so + libhunspell-1.3.so.0.0.0 + libminizip.so libopenal.so libopenjpeg.so libssl.so - libtcmalloc_minimal.so libuuid.so.16 libuuid.so.16.0.22 libssl.so.1.0.0 libfontconfig.so.1.4.4 ) + if (USE_TCMALLOC) + set(release_files ${release_files} "libtcmalloc_minimal.so") + endif (USE_TCMALLOC) + if (FMOD) set(release_files ${release_files} "libfmod-3.75.so") endif (FMOD) diff --git a/indra/cmake/FindHUNSPELL.cmake b/indra/cmake/FindHUNSPELL.cmake new file mode 100644 index 0000000000..6faf22959c --- /dev/null +++ b/indra/cmake/FindHUNSPELL.cmake @@ -0,0 +1,38 @@ +# -*- cmake -*- + +# - Find HUNSPELL +# This module defines +# HUNSPELL_INCLUDE_DIR, where to find libhunspell.h, etc. +# HUNSPELL_LIBRARY, the library needed to use HUNSPELL. +# HUNSPELL_FOUND, If false, do not try to use HUNSPELL. + +find_path(HUNSPELL_INCLUDE_DIR hunspell.h + PATH_SUFFIXES hunspell + ) + +set(HUNSPELL_NAMES ${HUNSPELL_NAMES} libhunspell-1.3.0 libhunspell) +find_library(HUNSPELL_LIBRARY + NAMES ${HUNSPELL_NAMES} + ) + +if (HUNSPELL_LIBRARY AND HUNSPELL_INCLUDE_DIR) + set(HUNSPELL_FOUND "YES") +else (HUNSPELL_LIBRARY AND HUNSPELL_INCLUDE_DIR) + set(HUNSPELL_FOUND "NO") +endif (HUNSPELL_LIBRARY AND HUNSPELL_INCLUDE_DIR) + + +if (HUNSPELL_FOUND) + if (NOT HUNSPELL_FIND_QUIETLY) + message(STATUS "Found Hunspell: Library in '${HUNSPELL_LIBRARY}' and header in '${HUNSPELL_INCLUDE_DIR}' ") + endif (NOT HUNSPELL_FIND_QUIETLY) +else (HUNSPELL_FOUND) + if (HUNSPELL_FIND_REQUIRED) + message(FATAL_ERROR " * * *\nCould not find HUNSPELL library! * * *") + endif (HUNSPELL_FIND_REQUIRED) +endif (HUNSPELL_FOUND) + +mark_as_advanced( + HUNSPELL_LIBRARY + HUNSPELL_INCLUDE_DIR + ) diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index d9f91193be..09501e0406 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -1,20 +1,34 @@ # -*- cmake -*- include(Prebuilt) +# If you want to enable or disable TCMALLOC in viewer builds, this is the place. +# set ON or OFF as desired. +set (USE_TCMALLOC ON) + if (STANDALONE) include(FindGooglePerfTools) else (STANDALONE) if (WINDOWS) - use_prebuilt_binary(tcmalloc) - set(TCMALLOC_LIBRARIES - debug libtcmalloc_minimal-debug - optimized libtcmalloc_minimal) + if (USE_TCMALLOC) + use_prebuilt_binary(tcmalloc) + set(TCMALLOC_LIBRARIES + debug libtcmalloc_minimal-debug + optimized libtcmalloc_minimal) + set(TCMALLOC_LINK_FLAGS "/INCLUDE:__tcmalloc") + else (USE_TCMALLOC) + set(TCMALLOC_LIBRARIES) + set(TCMALLOC_LINK_FLAGS) + endif (USE_TCMALLOC) set(GOOGLE_PERFTOOLS_FOUND "YES") endif (WINDOWS) if (LINUX) - use_prebuilt_binary(tcmalloc) - set(TCMALLOC_LIBRARIES - tcmalloc) + if (USE_TCMALLOC) + use_prebuilt_binary(tcmalloc) + set(TCMALLOC_LIBRARIES + tcmalloc) + else (USE_TCMALLOC) + set(TCMALLOC_LIBRARIES) + endif (USE_TCMALLOC) set(PROFILER_LIBRARIES profiler) set(GOOGLE_PERFTOOLS_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) @@ -29,13 +43,19 @@ if (GOOGLE_PERFTOOLS_FOUND) endif (GOOGLE_PERFTOOLS_FOUND) if (WINDOWS) - set(USE_GOOGLE_PERFTOOLS ON) + set(USE_GOOGLE_PERFTOOLS ON) endif (WINDOWS) if (USE_GOOGLE_PERFTOOLS) - set(TCMALLOC_FLAG -ULL_USE_TCMALLOC=1) + if (USE_TCMALLOC) + set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1) + else (USE_TCMALLOC) + set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) + endif (USE_TCMALLOC) +endif (USE_GOOGLE_PERFTOOLS) + +if (USE_GOOGLE_PERFTOOLS) include_directories(${GOOGLE_PERFTOOLS_INCLUDE_DIR}) set(GOOGLE_PERFTOOLS_LIBRARIES ${TCMALLOC_LIBRARIES} ${STACKTRACE_LIBRARIES} ${PROFILER_LIBRARIES}) else (USE_GOOGLE_PERFTOOLS) - set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) endif (USE_GOOGLE_PERFTOOLS) diff --git a/indra/cmake/Hunspell.cmake b/indra/cmake/Hunspell.cmake new file mode 100644 index 0000000000..0c9cf93316 --- /dev/null +++ b/indra/cmake/Hunspell.cmake @@ -0,0 +1,22 @@ +# -*- cmake -*- +include(Prebuilt) + +set(HUNSPELL_FIND_QUIETLY ON) +set(HUNSPELL_FIND_REQUIRED ON) + +if (STANDALONE) + include(FindHUNSPELL) +else (STANDALONE) + use_prebuilt_binary(libhunspell) + if (WINDOWS) + set(HUNSPELL_LIBRARY libhunspell) + elseif(DARWIN) + set(HUNSPELL_LIBRARY hunspell-1.3.0) + elseif(LINUX) + set(HUNSPELL_LIBRARY hunspell-1.3) + else() + message(FATAL_ERROR "Invalid platform") + endif() + set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell) + use_prebuilt_binary(dictionaries) +endif (STANDALONE) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 08feab6e36..a6f69a09e9 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -205,6 +205,15 @@ FUNCTION(LL_ADD_INTEGRATION_TEST SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}") endif(STANDALONE) + if (WINDOWS) + SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} + PROPERTIES + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_LINK_FLAGS}" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO" + LINK_FLAGS_RELEASE "" + ) + endif (WINDOWS) + # Add link deps to the executable if(TEST_DEBUG) message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})") diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake index df013b1665..f907181929 100644 --- a/indra/cmake/ViewerMiscLibs.cmake +++ b/indra/cmake/ViewerMiscLibs.cmake @@ -2,6 +2,7 @@ include(Prebuilt) if (NOT STANDALONE) + use_prebuilt_binary(libhunspell) use_prebuilt_binary(libuuid) use_prebuilt_binary(slvoice) use_prebuilt_binary(fontconfig) diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt index 633ad84159..91c9f20c10 100644 --- a/indra/integration_tests/llui_libtest/CMakeLists.txt +++ b/indra/integration_tests/llui_libtest/CMakeLists.txt @@ -18,6 +18,7 @@ include(LLWindow) include(LLUI) include(LLVFS) # ugh, needed for LLDir include(LLXML) +include(Hunspell) include(Linking) # include(Tut) @@ -31,6 +32,7 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} + ${LIBS_PREBUILD_DIR}/include/hunspell ) set(llui_libtest_SOURCE_FILES @@ -78,6 +80,7 @@ target_link_libraries(llui_libtest ${LLIMAGEJ2COJ_LIBRARIES} ${OS_LIBRARIES} ${GOOGLE_PERFTOOLS_LIBRARIES} + ${HUNSPELL_LIBRARY} ) if (WINDOWS) diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp index 6f6abefc67..87654b5b97 100644 --- a/indra/llcommon/llallocator.cpp +++ b/indra/llcommon/llallocator.cpp @@ -27,7 +27,7 @@ #include "linden_common.h" #include "llallocator.h" -#if LL_USE_TCMALLOC +#if (LL_USE_TCMALLOC && LL_USE_HEAP_PROFILER) #include "google/heap-profiler.h" #include "google/commandlineflags_public.h" diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 3b9758f996..afaf366668 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -61,6 +61,18 @@ BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE; LLPrivateMemoryPoolManager::mem_allocation_info_t LLPrivateMemoryPoolManager::sMemAllocationTracker; #endif +void ll_assert_aligned_func(uintptr_t ptr,U32 alignment) +{ +#ifdef SHOW_ASSERT + // Redundant, place to set breakpoints. + if (ptr%alignment!=0) + { + llwarns << "alignment check failed" << llendl; + } + llassert(ptr%alignment==0); +#endif +} + //static void LLMemory::initClass() { diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index bbbdaa6497..9dd776ff57 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -27,7 +27,6 @@ #define LLMEMORY_H #include "llmemtype.h" -#if LL_DEBUG inline void* ll_aligned_malloc( size_t size, int align ) { void* mem = malloc( size + (align - 1) + sizeof(void*) ); @@ -43,10 +42,11 @@ inline void ll_aligned_free( void* ptr ) free( ((void**)ptr)[-1] ); } +#if !LL_USE_TCMALLOC inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). { #if defined(LL_WINDOWS) - return _mm_malloc(size, 16); + return _aligned_malloc(size, 16); #elif defined(LL_DARWIN) return malloc(size); // default osx malloc is 16 byte aligned. #else @@ -58,21 +58,38 @@ inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed wi #endif } +inline void* ll_aligned_realloc_16(void* ptr, size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). +{ +#if defined(LL_WINDOWS) + return _aligned_realloc(ptr, size, 16); +#elif defined(LL_DARWIN) + return realloc(ptr,size); // default osx malloc is 16 byte aligned. +#else + return realloc(ptr,size); // FIXME not guaranteed to be aligned. +#endif +} + inline void ll_aligned_free_16(void *p) { #if defined(LL_WINDOWS) - _mm_free(p); + _aligned_free(p); #elif defined(LL_DARWIN) return free(p); #else free(p); // posix_memalign() is compatible with heap deallocator #endif } +#else // USE_TCMALLOC +// ll_aligned_foo_16 are not needed with tcmalloc +#define ll_aligned_malloc_16 malloc +#define ll_aligned_realloc_16 realloc +#define ll_aligned_free_16 free +#endif // USE_TCMALLOC inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32(). { #if defined(LL_WINDOWS) - return _mm_malloc(size, 32); + return _aligned_malloc(size, 32); #elif defined(LL_DARWIN) return ll_aligned_malloc( size, 32 ); #else @@ -87,22 +104,13 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi inline void ll_aligned_free_32(void *p) { #if defined(LL_WINDOWS) - _mm_free(p); + _aligned_free(p); #elif defined(LL_DARWIN) ll_aligned_free( p ); #else free(p); // posix_memalign() is compatible with heap deallocator #endif } -#else // LL_DEBUG -// ll_aligned_foo are noops now that we use tcmalloc everywhere (tcmalloc aligns automatically at appropriate intervals) -#define ll_aligned_malloc( size, align ) malloc(size) -#define ll_aligned_free( ptr ) free(ptr) -#define ll_aligned_malloc_16 malloc -#define ll_aligned_free_16 free -#define ll_aligned_malloc_32 malloc -#define ll_aligned_free_32 free -#endif // LL_DEBUG #ifndef __DEBUG_PRIVATE_MEM__ #define __DEBUG_PRIVATE_MEM__ 0 @@ -512,4 +520,13 @@ void LLPrivateMemoryPoolTester::operator delete[](void* addr) // LLSingleton moved to llsingleton.h +LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); + +#ifdef SHOW_ASSERT +#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment)) +#else +#define ll_assert_aligned(ptr,alignment) +#endif + + #endif diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 09733e8e2a..119efc7957 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -183,6 +183,9 @@ public: static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; } static bool isPunct(llwchar a) { return iswpunct(a) != 0; } + static bool isAlpha(char a) { return isalpha((unsigned char)a) != 0; } + static bool isAlpha(llwchar a) { return iswalpha(a) != 0; } + static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; } static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index bfb30f900f..9af16a0ed8 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@ const S32 LL_VERSION_MAJOR = 3; const S32 LL_VERSION_MINOR = 3; -const S32 LL_VERSION_PATCH = 3; +const S32 LL_VERSION_PATCH = 5; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index e36d0b20d2..f0b2caca3d 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -45,7 +45,7 @@ const S32 PARCEL_UNIT_AREA = 16; const F32 PARCEL_HEIGHT = 50.f; //Height above ground which parcel boundries exist for explicitly banned avatars -const F32 BAN_HEIGHT = 768.f; +const F32 BAN_HEIGHT = 5000.f; // Maximum number of entries in an access list const S32 PARCEL_MAX_ACCESS_LIST = 300; diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index b5e59c1ca3..5865ae030c 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -117,6 +117,7 @@ if (LL_TESTS) # INTEGRATION TESTS set(test_libs llmath llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests. + LL_ADD_INTEGRATION_TEST(alignment "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llbbox llbbox.cpp "${test_libs}") LL_ADD_INTEGRATION_TEST(llquaternion llquaternion.cpp "${test_libs}") LL_ADD_INTEGRATION_TEST(mathmisc "" "${test_libs}") diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index ec67b91d05..0b591be622 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -60,7 +60,7 @@ static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD; // roll(), pitch(), yaw() // etc... - +LL_ALIGN_PREFIX(16) class LLCamera : public LLCoordFrame { @@ -108,7 +108,7 @@ public: }; private: - LLPlane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP + LL_ALIGN_16(LLPlane mAgentPlanes[7]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP U8 mPlaneMask[8]; // 8 for alignment F32 mView; // angle between top and bottom frustum planes in radians. @@ -116,13 +116,13 @@ private: S32 mViewHeightInPixels; // for ViewHeightInPixels() only F32 mNearPlane; F32 mFarPlane; - LLPlane mLocalPlanes[4]; + LL_ALIGN_16(LLPlane mLocalPlanes[4]); F32 mFixedDistance; // Always return this distance, unless < 0 LLVector3 mFrustCenter; // center of frustum and radius squared for ultra-quick exclusion test F32 mFrustRadiusSquared; - LLPlane mWorldPlanes[PLANE_NUM]; - LLPlane mHorizPlanes[HORIZ_PLANE_NUM]; + LL_ALIGN_16(LLPlane mWorldPlanes[PLANE_NUM]); + LL_ALIGN_16(LLPlane mHorizPlanes[HORIZ_PLANE_NUM]); U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in @@ -208,7 +208,7 @@ protected: void calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom); void calculateFrustumPlanesFromWindow(F32 x1, F32 y1, F32 x2, F32 y2); void calculateWorldFrustumPlanes(); -}; +} LL_ALIGN_POSTFIX(16); #endif diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 9297bcbac2..b93f89d674 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -85,7 +85,7 @@ const F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO; const F32 FP_MAG_THRESHOLD = 0.0000001f; // TODO: Replace with logic like is_approx_equal -inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); } +inline bool is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); } // These functions work by interpreting sign+exp+mantissa as an unsigned // integer. @@ -111,13 +111,13 @@ inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < // WARNING: Infinity is comparable with F32_MAX and negative // infinity is comparable with F32_MIN -inline BOOL is_approx_equal(F32 x, F32 y) +inline bool is_approx_equal(F32 x, F32 y) { const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02; return (std::abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); } -inline BOOL is_approx_equal(F64 x, F64 y) +inline bool is_approx_equal(F64 x, F64 y) { const S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; return (std::abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); diff --git a/indra/llmath/llmatrix3a.h b/indra/llmath/llmatrix3a.h index adb7e3389d..9916cfd2da 100644 --- a/indra/llmath/llmatrix3a.h +++ b/indra/llmath/llmatrix3a.h @@ -111,7 +111,7 @@ public: protected: - LLVector4a mColumns[3]; + LL_ALIGN_16(LLVector4a mColumns[3]); }; diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index 27cf5b79f6..c4cefdb4fa 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -34,7 +34,7 @@ class LLMatrix4a { public: - LLVector4a mMatrix[4]; + LL_ALIGN_16(LLVector4a mMatrix[4]); inline void clear() { diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 6c768863a6..c3f6f7de2a 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -89,7 +89,7 @@ public: typedef LLOctreeNode<T> oct_node; typedef LLOctreeListener<T> oct_listener; - /*void* operator new(size_t size) + void* operator new(size_t size) { return ll_aligned_malloc_16(size); } @@ -97,7 +97,7 @@ public: void operator delete(void* ptr) { ll_aligned_free_16(ptr); - }*/ + } LLOctreeNode( const LLVector4a& center, const LLVector4a& size, diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h index a611894721..3c32441b11 100644 --- a/indra/llmath/llplane.h +++ b/indra/llmath/llplane.h @@ -36,6 +36,8 @@ // The plane normal = [A, B, C] // The closest approach = D / sqrt(A*A + B*B + C*C) + +LL_ALIGN_PREFIX(16) class LLPlane { public: @@ -94,7 +96,7 @@ public: private: LLVector4a mV; -}; +} LL_ALIGN_POSTFIX(16); diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h index c7cdf7b32c..01458521ec 100644 --- a/indra/llmath/llsimdmath.h +++ b/indra/llmath/llsimdmath.h @@ -67,11 +67,10 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) #define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) - - #include <xmmintrin.h> #include <emmintrin.h> +#include "llmemory.h" #include "llsimdtypes.h" #include "llsimdtypes.inl" diff --git a/indra/llmath/llsimdtypes.inl b/indra/llmath/llsimdtypes.inl index 712239e425..e905c84954 100644 --- a/indra/llmath/llsimdtypes.inl +++ b/indra/llmath/llsimdtypes.inl @@ -62,6 +62,7 @@ inline LLSimdScalar operator/(const LLSimdScalar& a, const LLSimdScalar& b) inline LLSimdScalar operator-(const LLSimdScalar& a) { static LL_ALIGN_16(const U32 signMask[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + ll_assert_aligned(signMask,16); return _mm_xor_ps(*reinterpret_cast<const LLQuad*>(signMask), a); } @@ -146,6 +147,7 @@ inline LLSimdScalar& LLSimdScalar::operator/=(const LLSimdScalar& rhs) inline LLSimdScalar LLSimdScalar::getAbs() const { static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; + ll_assert_aligned(F_ABS_MASK_4A,16); return _mm_and_ps( mQ, *reinterpret_cast<const LLQuad*>(F_ABS_MASK_4A)); } diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp index b66b7a7076..6edeb0fefe 100644 --- a/indra/llmath/llvector4a.cpp +++ b/indra/llmath/llvector4a.cpp @@ -24,6 +24,7 @@ * $/LicenseInfo$ */ +#include "llmemory.h" #include "llmath.h" #include "llquantize.h" @@ -44,7 +45,10 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast<const LLVector4a&> ( F assert(dst != NULL); assert(bytes > 0); assert((bytes % sizeof(F32))== 0); - + ll_assert_aligned(src,16); + ll_assert_aligned(dst,16); + assert(bytes%16==0); + F32* end = dst + (bytes / sizeof(F32) ); if (bytes > 64) @@ -189,6 +193,8 @@ void LLVector4a::quantize16( const LLVector4a& low, const LLVector4a& high ) LLVector4a oneOverDelta; { static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; + ll_assert_aligned(F_TWO_4A,16); + LLVector4a two; two.load4a( F_TWO_4A ); // Here we use _mm_rcp_ps plus one round of newton-raphson diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h index 596082509d..0526793d3a 100644 --- a/indra/llmath/llvector4a.h +++ b/indra/llmath/llvector4a.h @@ -32,6 +32,7 @@ class LLRotation; #include <assert.h> #include "llpreprocessor.h" +#include "llmemory.h" /////////////////////////////////// // FIRST TIME USERS PLEASE READ @@ -46,6 +47,7 @@ class LLRotation; // LLVector3/LLVector4. ///////////////////////////////// +LL_ALIGN_PREFIX(16) class LLVector4a { public: @@ -82,6 +84,7 @@ public: } // Copy words 16-byte blocks from src to dst. Source and destination must not overlap. + // Source and dest must be 16-byte aligned and size must be multiple of 16. static void memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes); //////////////////////////////////// @@ -90,6 +93,7 @@ public: LLVector4a() { //DO NOT INITIALIZE -- The overhead is completely unnecessary + ll_assert_aligned(this,16); } LLVector4a(F32 x, F32 y, F32 z, F32 w = 0.f) @@ -313,7 +317,7 @@ public: private: LLQuad mQ; -}; +} LL_ALIGN_POSTFIX(16); inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p) { diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl index 7ad22a5631..7c52ffef21 100644 --- a/indra/llmath/llvector4a.inl +++ b/indra/llmath/llvector4a.inl @@ -475,6 +475,7 @@ inline void LLVector4a::setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F3 inline LLBool32 LLVector4a::isFinite3() const { static LL_ALIGN_16(const U32 nanOrInfMask[4]) = { 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 }; + ll_assert_aligned(nanOrInfMask,16); const __m128i nanOrInfMaskV = *reinterpret_cast<const __m128i*> (nanOrInfMask); const __m128i maskResult = _mm_and_si128( _mm_castps_si128(mQ), nanOrInfMaskV ); const LLVector4Logical equalityCheck = _mm_castsi128_ps(_mm_cmpeq_epi32( maskResult, nanOrInfMaskV )); diff --git a/indra/llmath/llvector4logical.h b/indra/llmath/llvector4logical.h index dd66b09d43..c5698f7cea 100644 --- a/indra/llmath/llvector4logical.h +++ b/indra/llmath/llvector4logical.h @@ -27,6 +27,7 @@ #ifndef LL_VECTOR4LOGICAL_H #define LL_VECTOR4LOGICAL_H +#include "llmemory.h" //////////////////////////// // LLVector4Logical @@ -77,6 +78,7 @@ public: inline LLVector4Logical& invert() { static const LL_ALIGN_16(U32 allOnes[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + ll_assert_aligned(allOnes,16); mQ = _mm_andnot_ps( mQ, *(LLQuad*)(allOnes) ); return *this; } diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 06ac0aa1f6..53d56e96da 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -95,17 +95,6 @@ const S32 SCULPT_MIN_AREA_DETAIL = 1; extern BOOL gDebugGL; -void assert_aligned(void* ptr, uintptr_t alignment) -{ -#if 0 - uintptr_t t = (uintptr_t) ptr; - if (t%alignment != 0) - { - llerrs << "Alignment check failed." << llendl; - } -#endif -} - BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) { LLVector3 test = (pt2-pt1)%(pt3-pt2); @@ -6962,14 +6951,14 @@ void LLVolumeFace::resizeVertices(S32 num_verts) if (num_verts) { mPositions = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); - assert_aligned(mPositions, 16); + ll_assert_aligned(mPositions, 16); mNormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); - assert_aligned(mNormals, 16); + ll_assert_aligned(mNormals, 16); //pad texture coordinate block end to allow for QWORD reads S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; mTexCoords = (LLVector2*) ll_aligned_malloc_16(size); - assert_aligned(mTexCoords, 16); + ll_assert_aligned(mTexCoords, 16); } else { @@ -6993,14 +6982,17 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con // S32 old_size = mNumVertices*16; //positions - mPositions = (LLVector4a*) realloc(mPositions, new_size); + mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_size); + ll_assert_aligned(mPositions,16); //normals - mNormals = (LLVector4a*) realloc(mNormals, new_size); - + mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_size); + ll_assert_aligned(mNormals,16); + //tex coords new_size = ((new_verts*8)+0xF) & ~0xF; - mTexCoords = (LLVector2*) realloc(mTexCoords, new_size); + mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, new_size); + ll_assert_aligned(mTexCoords,16); //just clear binormals @@ -7053,7 +7045,8 @@ void LLVolumeFace::pushIndex(const U16& idx) S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; if (new_size != old_size) { - mIndices = (U16*) realloc(mIndices, new_size); + mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size); + ll_assert_aligned(mIndices,16); } mIndices[mNumIndices++] = idx; @@ -7094,12 +7087,12 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat } //allocate new buffer space - mPositions = (LLVector4a*) realloc(mPositions, new_count*sizeof(LLVector4a)); - assert_aligned(mPositions, 16); - mNormals = (LLVector4a*) realloc(mNormals, new_count*sizeof(LLVector4a)); - assert_aligned(mNormals, 16); - mTexCoords = (LLVector2*) realloc(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF); - assert_aligned(mTexCoords, 16); + mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_count*sizeof(LLVector4a)); + ll_assert_aligned(mPositions, 16); + mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_count*sizeof(LLVector4a)); + ll_assert_aligned(mNormals, 16); + mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF); + ll_assert_aligned(mTexCoords, 16); mNumVertices = new_count; @@ -7145,7 +7138,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat new_count = mNumIndices + face.mNumIndices; //allocate new index buffer - mIndices = (U16*) realloc(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF); + mIndices = (U16*) ll_aligned_realloc_16(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF); //get destination address into new index buffer U16* dst_idx = mIndices+mNumIndices; diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index ed54fe0835..9ae34a0c4e 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -37,6 +37,16 @@ class LLVolumeTriangle : public LLRefCount { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVolumeTriangle() { mBinIndex = -1; @@ -58,7 +68,7 @@ public: } - LLVector4a mPositionGroup; + LL_ALIGN_16(LLVector4a mPositionGroup); const LLVector4a* mV[3]; U16 mIndex[3]; @@ -80,6 +90,16 @@ class LLVolumeOctreeListener : public LLOctreeListener<LLVolumeTriangle> { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node); ~LLVolumeOctreeListener(); @@ -106,8 +126,8 @@ public: public: - LLVector4a mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects) - LLVector4a mExtents[2]; // extents (min, max) of this node and all its children + LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) + LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children }; class LLOctreeTriangleRayIntersect : public LLOctreeTraveler<LLVolumeTriangle> diff --git a/indra/llmath/tests/alignment_test.cpp b/indra/llmath/tests/alignment_test.cpp new file mode 100644 index 0000000000..ac0c45ae6f --- /dev/null +++ b/indra/llmath/tests/alignment_test.cpp @@ -0,0 +1,128 @@ +/** + * @file v3dmath_test.cpp + * @author Vir + * @date 2011-12 + * @brief v3dmath test cases. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +// Tests related to allocating objects with alignment constraints, particularly for SSE support. + +#include "linden_common.h" +#include "../test/lltut.h" +#include "../llmath.h" +#include "../llsimdmath.h" +#include "../llvector4a.h" + +void* operator new(size_t size) +{ + return ll_aligned_malloc_16(size); +} + +void operator delete(void *p) +{ + ll_aligned_free_16(p); +} + +namespace tut +{ + +#define is_aligned(ptr,alignment) ((reinterpret_cast<uintptr_t>(ptr))%(alignment)==0) +#define is_aligned_relative(ptr,base_ptr,alignment) ((reinterpret_cast<uintptr_t>(ptr)-reinterpret_cast<uintptr_t>(base_ptr))%(alignment)==0) + +struct alignment_test {}; + +typedef test_group<alignment_test> alignment_test_t; +typedef alignment_test_t::object alignment_test_object_t; +tut::alignment_test_t tut_alignment_test("LLAlignment"); + +LL_ALIGN_PREFIX(16) +class MyVector4a +{ + LLQuad mQ; +} LL_ALIGN_POSTFIX(16); + + +// Verify that aligned allocators perform as advertised. +template<> template<> +void alignment_test_object_t::test<1>() +{ +# ifdef LL_DEBUG + skip("This test fails on Windows when compiled in debug mode."); +# endif + + const int num_tests = 7; + void *align_ptr; + for (int i=0; i<num_tests; i++) + { + align_ptr = ll_aligned_malloc_16(sizeof(MyVector4a)); + ensure("ll_aligned_malloc_16 failed", is_aligned(align_ptr,16)); + + align_ptr = ll_aligned_realloc_16(align_ptr,2*sizeof(MyVector4a)); + ensure("ll_aligned_realloc_16 failed", is_aligned(align_ptr,16)); + + ll_aligned_free_16(align_ptr); + + align_ptr = ll_aligned_malloc_32(sizeof(MyVector4a)); + ensure("ll_aligned_malloc_32 failed", is_aligned(align_ptr,32)); + ll_aligned_free_32(align_ptr); + } +} + +// In-place allocation of objects and arrays. +template<> template<> +void alignment_test_object_t::test<2>() +{ + MyVector4a vec1; + ensure("LLAlignment vec1 unaligned", is_aligned(&vec1,16)); + + MyVector4a veca[12]; + ensure("LLAlignment veca unaligned", is_aligned(veca,16)); +} + +// Heap allocation of objects and arrays. +template<> template<> +void alignment_test_object_t::test<3>() +{ +# ifdef LL_DEBUG + skip("This test fails on Windows when compiled in debug mode."); +# endif + + const int ARR_SIZE = 7; + for(int i=0; i<ARR_SIZE; i++) + { + MyVector4a *vecp = new MyVector4a; + ensure("LLAlignment vecp unaligned", is_aligned(vecp,16)); + delete vecp; + } + + MyVector4a *veca = new MyVector4a[ARR_SIZE]; + ensure("LLAligment veca base", is_aligned(veca,16)); + for(int i=0; i<ARR_SIZE; i++) + { + std::cout << "veca[" << i << "]" << std::endl; + ensure("LLAlignment veca member unaligned", is_aligned(&veca[i],16)); + } +} + +} diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index cb32a510b8..28ed051c55 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1026,7 +1026,8 @@ void LLModel::setVolumeFaceData( if (tc.get()) { - LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32)); + U32 tex_size = (num_verts*2*sizeof(F32)+0xF)&~0xF; + LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), tex_size); } else { diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index fccbf37a8d..4dc2fcd714 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -422,6 +422,16 @@ S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y } // font metrics - override for LLFontFreetype that returns units of virtual pixels +F32 LLFontGL::getAscenderHeight() const +{ + return mFontFreetype->getAscenderHeight() / sScaleY; +} + +F32 LLFontGL::getDescenderHeight() const +{ + return mFontFreetype->getDescenderHeight() / sScaleY; +} + S32 LLFontGL::getLineHeight() const { return llceil(mFontFreetype->getAscenderHeight() / sScaleY) + llceil(mFontFreetype->getDescenderHeight() / sScaleY); diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 74bdbb43e7..5ed5d2c4eb 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -115,6 +115,8 @@ public: S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const; // font metrics - override for LLFontFreetype that returns units of virtual pixels + F32 getAscenderHeight() const; + F32 getDescenderHeight() const; S32 getLineHeight() const; S32 getWidth(const std::string& utf8text) const; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 0092df6587..ece794b7f1 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -286,10 +286,12 @@ void LLVBOPool::seedPool() allocate(dummy_name, size, true); } } + } } } + void LLVBOPool::cleanup() { U32 size = LL_VBO_BLOCK_SIZE; diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 20c3456a56..cca4ca3981 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -23,6 +23,7 @@ include_directories( ${LLWINDOW_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} + ${LIBS_PREBUILD_DIR}/include/hunspell ) set(llui_SOURCE_FILES @@ -84,6 +85,7 @@ set(llui_SOURCE_FILES llsearcheditor.cpp llslider.cpp llsliderctrl.cpp + llspellcheck.cpp llspinctrl.cpp llstatbar.cpp llstatgraph.cpp @@ -191,6 +193,8 @@ set(llui_HEADER_FILES llscrolllistitem.h llsliderctrl.h llslider.h + llspellcheck.h + llspellcheckmenuhandler.h llspinctrl.h llstatbar.h llstatgraph.h @@ -260,6 +264,7 @@ target_link_libraries(llui ${LLXUIXML_LIBRARIES} ${LLXML_LIBRARIES} ${LLMATH_LIBRARIES} + ${HUNSPELL_LIBRARY} ${LLCOMMON_LIBRARIES} # must be after llimage, llwindow, llrender ) diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index d0fbf4b913..48d49af588 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -45,6 +45,7 @@ #include "llkeyboard.h" #include "llrect.h" #include "llresmgr.h" +#include "llspellcheck.h" #include "llstring.h" #include "llwindow.h" #include "llui.h" @@ -65,6 +66,7 @@ const S32 SCROLL_INCREMENT_ADD = 0; // make space for typing const S32 SCROLL_INCREMENT_DEL = 4; // make space for baskspacing const F32 AUTO_SCROLL_TIME = 0.05f; const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. *TODO: make this equal to the double click interval? +const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on const std::string PASSWORD_ASTERISK( "\xE2\x80\xA2" ); // U+2022 BULLET @@ -88,6 +90,7 @@ LLLineEditor::Params::Params() background_image_focused("background_image_focused"), select_on_focus("select_on_focus", false), revert_on_esc("revert_on_esc", true), + spellcheck("spellcheck", false), commit_on_focus_lost("commit_on_focus_lost", true), ignore_tab("ignore_tab", true), is_password("is_password", false), @@ -134,6 +137,9 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mIgnoreArrowKeys( FALSE ), mIgnoreTab( p.ignore_tab ), mDrawAsterixes( p.is_password ), + mSpellCheck( p.spellcheck ), + mSpellCheckStart(-1), + mSpellCheckEnd(-1), mSelectAllonFocusReceived( p.select_on_focus ), mSelectAllonCommit( TRUE ), mPassDelete(FALSE), @@ -151,7 +157,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mHighlightColor(p.highlight_color()), mPreeditBgColor(p.preedit_bg_color()), mGLFont(p.font), - mContextMenuHandle() + mContextMenuHandle(), + mAutoreplaceCallback() { llassert( mMaxLengthBytes > 0 ); @@ -177,6 +184,12 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) updateTextPadding(); setCursor(mText.length()); + if (mSpellCheck) + { + LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLLineEditor::onSpellCheckSettingsChange, this)); + } + mSpellCheckTimer.reset(); + setPrevalidateInput(p.prevalidate_input_callback()); setPrevalidate(p.prevalidate_callback()); @@ -195,7 +208,6 @@ LLLineEditor::~LLLineEditor() gFocusMgr.releaseFocusIfNeeded( this ); } - void LLLineEditor::onFocusReceived() { gEditMenuHandler = this; @@ -519,6 +531,99 @@ void LLLineEditor::selectAll() updatePrimary(); } +bool LLLineEditor::getSpellCheck() const +{ + return (LLSpellChecker::getUseSpellCheck()) && (!mReadOnly) && (mSpellCheck); +} + +const std::string& LLLineEditor::getSuggestion(U32 index) const +{ + return (index < mSuggestionList.size()) ? mSuggestionList[index] : LLStringUtil::null; +} + +U32 LLLineEditor::getSuggestionCount() const +{ + return mSuggestionList.size(); +} + +void LLLineEditor::replaceWithSuggestion(U32 index) +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) + { + deselect(); + + // Delete the misspelled word + mText.erase(it->first, it->second - it->first); + + // Insert the suggestion in its place + LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); + mText.insert(it->first, suggestion); + setCursor(it->first + (S32)suggestion.length()); + + break; + } + } + mSpellCheckStart = mSpellCheckEnd = -1; +} + +void LLLineEditor::addToDictionary() +{ + if (canAddToDictionary()) + { + LLSpellChecker::instance().addToCustomDictionary(getMisspelledWord(mCursorPos)); + } +} + +bool LLLineEditor::canAddToDictionary() const +{ + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); +} + +void LLLineEditor::addToIgnore() +{ + if (canAddToIgnore()) + { + LLSpellChecker::instance().addToIgnoreList(getMisspelledWord(mCursorPos)); + } +} + +bool LLLineEditor::canAddToIgnore() const +{ + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); +} + +std::string LLLineEditor::getMisspelledWord(U32 pos) const +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + { + return wstring_to_utf8str(mText.getWString().substr(it->first, it->second - it->first)); + } + } + return LLStringUtil::null; +} + +bool LLLineEditor::isMisspelledWord(U32 pos) const +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + { + return true; + } + } + return false; +} + +void LLLineEditor::onSpellCheckSettingsChange() +{ + // Recheck the spelling on every change + mMisspellRanges.clear(); + mSpellCheckStart = mSpellCheckEnd = -1; +} BOOL LLLineEditor::handleDoubleClick(S32 x, S32 y, MASK mask) { @@ -866,6 +971,12 @@ void LLLineEditor::addChar(const llwchar uni_char) LLUI::reportBadKeystroke(); } + if (!mReadOnly && mAutoreplaceCallback != NULL) + { + // call callback + mAutoreplaceCallback(mText, mCursorPos); + } + getWindow()->hideCursorUntilMouseMove(); } @@ -1058,9 +1169,8 @@ void LLLineEditor::cut() LLUI::reportBadKeystroke(); } else - if( mKeystrokeCallback ) { - mKeystrokeCallback( this ); + onKeystroke(); } } } @@ -1187,9 +1297,8 @@ void LLLineEditor::pasteHelper(bool is_primary) LLUI::reportBadKeystroke(); } else - if( mKeystrokeCallback ) { - mKeystrokeCallback( this ); + onKeystroke(); } } } @@ -1442,9 +1551,10 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask ) // Notify owner if requested if (!need_to_rollback && handled) { - if (mKeystrokeCallback) + onKeystroke(); + if ( (!selection_modified) && (KEY_BACKSPACE == key) ) { - mKeystrokeCallback(this); + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } } } @@ -1497,12 +1607,11 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char) // Notify owner if requested if( !need_to_rollback && handled ) { - if( mKeystrokeCallback ) - { - // HACK! The only usage of this callback doesn't do anything with the character. - // We'll have to do something about this if something ever changes! - Doug - mKeystrokeCallback( this ); - } + // HACK! The only usage of this callback doesn't do anything with the character. + // We'll have to do something about this if something ever changes! - Doug + onKeystroke(); + + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } } return handled; @@ -1531,9 +1640,7 @@ void LLLineEditor::doDelete() if (!prevalidateInput(text_to_delete)) { - if( mKeystrokeCallback ) - mKeystrokeCallback( this ); - + onKeystroke(); return; } setCursor(getCursor() + 1); @@ -1549,10 +1656,9 @@ void LLLineEditor::doDelete() } else { - if( mKeystrokeCallback ) - { - mKeystrokeCallback( this ); - } + onKeystroke(); + + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } } } @@ -1624,6 +1730,10 @@ void LLLineEditor::draw() background.stretch( -mBorderThickness ); S32 lineeditor_v_pad = (background.getHeight() - mGLFont->getLineHeight()) / 2; + if (mSpellCheck) + { + lineeditor_v_pad += 1; + } drawBackground(); @@ -1698,14 +1808,14 @@ void LLLineEditor::draw() { S32 select_left; S32 select_right; - if( mSelectionStart < getCursor() ) + if (mSelectionStart < mSelectionEnd) { select_left = mSelectionStart; - select_right = getCursor(); + select_right = mSelectionEnd; } else { - select_left = getCursor(); + select_left = mSelectionEnd; select_right = mSelectionStart; } @@ -1749,7 +1859,7 @@ void LLLineEditor::draw() if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) ) { // unselected, right side - mGLFont->render( + rendered_text += mGLFont->render( mText, mScrollHPos + rendered_text, rendered_pixels_right, text_bottom, text_color, @@ -1763,7 +1873,7 @@ void LLLineEditor::draw() } else { - mGLFont->render( + rendered_text = mGLFont->render( mText, mScrollHPos, rendered_pixels_right, text_bottom, text_color, @@ -1778,6 +1888,101 @@ void LLLineEditor::draw() mBorder->setVisible(FALSE); // no more programmatic art. #endif + if ( (getSpellCheck()) && (mText.length() > 2) ) + { + // Calculate start and end indices for the first and last visible word + U32 start = prevWordPos(mScrollHPos), end = nextWordPos(mScrollHPos + rendered_text); + + if ( (mSpellCheckStart != start) || (mSpellCheckEnd != end) ) + { + const LLWString& text = mText.getWString().substr(start, end); + + // Find the start of the first word + U32 word_start = 0, word_end = 0; + while ( (word_start < text.length()) && (!LLStringOps::isAlpha(text[word_start])) ) + { + word_start++; + } + + // Iterate over all words in the text block and check them one by one + mMisspellRanges.clear(); + while (word_start < text.length()) + { + // Find the end of the current word (special case handling for "'" when it's used as a contraction) + word_end = word_start + 1; + while ( (word_end < text.length()) && + ((LLWStringUtil::isPartOfWord(text[word_end])) || + ((L'\'' == text[word_end]) && (word_end + 1 < text.length()) && + (LLStringOps::isAlnum(text[word_end - 1])) && (LLStringOps::isAlnum(text[word_end + 1])))) ) + { + word_end++; + } + if (word_end > text.length()) + { + break; + } + + // Don't process words shorter than 3 characters + std::string word = wstring_to_utf8str(text.substr(word_start, word_end - word_start)); + if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) ) + { + mMisspellRanges.push_back(std::pair<U32, U32>(start + word_start, start + word_end)); + } + + // Find the start of the next word + word_start = word_end + 1; + while ( (word_start < text.length()) && (!LLWStringUtil::isPartOfWord(text[word_start])) ) + { + word_start++; + } + } + + mSpellCheckStart = start; + mSpellCheckEnd = end; + } + + // Draw squiggly lines under any (visible) misspelled words + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + // Skip over words that aren't (partially) visible + if ( ((it->first < start) && (it->second < start)) || (it->first > end) ) + { + continue; + } + + // Skip the current word if the user is still busy editing it + if ( (!mSpellCheckTimer.hasExpired()) && (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) + { + continue; + } + + S32 pxWidth = getRect().getWidth(); + S32 pxStart = findPixelNearestPos(it->first - getCursor()); + if (pxStart > pxWidth) + { + continue; + } + S32 pxEnd = findPixelNearestPos(it->second - getCursor()); + if (pxEnd > pxWidth) + { + pxEnd = pxWidth; + } + + S32 pxBottom = (S32)(text_bottom + mGLFont->getDescenderHeight()); + + gGL.color4ub(255, 0, 0, 200); + while (pxStart + 1 < pxEnd) + { + gl_line_2d(pxStart, pxBottom, pxStart + 2, pxBottom - 2); + if (pxStart + 3 < pxEnd) + { + gl_line_2d(pxStart + 2, pxBottom - 3, pxStart + 4, pxBottom - 1); + } + pxStart += 4; + } + } + } + // If we're editing... if( hasFocus()) { @@ -2109,6 +2314,15 @@ void LLLineEditor::setSelectAllonFocusReceived(BOOL b) mSelectAllonFocusReceived = b; } +void LLLineEditor::onKeystroke() +{ + if (mKeystrokeCallback) + { + mKeystrokeCallback(this); + } + + mSpellCheckStart = mSpellCheckEnd = -1; +} void LLLineEditor::setKeystrokeCallback(callback_t callback, void* user_data) { @@ -2231,10 +2445,9 @@ void LLLineEditor::updatePreedit(const LLWString &preedit_string, // Update of the preedit should be caused by some key strokes. mKeystrokeTimer.reset(); - if( mKeystrokeCallback ) - { - mKeystrokeCallback( this ); - } + onKeystroke(); + + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } BOOL LLLineEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const @@ -2386,7 +2599,38 @@ void LLLineEditor::showContextMenu(S32 x, S32 y) S32 screen_x, screen_y; localPointToScreen(x, y, &screen_x, &screen_y); - menu->show(screen_x, screen_y); + + setCursorAtLocalPos(x); + if (hasSelection()) + { + if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) + { + deselect(); + } + else + { + setCursor(llmax(mSelectionStart, mSelectionEnd)); + } + } + + bool use_spellcheck = getSpellCheck(), is_misspelled = false; + if (use_spellcheck) + { + mSuggestionList.clear(); + + // If the cursor is on a misspelled word, retrieve suggestions for it + std::string misspelled_word = getMisspelledWord(mCursorPos); + if ((is_misspelled = !misspelled_word.empty()) == true) + { + LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList); + } + } + + menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty())); + menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled)); + menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled)); + menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled)); + menu->show(screen_x, screen_y, this); } } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 2518dbe3c7..71dd53f608 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -40,6 +40,7 @@ #include "llframetimer.h" #include "lleditmenuhandler.h" +#include "llspellcheckmenuhandler.h" #include "lluictrl.h" #include "lluiimage.h" #include "lluistring.h" @@ -54,7 +55,7 @@ class LLButton; class LLContextMenu; class LLLineEditor -: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor +: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor, public LLSpellCheckMenuHandler { public: @@ -86,6 +87,7 @@ public: Optional<bool> select_on_focus, revert_on_esc, + spellcheck, commit_on_focus_lost, ignore_tab, is_password; @@ -146,6 +148,24 @@ public: virtual void deselect(); virtual BOOL canDeselect() const; + // LLSpellCheckMenuHandler overrides + /*virtual*/ bool getSpellCheck() const; + + /*virtual*/ const std::string& getSuggestion(U32 index) const; + /*virtual*/ U32 getSuggestionCount() const; + /*virtual*/ void replaceWithSuggestion(U32 index); + + /*virtual*/ void addToDictionary(); + /*virtual*/ bool canAddToDictionary() const; + + /*virtual*/ void addToIgnore(); + /*virtual*/ bool canAddToIgnore() const; + + // Spell checking helper functions + std::string getMisspelledWord(U32 pos) const; + bool isMisspelledWord(U32 pos) const; + void onSpellCheckSettingsChange(); + // view overrides virtual void draw(); virtual void reshape(S32 width,S32 height,BOOL called_from_parent=TRUE); @@ -169,6 +189,9 @@ public: virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text ); virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); + typedef boost::function<void(LLUIString&, S32&)> autoreplace_callback_t; + autoreplace_callback_t mAutoreplaceCallback; + void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; } const std::string& getLabel() { return mLabel.getString(); } @@ -223,6 +246,7 @@ public: void setSelectAllonFocusReceived(BOOL b); void setSelectAllonCommit(BOOL b) { mSelectAllonCommit = b; } + void onKeystroke(); typedef boost::function<void (LLLineEditor* caller, void* user_data)> callback_t; void setKeystrokeCallback(callback_t callback, void* user_data); @@ -322,6 +346,13 @@ protected: S32 mLastSelectionStart; S32 mLastSelectionEnd; + bool mSpellCheck; + S32 mSpellCheckStart; + S32 mSpellCheckEnd; + LLTimer mSpellCheckTimer; + std::list<std::pair<U32, U32> > mMisspellRanges; + std::vector<std::string> mSuggestionList; + LLTextValidate::validate_func_t mPrevalidateFunc; LLTextValidate::validate_func_t mPrevalidateInputFunc; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index ff6928ffda..efb9848a90 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3854,7 +3854,7 @@ void LLContextMenu::setVisible(BOOL visible) } // Takes cursor position in screen space? -void LLContextMenu::show(S32 x, S32 y) +void LLContextMenu::show(S32 x, S32 y, LLView* spawning_view) { if (getChildList()->empty()) { @@ -3908,6 +3908,14 @@ void LLContextMenu::show(S32 x, S32 y) setRect(rect); arrange(); + if (spawning_view) + { + mSpawningViewHandle = spawning_view->getHandle(); + } + else + { + mSpawningViewHandle.markDead(); + } LLView::setVisible(TRUE); } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 36f3ba34b9..67b3e1fbe6 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -670,7 +670,7 @@ public: virtual void draw (); - virtual void show (S32 x, S32 y); + virtual void show (S32 x, S32 y, LLView* spawning_view = NULL); virtual void hide (); virtual BOOL handleHover ( S32 x, S32 y, MASK mask ); @@ -683,10 +683,14 @@ public: LLHandle<LLContextMenu> getHandle() { return getDerivedHandle<LLContextMenu>(); } + LLView* getSpawningView() const { return mSpawningViewHandle.get(); } + void setSpawningView(LLHandle<LLView> spawning_view) { mSpawningViewHandle = spawning_view; } + protected: BOOL mHoveredAnyItem; LLMenuItemGL* mHoverItem; LLRootHandle<LLContextMenu> mHandle; + LLHandle<LLView> mSpawningViewHandle; }; diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 9b7e30bb04..2fd187a526 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -389,12 +389,11 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height { *show_h_scrollbar = TRUE; *visible_height -= scrollbar_size; - + // Note: Do *not* recompute *show_v_scrollbar here because with // The view inside the scroll container should not be extended // to container's full height to ensure the correct computation // of *show_v_scrollbar after subtracting horizontal scrollbar_size. - // Must retest now that visible_height has changed if( !*show_v_scrollbar && ((doc_height - *visible_height) > 1) ) { *show_v_scrollbar = TRUE; diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp new file mode 100644 index 0000000000..a189375fbe --- /dev/null +++ b/indra/llui/llspellcheck.cpp @@ -0,0 +1,505 @@ +/** + * @file llspellcheck.cpp + * @brief Spell checking functionality + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lldir.h" +#include "llsdserialize.h" + +#include "llspellcheck.h" +#if LL_WINDOWS + #include <hunspell/hunspelldll.h> + #pragma comment(lib, "libhunspell.lib") +#else + #include <hunspell/hunspell.hxx> +#endif + +static const std::string DICT_DIR = "dictionaries"; +static const std::string DICT_FILE_CUSTOM = "user_custom.dic"; +static const std::string DICT_FILE_IGNORE = "user_ignore.dic"; + +static const std::string DICT_FILE_MAIN = "dictionaries.xml"; +static const std::string DICT_FILE_USER = "user_dictionaries.xml"; + +LLSD LLSpellChecker::sDictMap; +LLSpellChecker::settings_change_signal_t LLSpellChecker::sSettingsChangeSignal; + +LLSpellChecker::LLSpellChecker() + : mHunspell(NULL) +{ + // Load initial dictionary information + refreshDictionaryMap(); +} + +LLSpellChecker::~LLSpellChecker() +{ + delete mHunspell; +} + +bool LLSpellChecker::checkSpelling(const std::string& word) const +{ + if ( (!mHunspell) || (word.length() < 3) || (0 != mHunspell->spell(word.c_str())) ) + { + return true; + } + if (mIgnoreList.size() > 0) + { + std::string word_lower(word); + LLStringUtil::toLower(word_lower); + return (mIgnoreList.end() != std::find(mIgnoreList.begin(), mIgnoreList.end(), word_lower)); + } + return false; +} + +S32 LLSpellChecker::getSuggestions(const std::string& word, std::vector<std::string>& suggestions) const +{ + suggestions.clear(); + if ( (!mHunspell) || (word.length() < 3) ) + { + return 0; + } + + char** suggestion_list; int suggestion_cnt = 0; + if ( (suggestion_cnt = mHunspell->suggest(&suggestion_list, word.c_str())) != 0 ) + { + for (int suggestion_index = 0; suggestion_index < suggestion_cnt; suggestion_index++) + { + suggestions.push_back(suggestion_list[suggestion_index]); + } + mHunspell->free_list(&suggestion_list, suggestion_cnt); + } + return suggestions.size(); +} + +// static +const LLSD LLSpellChecker::getDictionaryData(const std::string& dict_language) +{ + for (LLSD::array_const_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) + { + const LLSD& dict_entry = *it; + if (dict_language == dict_entry["language"].asString()) + { + return dict_entry; + } + } + return LLSD(); +} + +// static +bool LLSpellChecker::hasDictionary(const std::string& dict_language, bool check_installed) +{ + const LLSD dict_info = getDictionaryData(dict_language); + return dict_info.has("language") && ( (!check_installed) || (dict_info["installed"].asBoolean()) ); +} + +// static +void LLSpellChecker::setDictionaryData(const LLSD& dict_info) +{ + const std::string dict_language = dict_info["language"].asString(); + if (dict_language.empty()) + { + return; + } + + for (LLSD::array_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) + { + LLSD& dict_entry = *it; + if (dict_language == dict_entry["language"].asString()) + { + dict_entry = dict_info; + return; + } + } + sDictMap.append(dict_info); + return; +} + +// static +void LLSpellChecker::refreshDictionaryMap() +{ + const std::string app_path = getDictionaryAppPath(); + const std::string user_path = getDictionaryUserPath(); + + // Load dictionary information (file name, friendly name, ...) + llifstream user_file(user_path + DICT_FILE_MAIN, std::ios::binary); + if ( (!user_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, user_file)) || (0 == sDictMap.size()) ) + { + llifstream app_file(app_path + DICT_FILE_MAIN, std::ios::binary); + if ( (!app_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, app_file)) || (0 == sDictMap.size()) ) + { + return; + } + } + + // Load user installed dictionary information + llifstream custom_file(user_path + DICT_FILE_USER, std::ios::binary); + if (custom_file.is_open()) + { + LLSD custom_dict_map; + LLSDSerialize::fromXMLDocument(custom_dict_map, custom_file); + for (LLSD::array_iterator it = custom_dict_map.beginArray(); it != custom_dict_map.endArray(); ++it) + { + LLSD& dict_info = *it; + dict_info["user_installed"] = true; + setDictionaryData(dict_info); + } + custom_file.close(); + } + + // Look for installed dictionaries + std::string tmp_app_path, tmp_user_path; + for (LLSD::array_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) + { + LLSD& sdDict = *it; + tmp_app_path = (sdDict.has("name")) ? app_path + sdDict["name"].asString() : LLStringUtil::null; + tmp_user_path = (sdDict.has("name")) ? user_path + sdDict["name"].asString() : LLStringUtil::null; + sdDict["installed"] = + (!tmp_app_path.empty()) && ((gDirUtilp->fileExists(tmp_user_path + ".dic")) || (gDirUtilp->fileExists(tmp_app_path + ".dic"))); + } + + sSettingsChangeSignal(); +} + +void LLSpellChecker::addToCustomDictionary(const std::string& word) +{ + if (mHunspell) + { + mHunspell->add(word.c_str()); + } + addToDictFile(getDictionaryUserPath() + DICT_FILE_CUSTOM, word); + sSettingsChangeSignal(); +} + +void LLSpellChecker::addToIgnoreList(const std::string& word) +{ + std::string word_lower(word); + LLStringUtil::toLower(word_lower); + if (mIgnoreList.end() == std::find(mIgnoreList.begin(), mIgnoreList.end(), word_lower)) + { + mIgnoreList.push_back(word_lower); + addToDictFile(getDictionaryUserPath() + DICT_FILE_IGNORE, word_lower); + sSettingsChangeSignal(); + } +} + +void LLSpellChecker::addToDictFile(const std::string& dict_path, const std::string& word) +{ + std::vector<std::string> word_list; + + if (gDirUtilp->fileExists(dict_path)) + { + llifstream file_in(dict_path, std::ios::in); + if (file_in.is_open()) + { + std::string word; int line_num = 0; + while (getline(file_in, word)) + { + // Skip over the first line since that's just a line count + if (0 != line_num) + { + word_list.push_back(word); + } + line_num++; + } + } + else + { + // TODO: show error message? + return; + } + } + + word_list.push_back(word); + + llofstream file_out(dict_path, std::ios::out | std::ios::trunc); + if (file_out.is_open()) + { + file_out << word_list.size() << std::endl; + for (std::vector<std::string>::const_iterator itWord = word_list.begin(); itWord != word_list.end(); ++itWord) + { + file_out << *itWord << std::endl; + } + file_out.close(); + } +} + +bool LLSpellChecker::isActiveDictionary(const std::string& dict_language) const +{ + return + (mDictLanguage == dict_language) || + (mDictSecondary.end() != std::find(mDictSecondary.begin(), mDictSecondary.end(), dict_language)); +} + +void LLSpellChecker::setSecondaryDictionaries(dict_list_t dict_list) +{ + if (!getUseSpellCheck()) + { + return; + } + + // Check if we're only adding secondary dictionaries, or removing them + dict_list_t dict_add(llmax(dict_list.size(), mDictSecondary.size())), dict_rem(llmax(dict_list.size(), mDictSecondary.size())); + dict_list.sort(); + mDictSecondary.sort(); + dict_list_t::iterator end_added = std::set_difference(dict_list.begin(), dict_list.end(), mDictSecondary.begin(), mDictSecondary.end(), dict_add.begin()); + dict_list_t::iterator end_removed = std::set_difference(mDictSecondary.begin(), mDictSecondary.end(), dict_list.begin(), dict_list.end(), dict_rem.begin()); + + if (end_removed != dict_rem.begin()) // We can't remove secondary dictionaries so we need to recreate the Hunspell instance + { + mDictSecondary = dict_list; + + std::string dict_language = mDictLanguage; + initHunspell(dict_language); + } + else if (end_added != dict_add.begin()) // Add the new secondary dictionaries one by one + { + const std::string app_path = getDictionaryAppPath(); + const std::string user_path = getDictionaryUserPath(); + for (dict_list_t::const_iterator it_added = dict_add.begin(); it_added != end_added; ++it_added) + { + const LLSD dict_entry = getDictionaryData(*it_added); + if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) ) + { + continue; + } + + const std::string strFileDic = dict_entry["name"].asString() + ".dic"; + if (gDirUtilp->fileExists(user_path + strFileDic)) + { + mHunspell->add_dic((user_path + strFileDic).c_str()); + } + else if (gDirUtilp->fileExists(app_path + strFileDic)) + { + mHunspell->add_dic((app_path + strFileDic).c_str()); + } + } + mDictSecondary = dict_list; + sSettingsChangeSignal(); + } +} + +void LLSpellChecker::initHunspell(const std::string& dict_language) +{ + if (mHunspell) + { + delete mHunspell; + mHunspell = NULL; + mDictLanguage.clear(); + mDictFile.clear(); + mIgnoreList.clear(); + } + + const LLSD dict_entry = (!dict_language.empty()) ? getDictionaryData(dict_language) : LLSD(); + if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) || (!dict_entry["is_primary"].asBoolean())) + { + sSettingsChangeSignal(); + return; + } + + const std::string app_path = getDictionaryAppPath(); + const std::string user_path = getDictionaryUserPath(); + if (dict_entry.has("name")) + { + const std::string filename_aff = dict_entry["name"].asString() + ".aff"; + const std::string filename_dic = dict_entry["name"].asString() + ".dic"; + if ( (gDirUtilp->fileExists(user_path + filename_aff)) && (gDirUtilp->fileExists(user_path + filename_dic)) ) + { + mHunspell = new Hunspell((user_path + filename_aff).c_str(), (user_path + filename_dic).c_str()); + } + else if ( (gDirUtilp->fileExists(app_path + filename_aff)) && (gDirUtilp->fileExists(app_path + filename_dic)) ) + { + mHunspell = new Hunspell((app_path + filename_aff).c_str(), (app_path + filename_dic).c_str()); + } + if (!mHunspell) + { + return; + } + + mDictLanguage = dict_language; + mDictFile = dict_entry["name"].asString(); + + if (gDirUtilp->fileExists(user_path + DICT_FILE_CUSTOM)) + { + mHunspell->add_dic((user_path + DICT_FILE_CUSTOM).c_str()); + } + + if (gDirUtilp->fileExists(user_path + DICT_FILE_IGNORE)) + { + llifstream file_in(user_path + DICT_FILE_IGNORE, std::ios::in); + if (file_in.is_open()) + { + std::string word; int idxLine = 0; + while (getline(file_in, word)) + { + // Skip over the first line since that's just a line count + if (0 != idxLine) + { + LLStringUtil::toLower(word); + mIgnoreList.push_back(word); + } + idxLine++; + } + } + } + + for (dict_list_t::const_iterator it = mDictSecondary.begin(); it != mDictSecondary.end(); ++it) + { + const LLSD dict_entry = getDictionaryData(*it); + if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) ) + { + continue; + } + + const std::string filename_dic = dict_entry["name"].asString() + ".dic"; + if (gDirUtilp->fileExists(user_path + filename_dic)) + { + mHunspell->add_dic((user_path + filename_dic).c_str()); + } + else if (gDirUtilp->fileExists(app_path + filename_dic)) + { + mHunspell->add_dic((app_path + filename_dic).c_str()); + } + } + } + + sSettingsChangeSignal(); +} + +// static +const std::string LLSpellChecker::getDictionaryAppPath() +{ + std::string dict_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, DICT_DIR, ""); + return dict_path; +} + +// static +const std::string LLSpellChecker::getDictionaryUserPath() +{ + std::string dict_path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, DICT_DIR, ""); + if (!gDirUtilp->fileExists(dict_path)) + { + LLFile::mkdir(dict_path); + } + return dict_path; +} + +// static +bool LLSpellChecker::getUseSpellCheck() +{ + return (LLSpellChecker::instanceExists()) && (LLSpellChecker::instance().mHunspell); +} + +// static +bool LLSpellChecker::canRemoveDictionary(const std::string& dict_language) +{ + // Only user-installed inactive dictionaries can be removed + const LLSD dict_info = getDictionaryData(dict_language); + return + (dict_info["user_installed"].asBoolean()) && + ( (!getUseSpellCheck()) || (!LLSpellChecker::instance().isActiveDictionary(dict_language)) ); +} + +// static +void LLSpellChecker::removeDictionary(const std::string& dict_language) +{ + if (!canRemoveDictionary(dict_language)) + { + return; + } + + LLSD dict_map = loadUserDictionaryMap(); + for (LLSD::array_const_iterator it = dict_map.beginArray(); it != dict_map.endArray(); ++it) + { + const LLSD& dict_info = *it; + if (dict_info["language"].asString() == dict_language) + { + const std::string dict_dic = getDictionaryUserPath() + dict_info["name"].asString() + ".dic"; + if (gDirUtilp->fileExists(dict_dic)) + { + LLFile::remove(dict_dic); + } + const std::string dict_aff = getDictionaryUserPath() + dict_info["name"].asString() + ".aff"; + if (gDirUtilp->fileExists(dict_aff)) + { + LLFile::remove(dict_aff); + } + dict_map.erase(it - dict_map.beginArray()); + break; + } + } + saveUserDictionaryMap(dict_map); + + refreshDictionaryMap(); +} + +// static +LLSD LLSpellChecker::loadUserDictionaryMap() +{ + LLSD dict_map; + llifstream dict_file(getDictionaryUserPath() + DICT_FILE_USER, std::ios::binary); + if (dict_file.is_open()) + { + LLSDSerialize::fromXMLDocument(dict_map, dict_file); + dict_file.close(); + } + return dict_map; +} + +// static +void LLSpellChecker::saveUserDictionaryMap(const LLSD& dict_map) +{ + llofstream dict_file(getDictionaryUserPath() + DICT_FILE_USER, std::ios::trunc); + if (dict_file.is_open()) + { + LLSDSerialize::toPrettyXML(dict_map, dict_file); + dict_file.close(); + } +} + +// static +boost::signals2::connection LLSpellChecker::setSettingsChangeCallback(const settings_change_signal_t::slot_type& cb) +{ + return sSettingsChangeSignal.connect(cb); +} + +// static +void LLSpellChecker::setUseSpellCheck(const std::string& dict_language) +{ + if ( (((dict_language.empty()) && (getUseSpellCheck())) || (!dict_language.empty())) && + (LLSpellChecker::instance().mDictLanguage != dict_language) ) + { + LLSpellChecker::instance().initHunspell(dict_language); + } +} + +// static +void LLSpellChecker::initClass() +{ + if (sDictMap.isUndefined()) + { + refreshDictionaryMap(); + } +} diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h new file mode 100644 index 0000000000..4ab80195ea --- /dev/null +++ b/indra/llui/llspellcheck.h @@ -0,0 +1,93 @@ +/** + * @file llspellcheck.h + * @brief Spell checking functionality + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLSPELLCHECK_H +#define LLSPELLCHECK_H + +#include "llsingleton.h" +#include "llui.h" +#include <boost/signals2.hpp> + +class Hunspell; + +class LLSpellChecker : public LLSingleton<LLSpellChecker>, public LLInitClass<LLSpellChecker> +{ + friend class LLSingleton<LLSpellChecker>; + friend class LLInitClass<LLSpellChecker>; +protected: + LLSpellChecker(); + ~LLSpellChecker(); + +public: + void addToCustomDictionary(const std::string& word); + void addToIgnoreList(const std::string& word); + bool checkSpelling(const std::string& word) const; + S32 getSuggestions(const std::string& word, std::vector<std::string>& suggestions) const; +protected: + void addToDictFile(const std::string& dict_path, const std::string& word); + void initHunspell(const std::string& dict_language); + +public: + typedef std::list<std::string> dict_list_t; + + const std::string& getPrimaryDictionary() const { return mDictLanguage; } + const dict_list_t& getSecondaryDictionaries() const { return mDictSecondary; } + bool isActiveDictionary(const std::string& dict_language) const; + void setSecondaryDictionaries(dict_list_t dict_list); + + static bool canRemoveDictionary(const std::string& dict_language); + static const std::string getDictionaryAppPath(); + static const std::string getDictionaryUserPath(); + static const LLSD getDictionaryData(const std::string& dict_language); + static const LLSD& getDictionaryMap() { return sDictMap; } + static bool getUseSpellCheck(); + static bool hasDictionary(const std::string& dict_language, bool check_installed = false); + static void refreshDictionaryMap(); + static void removeDictionary(const std::string& dict_language); + static void setUseSpellCheck(const std::string& dict_language); +protected: + static LLSD loadUserDictionaryMap(); + static void setDictionaryData(const LLSD& dict_info); + static void saveUserDictionaryMap(const LLSD& dict_map); + +public: + typedef boost::signals2::signal<void()> settings_change_signal_t; + static boost::signals2::connection setSettingsChangeCallback(const settings_change_signal_t::slot_type& cb); +protected: + static void initClass(); + +protected: + Hunspell* mHunspell; + std::string mDictLanguage; + std::string mDictFile; + dict_list_t mDictSecondary; + std::vector<std::string> mIgnoreList; + + static LLSD sDictMap; + static settings_change_signal_t sSettingsChangeSignal; +}; + +#endif // LLSPELLCHECK_H diff --git a/indra/llui/llspellcheckmenuhandler.h b/indra/llui/llspellcheckmenuhandler.h new file mode 100644 index 0000000000..d5c95bad39 --- /dev/null +++ b/indra/llui/llspellcheckmenuhandler.h @@ -0,0 +1,46 @@ +/** + * @file llspellcheckmenuhandler.h + * @brief Interface used by spell check menu handling + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLSPELLCHECKMENUHANDLER_H +#define LLSPELLCHECKMENUHANDLER_H + +class LLSpellCheckMenuHandler +{ +public: + virtual bool getSpellCheck() const { return false; } + + virtual const std::string& getSuggestion(U32 index) const { return LLStringUtil::null; } + virtual U32 getSuggestionCount() const { return 0; } + virtual void replaceWithSuggestion(U32 index){} + + virtual void addToDictionary() {} + virtual bool canAddToDictionary() const { return false; } + + virtual void addToIgnore() {} + virtual bool canAddToIgnore() const { return false; } +}; + +#endif // LLSPELLCHECKMENUHANDLER_H diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 104481cbfc..3815eec447 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -32,6 +32,7 @@ #include "lllocalcliprect.h" #include "llmenugl.h" #include "llscrollcontainer.h" +#include "llspellcheck.h" #include "llstl.h" #include "lltextparser.h" #include "lltextutil.h" @@ -155,6 +156,7 @@ LLTextBase::Params::Params() plain_text("plain_text",false), track_end("track_end", false), read_only("read_only", false), + spellcheck("spellcheck", false), v_pad("v_pad", 0), h_pad("h_pad", 0), clip("clip", true), @@ -181,6 +183,9 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mFontShadow(p.font_shadow), mPopupMenu(NULL), mReadOnly(p.read_only), + mSpellCheck(p.spellcheck), + mSpellCheckStart(-1), + mSpellCheckEnd(-1), mCursorColor(p.cursor_color), mFgColor(p.text_color), mBorderVisible( p.border_visible ), @@ -246,6 +251,12 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) addChild(mDocumentView); } + if (mSpellCheck) + { + LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLTextBase::onSpellCheckSettingsChange, this)); + } + mSpellCheckTimer.reset(); + createDefaultSegment(); updateRects(); @@ -541,8 +552,92 @@ void LLTextBase::drawText() return; } + // Perform spell check if needed + if ( (getSpellCheck()) && (getWText().length() > 2) ) + { + // Calculate start and end indices for the spell checking range + S32 start = line_start, end = getLineEnd(last_line); + + if ( (mSpellCheckStart != start) || (mSpellCheckEnd != end) ) + { + const LLWString& wstrText = getWText(); + mMisspellRanges.clear(); + + segment_set_t::const_iterator seg_it = getSegIterContaining(start); + while (mSegments.end() != seg_it) + { + LLTextSegmentPtr text_segment = *seg_it; + if ( (text_segment.isNull()) || (text_segment->getStart() >= end) ) + { + break; + } + + if (!text_segment->canEdit()) + { + ++seg_it; + continue; + } + + // Combine adjoining text segments into one + U32 seg_start = text_segment->getStart(), seg_end = llmin(text_segment->getEnd(), end); + while (mSegments.end() != ++seg_it) + { + text_segment = *seg_it; + if ( (text_segment.isNull()) || (!text_segment->canEdit()) || (text_segment->getStart() >= end) ) + { + break; + } + seg_end = llmin(text_segment->getEnd(), end); + } + + // Find the start of the first word + U32 word_start = seg_start, word_end = -1; + while ( (word_start < wstrText.length()) && (!LLStringOps::isAlpha(wstrText[word_start])) ) + { + word_start++; + } + + // Iterate over all words in the text block and check them one by one + while (word_start < seg_end) + { + // Find the end of the current word (special case handling for "'" when it's used as a contraction) + word_end = word_start + 1; + while ( (word_end < seg_end) && + ((LLWStringUtil::isPartOfWord(wstrText[word_end])) || + ((L'\'' == wstrText[word_end]) && + (LLStringOps::isAlnum(wstrText[word_end - 1])) && (LLStringOps::isAlnum(wstrText[word_end + 1])))) ) + { + word_end++; + } + if (word_end > seg_end) + { + break; + } + + // Don't process words shorter than 3 characters + std::string word = wstring_to_utf8str(wstrText.substr(word_start, word_end - word_start)); + if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) ) + { + mMisspellRanges.push_back(std::pair<U32, U32>(word_start, word_end)); + } + + // Find the start of the next word + word_start = word_end + 1; + while ( (word_start < seg_end) && (!LLWStringUtil::isPartOfWord(wstrText[word_start])) ) + { + word_start++; + } + } + } + + mSpellCheckStart = start; + mSpellCheckEnd = end; + } + } + LLTextSegmentPtr cur_segment = *seg_iter; + std::list<std::pair<U32, U32> >::const_iterator misspell_it = std::lower_bound(mMisspellRanges.begin(), mMisspellRanges.end(), std::pair<U32, U32>(line_start, 0)); for (S32 cur_line = first_line; cur_line < last_line; cur_line++) { S32 next_line = cur_line + 1; @@ -577,7 +672,8 @@ void LLTextBase::drawText() cur_segment = *seg_iter; } - S32 clipped_end = llmin( line_end, cur_segment->getEnd() ) - cur_segment->getStart(); + S32 seg_end = llmin(line_end, cur_segment->getEnd()); + S32 clipped_end = seg_end - cur_segment->getStart(); if (mUseEllipses // using ellipses && clipped_end == line_end // last segment on line @@ -589,6 +685,46 @@ void LLTextBase::drawText() text_rect.mRight -= 2; } + // Draw squiggly lines under any visible misspelled words + while ( (mMisspellRanges.end() != misspell_it) && (misspell_it->first < seg_end) && (misspell_it->second > seg_start) ) + { + // Skip the current word if the user is still busy editing it + if ( (!mSpellCheckTimer.hasExpired()) && (misspell_it->first <= (U32)mCursorPos) && (misspell_it->second >= (U32)mCursorPos) ) + { + ++misspell_it; + continue; + } + + U32 misspell_start = llmax<U32>(misspell_it->first, seg_start), misspell_end = llmin<U32>(misspell_it->second, seg_end); + S32 squiggle_start = 0, squiggle_end = 0, pony = 0; + cur_segment->getDimensions(seg_start - cur_segment->getStart(), misspell_start - seg_start, squiggle_start, pony); + cur_segment->getDimensions(misspell_start - cur_segment->getStart(), misspell_end - misspell_start, squiggle_end, pony); + squiggle_start += text_rect.mLeft; + + pony = (squiggle_end + 3) / 6; + squiggle_start += squiggle_end / 2 - pony * 3; + squiggle_end = squiggle_start + pony * 6; + + S32 squiggle_bottom = text_rect.mBottom + (S32)cur_segment->getStyle()->getFont()->getDescenderHeight(); + + gGL.color4ub(255, 0, 0, 200); + while (squiggle_start + 1 < squiggle_end) + { + gl_line_2d(squiggle_start, squiggle_bottom, squiggle_start + 2, squiggle_bottom - 2); + if (squiggle_start + 3 < squiggle_end) + { + gl_line_2d(squiggle_start + 2, squiggle_bottom - 3, squiggle_start + 4, squiggle_bottom - 1); + } + squiggle_start += 4; + } + + if (misspell_it->second > seg_end) + { + break; + } + ++misspell_it; + } + text_rect.mLeft = (S32)(cur_segment->draw(seg_start - cur_segment->getStart(), clipped_end, selection_left, selection_right, text_rect)); seg_start = clipped_end + cur_segment->getStart(); @@ -1108,6 +1244,99 @@ void LLTextBase::deselect() mIsSelecting = FALSE; } +bool LLTextBase::getSpellCheck() const +{ + return (LLSpellChecker::getUseSpellCheck()) && (!mReadOnly) && (mSpellCheck); +} + +const std::string& LLTextBase::getSuggestion(U32 index) const +{ + return (index < mSuggestionList.size()) ? mSuggestionList[index] : LLStringUtil::null; +} + +U32 LLTextBase::getSuggestionCount() const +{ + return mSuggestionList.size(); +} + +void LLTextBase::replaceWithSuggestion(U32 index) +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) + { + deselect(); + + // Delete the misspelled word + removeStringNoUndo(it->first, it->second - it->first); + + // Insert the suggestion in its place + LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); + insertStringNoUndo(it->first, utf8str_to_wstring(mSuggestionList[index])); + setCursorPos(it->first + (S32)suggestion.length()); + + break; + } + } + mSpellCheckStart = mSpellCheckEnd = -1; +} + +void LLTextBase::addToDictionary() +{ + if (canAddToDictionary()) + { + LLSpellChecker::instance().addToCustomDictionary(getMisspelledWord(mCursorPos)); + } +} + +bool LLTextBase::canAddToDictionary() const +{ + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); +} + +void LLTextBase::addToIgnore() +{ + if (canAddToIgnore()) + { + LLSpellChecker::instance().addToIgnoreList(getMisspelledWord(mCursorPos)); + } +} + +bool LLTextBase::canAddToIgnore() const +{ + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); +} + +std::string LLTextBase::getMisspelledWord(U32 pos) const +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + { + return wstring_to_utf8str(getWText().substr(it->first, it->second - it->first)); + } + } + return LLStringUtil::null; +} + +bool LLTextBase::isMisspelledWord(U32 pos) const +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + { + return true; + } + } + return false; +} + +void LLTextBase::onSpellCheckSettingsChange() +{ + // Recheck the spelling on every change + mMisspellRanges.clear(); + mSpellCheckStart = mSpellCheckEnd = -1; +} // Sets the scrollbar from the cursor position void LLTextBase::updateScrollFromCursor() @@ -1707,9 +1936,6 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para while ( LLUrlRegistry::instance().findUrl(text, match, boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) ) { - - LLTextUtil::processUrlMatch(&match,this); - start = match.getStart(); end = match.getEnd()+1; @@ -1745,6 +1971,8 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para } } + LLTextUtil::processUrlMatch(&match,this); + // move on to the rest of the text after the Url if (end < (S32)text.length()) { diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 0549141b72..90b147cee1 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -30,6 +30,7 @@ #include "v4color.h" #include "lleditmenuhandler.h" +#include "llspellcheckmenuhandler.h" #include "llstyle.h" #include "llkeywords.h" #include "llpanel.h" @@ -230,7 +231,8 @@ typedef LLPointer<LLTextSegment> LLTextSegmentPtr; /// class LLTextBase : public LLUICtrl, - protected LLEditMenuHandler + protected LLEditMenuHandler, + public LLSpellCheckMenuHandler { public: friend class LLTextSegment; @@ -259,6 +261,7 @@ public: border_visible, track_end, read_only, + spellcheck, allow_scroll, plain_text, wrap, @@ -311,6 +314,24 @@ public: /*virtual*/ BOOL canDeselect() const; /*virtual*/ void deselect(); + // LLSpellCheckMenuHandler overrides + /*virtual*/ bool getSpellCheck() const; + + /*virtual*/ const std::string& getSuggestion(U32 index) const; + /*virtual*/ U32 getSuggestionCount() const; + /*virtual*/ void replaceWithSuggestion(U32 index); + + /*virtual*/ void addToDictionary(); + /*virtual*/ bool canAddToDictionary() const; + + /*virtual*/ void addToIgnore(); + /*virtual*/ bool canAddToIgnore() const; + + // Spell checking helper functions + std::string getMisspelledWord(U32 pos) const; + bool isMisspelledWord(U32 pos) const; + void onSpellCheckSettingsChange(); + // used by LLTextSegment layout code bool getWordWrap() { return mWordWrap; } bool getUseEllipses() { return mUseEllipses; } @@ -540,6 +561,14 @@ protected: BOOL mIsSelecting; // Are we in the middle of a drag-select? + // spell checking + bool mSpellCheck; + S32 mSpellCheckStart; + S32 mSpellCheckEnd; + LLTimer mSpellCheckTimer; + std::list<std::pair<U32, U32> > mMisspellRanges; + std::vector<std::string> mSuggestionList; + // configuration S32 mHPad; // padding on left of text S32 mVPad; // padding above text diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 9720dded6c..144b6960a1 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -54,6 +54,7 @@ #include "llwindow.h" #include "lltextparser.h" #include "llscrollcontainer.h" +#include "llspellcheck.h" #include "llpanel.h" #include "llurlregistry.h" #include "lltooltip.h" @@ -77,6 +78,7 @@ template class LLTextEditor* LLView::getChild<class LLTextEditor>( const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32; const S32 UI_TEXTEDITOR_LINE_NUMBER_DIGITS = 4; const S32 SPACES_PER_TAB = 4; +const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on /////////////////////////////////////////////////////////////////// @@ -1953,7 +1955,38 @@ void LLTextEditor::showContextMenu(S32 x, S32 y) S32 screen_x, screen_y; localPointToScreen(x, y, &screen_x, &screen_y); - mContextMenu->show(screen_x, screen_y); + + setCursorAtLocalPos(x, y, false); + if (hasSelection()) + { + if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) + { + deselect(); + } + else + { + setCursorPos(llmax(mSelectionStart, mSelectionEnd)); + } + } + + bool use_spellcheck = getSpellCheck(), is_misspelled = false; + if (use_spellcheck) + { + mSuggestionList.clear(); + + // If the cursor is on a misspelled word, retrieve suggestions for it + std::string misspelled_word = getMisspelledWord(mCursorPos); + if ((is_misspelled = !misspelled_word.empty()) == true) + { + LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList); + } + } + + mContextMenu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty())); + mContextMenu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled)); + mContextMenu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled)); + mContextMenu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled)); + mContextMenu->show(screen_x, screen_y, this); } @@ -2838,6 +2871,9 @@ void LLTextEditor::setKeystrokeCallback(const keystroke_signal_t::slot_type& cal void LLTextEditor::onKeyStroke() { mKeystrokeSignal(this); + + mSpellCheckStart = mSpellCheckEnd = -1; + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } //virtual diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp index 53cecf9d4a..8b356ba138 100644 --- a/indra/llwindow/llkeyboard.cpp +++ b/indra/llwindow/llkeyboard.cpp @@ -46,7 +46,7 @@ LLKeyStringTranslatorFunc* LLKeyboard::mStringTranslator = NULL; // Used for l10 // Class Implementation // -LLKeyboard::LLKeyboard() : mCallbacks(NULL), mNumpadDistinct(ND_NUMLOCK_OFF) +LLKeyboard::LLKeyboard() : mCallbacks(NULL) { S32 i; diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h index ba472cfde5..c155c1b362 100644 --- a/indra/llwindow/llkeyboard.h +++ b/indra/llwindow/llkeyboard.h @@ -63,14 +63,6 @@ class LLWindowCallbacks; class LLKeyboard { public: - typedef enum e_numpad_distinct - { - ND_NEVER, - ND_NUMLOCK_OFF, - ND_NUMLOCK_ON - } ENumpadDistinct; - -public: LLKeyboard(); virtual ~LLKeyboard(); @@ -107,8 +99,6 @@ public: static BOOL keyFromString(const std::string& str, KEY *key); // False on failure static std::string stringFromKey(KEY key); static std::string stringFromAccelerator( MASK accel_mask, KEY key ); - e_numpad_distinct getNumpadDistinct() { return mNumpadDistinct; } - void setNumpadDistinct(e_numpad_distinct val) { mNumpadDistinct = val; } void setCallbacks(LLWindowCallbacks *cbs) { mCallbacks = cbs; } F32 getKeyElapsedTime( KEY key ); // Returns time in seconds since key was pressed. @@ -135,8 +125,6 @@ protected: static LLKeyStringTranslatorFunc* mStringTranslator; // Used for l10n + PC/Mac/Linux accelerator labeling - e_numpad_distinct mNumpadDistinct; - EKeyboardInsertMode mInsertMode; static std::map<KEY,std::string> sKeysToNames; diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index ecc2631669..7f8f303517 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -299,28 +299,11 @@ void LLKeyboardMacOSX::scanKeyboard() BOOL LLKeyboardMacOSX::translateNumpadKey( const U16 os_key, KEY *translated_key ) { - if(mNumpadDistinct == ND_NUMLOCK_ON) - { - std::map<U16, KEY>::iterator iter= mTranslateNumpadMap.find(os_key); - if(iter != mTranslateNumpadMap.end()) - { - *translated_key = iter->second; - return TRUE; - } - } return translateKey(os_key, translated_key); } U16 LLKeyboardMacOSX::inverseTranslateNumpadKey(const KEY translated_key) { - if(mNumpadDistinct == ND_NUMLOCK_ON) - { - std::map<KEY, U16>::iterator iter= mInvTranslateNumpadMap.find(translated_key); - if(iter != mInvTranslateNumpadMap.end()) - { - return iter->second; - } - } return inverseTranslateKey(translated_key); } diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp index 4bb9603368..7c9aa1d340 100644 --- a/indra/llwindow/llkeyboardsdl.cpp +++ b/indra/llwindow/llkeyboardsdl.cpp @@ -312,29 +312,11 @@ void LLKeyboardSDL::scanKeyboard() BOOL LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key) { - if(mNumpadDistinct == ND_NUMLOCK_ON) - { - std::map<U16, KEY>::iterator iter= mTranslateNumpadMap.find(os_key); - if(iter != mTranslateNumpadMap.end()) - { - *translated_key = iter->second; - return TRUE; - } - } - BOOL success = translateKey(os_key, translated_key); - return success; + return translateKey(os_key, translated_key); } U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key) { - if(mNumpadDistinct == ND_NUMLOCK_ON) - { - std::map<KEY, U16>::iterator iter= mInvTranslateNumpadMap.find(translated_key); - if(iter != mInvTranslateNumpadMap.end()) - { - return iter->second; - } - } return inverseTranslateKey(translated_key); } diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp index df78816bd6..be3fe5deb0 100644 --- a/indra/llwindow/llkeyboardwin32.cpp +++ b/indra/llwindow/llkeyboardwin32.cpp @@ -299,69 +299,13 @@ void LLKeyboardWin32::scanKeyboard() BOOL LLKeyboardWin32::translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key) { - if(mNumpadDistinct == ND_NUMLOCK_ON) - { - std::map<U16, KEY>::iterator iter = mTranslateNumpadMap.find(os_key); - if (iter != mTranslateNumpadMap.end()) - { - *translated_key = iter->second; - return TRUE; - } - } - - BOOL success = translateKey(os_key, translated_key); - if(mNumpadDistinct != ND_NEVER) { - if(!success) return success; - if(mask & MASK_EXTENDED) - { - // this is where we'd create new keycodes for extended keys - // the set of extended keys includes the 'normal' arrow keys and - // the pgup/dn/insert/home/end/delete cluster above the arrow keys - // see http://windowssdk.msdn.microsoft.com/en-us/library/ms646280.aspx - - // only process the return key if numlock is off - if(((mNumpadDistinct == ND_NUMLOCK_OFF && - !(GetKeyState(VK_NUMLOCK) & 1)) - || mNumpadDistinct == ND_NUMLOCK_ON) && - *translated_key == KEY_RETURN) { - *translated_key = KEY_PAD_RETURN; - } - } - else - { - // the non-extended keys, those are in the numpad - switch (*translated_key) - { - case KEY_LEFT: - *translated_key = KEY_PAD_LEFT; break; - case KEY_RIGHT: - *translated_key = KEY_PAD_RIGHT; break; - case KEY_UP: - *translated_key = KEY_PAD_UP; break; - case KEY_DOWN: - *translated_key = KEY_PAD_DOWN; break; - case KEY_HOME: - *translated_key = KEY_PAD_HOME; break; - case KEY_END: - *translated_key = KEY_PAD_END; break; - case KEY_PAGE_UP: - *translated_key = KEY_PAD_PGUP; break; - case KEY_PAGE_DOWN: - *translated_key = KEY_PAD_PGDN; break; - case KEY_INSERT: - *translated_key = KEY_PAD_INS; break; - case KEY_DELETE: - *translated_key = KEY_PAD_DEL; break; - } - } - } - return success; + return translateKey(os_key, translated_key); } U16 LLKeyboardWin32::inverseTranslateExtendedKey(const KEY translated_key) { // if numlock is on, then we need to translate KEY_PAD_FOO to the corresponding number pad number - if((mNumpadDistinct == ND_NUMLOCK_ON) && (GetKeyState(VK_NUMLOCK) & 1)) + if(GetKeyState(VK_NUMLOCK) & 1) { std::map<KEY, U16>::iterator iter = mInvTranslateNumpadMap.find(translated_key); if (iter != mInvTranslateNumpadMap.end()) diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 0809d95628..53d9380f4f 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -201,7 +201,8 @@ void LLControlVariable::setValue(const LLSD& new_value, bool saved_value) } LLSD storable_value = getComparableValue(new_value); - bool value_changed = llsd_compare(getValue(), storable_value) == FALSE; + LLSD original_value = getValue(); + bool value_changed = llsd_compare(original_value, storable_value) == FALSE; if(saved_value) { // If we're going to save this value, return to default but don't fire @@ -237,7 +238,7 @@ void LLControlVariable::setValue(const LLSD& new_value, bool saved_value) if(value_changed) { - mCommitSignal(this, storable_value); + firePropertyChanged(original_value); } } @@ -249,12 +250,13 @@ void LLControlVariable::setDefaultValue(const LLSD& value) // *NOTE: Default values are not saved, only read. LLSD comparable_value = getComparableValue(value); - bool value_changed = (llsd_compare(getValue(), comparable_value) == FALSE); + LLSD original_value = getValue(); + bool value_changed = (llsd_compare(original_value, comparable_value) == FALSE); resetToDefault(false); mValues[0] = comparable_value; if(value_changed) { - firePropertyChanged(); + firePropertyChanged(original_value); } } @@ -277,6 +279,8 @@ void LLControlVariable::resetToDefault(bool fire_signal) { //The first setting is always the default //Pop to it and fire off the listener + LLSD originalValue = mValues.back(); + while(mValues.size() > 1) { mValues.pop_back(); @@ -284,7 +288,7 @@ void LLControlVariable::resetToDefault(bool fire_signal) if(fire_signal) { - firePropertyChanged(); + firePropertyChanged(originalValue); } } diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 597031ec70..9a3a40e476 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -98,7 +98,7 @@ class LLControlVariable : public LLRefCount public: typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t; - typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&)> commit_signal_t; + typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&, const LLSD&)> commit_signal_t; private: std::string mName; @@ -146,11 +146,11 @@ public: void setHiddenFromSettingsEditor(bool hide); void setComment(const std::string& comment); - void firePropertyChanged() +private: + void firePropertyChanged(const LLSD &pPreviousValue) { - mCommitSignal(this, mValues.back()); + mCommitSignal(this, mValues.back(), pPreviousValue); } -private: LLSD getComparableValue(const LLSD& value); bool llsd_compare(const LLSD& a, const LLSD & b); }; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0a267cbad0..9783601696 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -13,6 +13,7 @@ include(EXPAT) include(FMOD) include(OPENAL) include(FindOpenGL) +include(Hunspell) include(JsonCpp) include(LLAudio) include(LLCharacter) @@ -70,6 +71,7 @@ include_directories( ${LLLOGIN_INCLUDE_DIRS} ${UPDATER_INCLUDE_DIRS} ${LIBS_PREBUILT_DIR}/include/collada + ${LIBS_PREBUILD_DIR}/include/hunspell ${OPENAL_LIB_INCLUDE_DIRS} ${LIBS_PREBUILT_DIR}/include/collada/1.4 ) @@ -96,6 +98,7 @@ set(viewer_SOURCE_FILES llassetuploadresponders.cpp llattachmentsmgr.cpp llaudiosourcevo.cpp + llautoreplace.cpp llavataractions.cpp llavatariconctrl.cpp llavatarlist.cpp @@ -167,6 +170,7 @@ set(viewer_SOURCE_FILES llfloaterabout.cpp llfloaterbvhpreview.cpp llfloaterauction.cpp + llfloaterautoreplacesettings.cpp llfloateravatar.cpp llfloateravatarpicker.cpp llfloateravatartextures.cpp @@ -210,7 +214,6 @@ set(viewer_SOURCE_FILES llfloatermemleak.cpp llfloatermodelpreview.cpp llfloatermodeluploadbase.cpp - llfloatermodelwizard.cpp llfloaternamedesc.cpp llfloaternotificationsconsole.cpp llfloaterobjectweights.cpp @@ -232,6 +235,7 @@ set(viewer_SOURCE_FILES llfloatersidepanelcontainer.cpp llfloatersnapshot.cpp llfloatersounddevices.cpp + llfloaterspellchecksettings.cpp llfloatertelehub.cpp llfloatertestinspectors.cpp llfloatertestlistview.cpp @@ -654,6 +658,7 @@ set(viewer_HEADER_FILES llassetuploadresponders.h llattachmentsmgr.h llaudiosourcevo.h + llautoreplace.h llavataractions.h llavatariconctrl.h llavatarlist.h @@ -725,6 +730,7 @@ set(viewer_HEADER_FILES llfloaterabout.h llfloaterbvhpreview.h llfloaterauction.h + llfloaterautoreplacesettings.h llfloateravatar.h llfloateravatarpicker.h llfloateravatartextures.h @@ -768,7 +774,6 @@ set(viewer_HEADER_FILES llfloatermemleak.h llfloatermodelpreview.h llfloatermodeluploadbase.h - llfloatermodelwizard.h llfloaternamedesc.h llfloaternotificationsconsole.h llfloaterobjectweights.h @@ -790,6 +795,7 @@ set(viewer_HEADER_FILES llfloatersidepanelcontainer.h llfloatersnapshot.h llfloatersounddevices.h + llfloaterspellchecksettings.h llfloatertelehub.h llfloatertestinspectors.h llfloatertestlistview.h @@ -1515,9 +1521,7 @@ set(PACKAGE ON CACHE BOOL if (WINDOWS) set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES - # *TODO -reenable this once we get server usage sorted out - #LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:\"__tcmalloc\"" - LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:__tcmalloc" + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_LINK_FLAGS}" LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO" LINK_FLAGS_RELEASE "" ) @@ -1536,7 +1540,7 @@ if (WINDOWS) # In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py # and have the build deps get tracked *please* tell me about it. - if(USE_GOOGLE_PERFTOOLS) + if(USE_TCMALLOC) # Configure a var for tcmalloc location, if used. # Note the need to specify multiple names explicitly. set(GOOGLE_PERF_TOOLS_SOURCE @@ -1544,7 +1548,7 @@ if (WINDOWS) ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll ${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll ) - endif(USE_GOOGLE_PERFTOOLS) + endif(USE_TCMALLOC) set(COPY_INPUT_DEPENDENCIES @@ -1574,6 +1578,9 @@ if (WINDOWS) ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcp100.dll ${SHARED_LIB_STAGING_DIR}/Debug/msvcr100d.dll ${SHARED_LIB_STAGING_DIR}/Debug/msvcp100d.dll + ${SHARED_LIB_STAGING_DIR}/Release/libhunspell.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libhunspell.dll + ${SHARED_LIB_STAGING_DIR}/Debug/libhunspell.dll ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/SLVoice.exe ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxsdk.dll ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/ortp.dll @@ -1752,6 +1759,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${NDOF_LIBRARY} + ${HUNSPELL_LIBRARY} ${viewer_LIBRARIES} ${BOOST_PROGRAM_OPTIONS_LIBRARY} ${BOOST_REGEX_LIBRARY} diff --git a/indra/newview/app_settings/autoreplace.xml b/indra/newview/app_settings/autoreplace.xml new file mode 100644 index 0000000000..09d19f7b04 --- /dev/null +++ b/indra/newview/app_settings/autoreplace.xml @@ -0,0 +1,8330 @@ +<llsd> + <array> + <map> + <key>name</key> + <string>Abbreviations</string> + <key>replacements</key> + <map> + <key>afaic</key> + <string>As far as I am concerned</string> + <key>afaik</key> + <string>As far as I know</string> + <key>afk</key> + <string>away from keyboard</string> + <key>atm</key> + <string>at the moment</string> + <key>bbiab</key> + <string>be back in a bit</string> + <key>bbl</key> + <string>be back later</string> + <key>brb</key> + <string>be right back</string> + <key>btw</key> + <string>by the way</string> + <key>fyi</key> + <string>For your information</string> + <key>fwiw</key> + <string>For what its worth</string> + <key>gtg</key> + <string>got to go</string> + <key>idk</key> + <string>I don't know</string> + <key>iirc</key> + <string>if I recall correctly</string> + <key>imho</key> + <string>in my humble opinion</string> + <key>imo</key> + <string>in my opinion</string> + <key>irl</key> + <string>in real life</string> + <key>np</key> + <string>no problem</string> + <key>nsfw</key> + <string>not safe for work</string> + <key>nvm</key> + <string>nevermind</string> + <key>tc</key> + <string>take care</string> + <key>thx</key> + <string>thanks</string> + <key>ttfn</key> + <string>ta-ta for now</string> + <key>ttyl</key> + <string>talk to you later</string> + <key>ty</key> + <string>thank you</string> + <key>tyvm</key> + <string>thank you very much</string> + <key>wb</key> + <string>welcome back</string> + <key>yw</key> + <string>you're welcome</string> + <key>yvw</key> + <string>you're very welcome</string> + </map> + </map> + <map> + <key>name</key> + <string>Spelling Corrections</string> + <key>replacements</key> + <map> + <key>Amercia</key> + <string>America</string> + <key>Bernouilli</key> + <string>Bernoulli</string> + <key>Blitzkreig</key> + <string>Blitzkrieg</string> + <key>Bonnano</key> + <string>Bonanno</string> + <key>Brasillian</key> + <string>Brazilian</string> + <key>Britian</key> + <string>Britain</string> + <key>Brittish</key> + <string>British</string> + <key>Buddah</key> + <string>Buddha</string> + <key>Buddist</key> + <string>Buddhist</string> + <key>Cambrige</key> + <string>Cambridge</string> + <key>Capetown</key> + <string>Cape Town</string> + <key>Carmalite</key> + <string>Carmelite</string> + <key>Carnagie</key> + <string>Carnegie</string> + <key>Carnagie-Mellon</key> + <string>Carnegie-Mellon</string> + <key>Carnigie</key> + <string>Carnegie</string> + <key>Carnigie-Mellon</key> + <string>Carnegie-Mellon</string> + <key>Carribbean</key> + <string>Caribbean</string> + <key>Carribean</key> + <string>Caribbean</string> + <key>Carthagian</key> + <string>Carthaginian</string> + <key>Cataline</key> + <string>Catiline</string> + <key>Ceasar</key> + <string>Caesar</string> + <key>Celcius</key> + <string>Celsius</string> + <key>Champange</key> + <string>Champagne</string> + <key>Cincinatti</key> + <string>Cincinnati</string> + <key>Cincinnatti</key> + <string>Cincinnati</string> + <key>Conneticut</key> + <string>Connecticut</string> + <key>Dardenelles</key> + <string>Dardanelles</string> + <key>Dravadian</key> + <string>Dravidian</string> + <key>Enlish</key> + <string>English</string> + <key>Europian</key> + <string>European</string> + <key>Europians</key> + <string>Europeans</string> + <key>Eurpean</key> + <string>European</string> + <key>Eurpoean</key> + <string>European</string> + <key>Farenheit</key> + <string>Fahrenheit</string> + <key>Febuary</key> + <string>February</string> + <key>Feburary</key> + <string>February</string> + <key>Flemmish</key> + <string>Flemish</string> + <key>Formalhaut</key> + <string>Fomalhaut</string> + <key>Foundland</key> + <string>Newfoundland</string> + <key>Fransiscan</key> + <string>Franciscan</string> + <key>Fransiscans</key> + <string>Franciscans</string> + <key>Galations</key> + <string>Galatians</string> + <key>Gameboy</key> + <string>Game Boy</string> + <key>Ghandi</key> + <string>Gandhi</string> + <key>Godounov</key> + <string>Godunov</string> + <key>Gothenberg</key> + <string>Gothenburg</string> + <key>Gottleib</key> + <string>Gottlieb</string> + <key>Guaduloupe</key> + <string>Guadalupe</string> + <key>Guadulupe</key> + <string>Guadalupe</string> + <key>Guatamala</key> + <string>Guatemala</string> + <key>Guatamalan</key> + <string>Guatemalan</string> + <key>Guilia</key> + <string>Giulia</string> + <key>Guilio</key> + <string>Giulio</string> + <key>Guiness</key> + <string>Guinness</string> + <key>Guiseppe</key> + <string>Giuseppe</string> + <key>Habsbourg</key> + <string>Habsburg</string> + <key>Hallowean</key> + <string>Halloween</string> + <key>Heidelburg</key> + <string>Heidelberg</string> + <key>Ihaca</key> + <string>Ithaca</string> + <key>Israelies</key> + <string>Israelis</string> + <key>Janurary</key> + <string>January</string> + <key>Januray</key> + <string>January</string> + <key>Japanes</key> + <string>Japanese</string> + <key>Johanine</key> + <string>Johannine</string> + <key>Jospeh</key> + <string>Joseph</string> + <key>Juadaism</key> + <string>Judaism</string> + <key>Juadism</key> + <string>Judaism</string> + <key>Lybia</key> + <string>Libya</string> + <key>Malcom</key> + <string>Malcolm</string> + <key>Massachussets</key> + <string>Massachusetts</string> + <key>Massachussetts</key> + <string>Massachusetts</string> + <key>Mediteranean</key> + <string>Mediterranean</string> + <key>Michagan</key> + <string>Michigan</string> + <key>Misouri</key> + <string>Missouri</string> + <key>Missisipi</key> + <string>Mississippi</string> + <key>Missisippi</key> + <string>Mississippi</string> + <key>Monserrat</key> + <string>Montserrat</string> + <key>Montnana</key> + <string>Montana</string> + <key>Morisette</key> + <string>Morissette</string> + <key>Morrisette</key> + <string>Morissette</string> + <key>Mythraic</key> + <string>Mithraic</string> + <key>Naploeon</key> + <string>Napoleon</string> + <key>Napolean</key> + <string>Napoleon</string> + <key>Napoleonian</key> + <string>Napoleonic</string> + <key>Nazereth</key> + <string>Nazareth</string> + <key>Newyorker</key> + <string>New Yorker</string> + <key>Novermber</key> + <string>November</string> + <key>Nullabour</key> + <string>Nullarbor</string> + <key>Nuremburg</key> + <string>Nuremberg</string> + <key>Palistian</key> + <string>Palestinian</string> + <key>Palistinian</key> + <string>Palestinian</string> + <key>Palistinians</key> + <string>Palestinians</string> + <key>Papanicalou</key> + <string>Papanicolaou</string> + <key>Peloponnes</key> + <string>Peloponnesus</string> + <key>Pennyslvania</key> + <string>Pennsylvania</string> + <key>Pharoah</key> + <string>Pharaoh</string> + <key>Philipines</key> + <string>Philippines</string> + <key>Phillipine</key> + <string>Philippine</string> + <key>Phillipines</key> + <string>Philippines</string> + <key>Phillippines</key> + <string>Philippines</string> + <key>Phonecian</key> + <string>Phoenecian</string> + <key>Portugese</key> + <string>Portuguese</string> + <key>Postdam</key> + <string>Potsdam</string> + <key>Premonasterians</key> + <string>Premonstratensians</string> + <key>Pucini</key> + <string>Puccini</string> + <key>Puertorrican</key> + <string>Puerto Rican</string> + <key>Puertorricans</key> + <string>Puerto Ricans</string> + <key>Queenland</key> + <string>Queensland</string> + <key>Rockerfeller</key> + <string>Rockefeller</string> + <key>Russion</key> + <string>Russian</string> + <key>Sanhedrim</key> + <string>Sanhedrin</string> + <key>Saterday</key> + <string>Saturday</string> + <key>Saterdays</key> + <string>Saturdays</string> + <key>Sionist</key> + <string>Zionist</string> + <key>Sionists</key> + <string>Zionists</string> + <key>Sixtin</key> + <string>Sistine</string> + <key>Skagerak</key> + <string>Skagerrak</string> + <key>Tolkein</key> + <string>Tolkien</string> + <key>Tuscon</key> + <string>Tucson</string> + <key>Ukranian</key> + <string>Ukrainian</string> + <key>UnitesStates</key> + <string>UnitedStates</string> + <key>Yementite</key> + <string>Yemenite</string> + <key>abandonned</key> + <string>abandoned</string> + <key>aberation</key> + <string>aberration</string> + <key>abilties</key> + <string>abilities</string> + <key>abilty</key> + <string>ability</string> + <key>abondon</key> + <string>abandon</string> + <key>abondoned</key> + <string>abandoned</string> + <key>abondoning</key> + <string>abandoning</string> + <key>abondons</key> + <string>abandons</string> + <key>aborigene</key> + <string>aborigine</string> + <key>abortificant</key> + <string>abortifacient</string> + <key>abreviate</key> + <string>abbreviate</string> + <key>abreviated</key> + <string>abbreviated</string> + <key>abreviation</key> + <string>abbreviation</string> + <key>abritrary</key> + <string>arbitrary</string> + <key>absail</key> + <string>abseil</string> + <key>absailing</key> + <string>abseiling</string> + <key>absense</key> + <string>absence</string> + <key>absolutly</key> + <string>absolutely</string> + <key>absorbsion</key> + <string>absorption</string> + <key>absorbtion</key> + <string>absorption</string> + <key>abundacies</key> + <string>abundances</string> + <key>abundancies</key> + <string>abundances</string> + <key>abundunt</key> + <string>abundant</string> + <key>abutts</key> + <string>abuts</string> + <key>acadamy</key> + <string>academy</string> + <key>acadmic</key> + <string>academic</string> + <key>accademic</key> + <string>academic</string> + <key>accademy</key> + <string>academy</string> + <key>acccused</key> + <string>accused</string> + <key>accelleration</key> + <string>acceleration</string> + <key>accension</key> + <string>ascension</string> + <key>acceptence</key> + <string>acceptance</string> + <key>acceptible</key> + <string>acceptable</string> + <key>accessable</key> + <string>accessible</string> + <key>accidentaly</key> + <string>accidentally</string> + <key>accidently</key> + <string>accidentally</string> + <key>acclimitization</key> + <string>acclimatization</string> + <key>accomadate</key> + <string>accommodate</string> + <key>accomadated</key> + <string>accommodated</string> + <key>accomadates</key> + <string>accommodates</string> + <key>accomadating</key> + <string>accommodating</string> + <key>accomadation</key> + <string>accommodation</string> + <key>accomadations</key> + <string>accommodations</string> + <key>accomdate</key> + <string>accommodate</string> + <key>accomodate</key> + <string>accommodate</string> + <key>accomodated</key> + <string>accommodated</string> + <key>accomodates</key> + <string>accommodates</string> + <key>accomodating</key> + <string>accommodating</string> + <key>accomodation</key> + <string>accommodation</string> + <key>accomodations</key> + <string>accommodations</string> + <key>accompanyed</key> + <string>accompanied</string> + <key>accordeon</key> + <string>accordion</string> + <key>accordian</key> + <string>accordion</string> + <key>accoring</key> + <string>according</string> + <key>accoustic</key> + <string>acoustic</string> + <key>accquainted</key> + <string>acquainted </string> + <key>accrediation</key> + <string>accreditation</string> + <key>accredidation</key> + <string>accreditation</string> + <key>accross</key> + <string>across</string> + <key>accussed</key> + <string>accused</string> + <key>acedemic</key> + <string>academic</string> + <key>acheive</key> + <string>achieve</string> + <key>acheived</key> + <string>achieved</string> + <key>acheivement</key> + <string>achievement</string> + <key>acheivements</key> + <string>achievements</string> + <key>acheives</key> + <string>achieves</string> + <key>acheiving</key> + <string>achieving</string> + <key>acheivment</key> + <string>achievement</string> + <key>acheivments</key> + <string>achievements</string> + <key>achievment</key> + <string>achievement</string> + <key>achievments</key> + <string>achievements</string> + <key>achivement</key> + <string>achievement</string> + <key>achivements</key> + <string>achievements</string> + <key>acknowldeged</key> + <string>acknowledged</string> + <key>acknowledgeing</key> + <string>acknowledging</string> + <key>ackward</key> + <string>awkward</string> + <key>acommodate</key> + <string>accommodate</string> + <key>acomplish</key> + <string>accomplish</string> + <key>acomplished</key> + <string>accomplished</string> + <key>acomplishment</key> + <string>accomplishment</string> + <key>acomplishments</key> + <string>accomplishments</string> + <key>acording</key> + <string>according</string> + <key>acordingly</key> + <string>accordingly</string> + <key>acquaintence</key> + <string>acquaintance</string> + <key>acquaintences</key> + <string>acquaintances</string> + <key>acquiantence</key> + <string>acquaintance</string> + <key>acquiantences</key> + <string>acquaintances</string> + <key>acquited</key> + <string>acquitted</string> + <key>activites</key> + <string>activities</string> + <key>activly</key> + <string>actively</string> + <key>actualy</key> + <string>actually</string> + <key>acuracy</key> + <string>accuracy</string> + <key>acused</key> + <string>accused</string> + <key>acustom</key> + <string>accustom</string> + <key>acustommed</key> + <string>accustomed</string> + <key>adavanced</key> + <string>advanced</string> + <key>adbandon</key> + <string>abandon</string> + <key>additinally</key> + <string>additionally</string> + <key>additionaly</key> + <string>additionally</string> + <key>additonal</key> + <string>additional</string> + <key>additonally</key> + <string>additionally</string> + <key>addmission</key> + <string>admission</string> + <key>addopt</key> + <string>adopt</string> + <key>addopted</key> + <string>adopted</string> + <key>addoptive</key> + <string>adoptive</string> + <key>addres</key> + <string>address</string> + <key>addresable</key> + <string>addressable</string> + <key>addresed</key> + <string>addressed</string> + <key>addresing</key> + <string>addressing</string> + <key>addressess</key> + <string>addresses</string> + <key>addtion</key> + <string>addition</string> + <key>addtional</key> + <string>additional</string> + <key>adecuate</key> + <string>adequate</string> + <key>adequit</key> + <string>adequate</string> + <key>adhearing</key> + <string>adhering</string> + <key>adherance</key> + <string>adherence</string> + <key>admendment</key> + <string>amendment</string> + <key>admininistrative</key> + <string>administrative</string> + <key>adminstered</key> + <string>administered</string> + <key>adminstrate</key> + <string>administrate</string> + <key>adminstration</key> + <string>administration</string> + <key>adminstrative</key> + <string>administrative</string> + <key>adminstrator</key> + <string>administrator</string> + <key>admissability</key> + <string>admissibility</string> + <key>admissable</key> + <string>admissible</string> + <key>admited</key> + <string>admitted</string> + <key>admitedly</key> + <string>admittedly</string> + <key>adn</key> + <string>and</string> + <key>adolecent</key> + <string>adolescent</string> + <key>adquire</key> + <string>acquire</string> + <key>adquired</key> + <string>acquired</string> + <key>adquires</key> + <string>acquires</string> + <key>adquiring</key> + <string>acquiring</string> + <key>adres</key> + <string>address</string> + <key>adresable</key> + <string>addressable</string> + <key>adresing</key> + <string>addressing</string> + <key>adress</key> + <string>address</string> + <key>adressable</key> + <string>addressable</string> + <key>adressed</key> + <string>addressed</string> + <key>adressing</key> + <string>addressing</string> + <key>adventrous</key> + <string>adventurous</string> + <key>advertisment</key> + <string>advertisement</string> + <key>advertisments</key> + <string>advertisements</string> + <key>advesary</key> + <string>adversary</string> + <key>adviced</key> + <string>advised</string> + <key>aeriel</key> + <string>aerial</string> + <key>aeriels</key> + <string>aerials</string> + <key>afair</key> + <string>affair</string> + <key>afficianados</key> + <string>aficionados</string> + <key>afficionado</key> + <string>aficionado</string> + <key>afficionados</key> + <string>aficionados</string> + <key>affilate</key> + <string>affiliate</string> + <key>affilliate</key> + <string>affiliate</string> + <key>affort</key> + <string>afford</string> + <key>aforememtioned</key> + <string>aforementioned</string> + <key>againnst</key> + <string>against</string> + <key>agains</key> + <string>against</string> + <key>agaisnt</key> + <string>against</string> + <key>aganist</key> + <string>against</string> + <key>aggaravates</key> + <string>aggravates</string> + <key>aggreed</key> + <string>agreed</string> + <key>aggreement</key> + <string>agreement</string> + <key>aggregious</key> + <string>egregious</string> + <key>aggresive</key> + <string>aggressive</string> + <key>agian</key> + <string>again</string> + <key>agianst</key> + <string>against</string> + <key>agin</key> + <string>again</string> + <key>agina</key> + <string>again</string> + <key>aginst</key> + <string>against</string> + <key>agravate</key> + <string>aggravate</string> + <key>agre</key> + <string>agree</string> + <key>agred</key> + <string>agreed</string> + <key>agreeement</key> + <string>agreement</string> + <key>agreemnt</key> + <string>agreement</string> + <key>agregate</key> + <string>aggregate</string> + <key>agregates</key> + <string>aggregates</string> + <key>agreing</key> + <string>agreeing</string> + <key>agression</key> + <string>aggression</string> + <key>agressive</key> + <string>aggressive</string> + <key>agressively</key> + <string>aggressively</string> + <key>agressor</key> + <string>aggressor</string> + <key>agricuture</key> + <string>agriculture</string> + <key>agrieved</key> + <string>aggrieved</string> + <key>ahev</key> + <string>have</string> + <key>ahppen</key> + <string>happen</string> + <key>ahve</key> + <string>have</string> + <key>aicraft</key> + <string>aircraft</string> + <key>aiport</key> + <string>airport</string> + <key>airbourne</key> + <string>airborne</string> + <key>aircaft</key> + <string>aircraft</string> + <key>aircrafts</key> + <string>aircraft</string> + <key>airporta</key> + <string>airports</string> + <key>airrcraft</key> + <string>aircraft</string> + <key>aisian</key> + <string>asian</string> + <key>albiet</key> + <string>albeit</string> + <key>alchohol</key> + <string>alcohol</string> + <key>alchoholic</key> + <string>alcoholic</string> + <key>alchol</key> + <string>alcohol</string> + <key>alcholic</key> + <string>alcoholic</string> + <key>alcohal</key> + <string>alcohol</string> + <key>alcoholical</key> + <string>alcoholic</string> + <key>aledge</key> + <string>allege</string> + <key>aledged</key> + <string>alleged</string> + <key>aledges</key> + <string>alleges</string> + <key>alege</key> + <string>allege</string> + <key>aleged</key> + <string>alleged</string> + <key>alegience</key> + <string>allegiance</string> + <key>algebraical</key> + <string>algebraic</string> + <key>algorhitms</key> + <string>algorithms</string> + <key>algoritm</key> + <string>algorithm</string> + <key>algoritms</key> + <string>algorithms</string> + <key>alientating</key> + <string>alienating</string> + <key>alledge</key> + <string>allege</string> + <key>alledged</key> + <string>alleged</string> + <key>alledgedly</key> + <string>allegedly</string> + <key>alledges</key> + <string>alleges</string> + <key>allegedely</key> + <string>allegedly</string> + <key>allegedy</key> + <string>allegedly</string> + <key>allegely</key> + <string>allegedly</string> + <key>allegence</key> + <string>allegiance</string> + <key>allegience</key> + <string>allegiance</string> + <key>allign</key> + <string>align</string> + <key>alligned</key> + <string>aligned</string> + <key>alliviate</key> + <string>alleviate</string> + <key>allopone</key> + <string>allophone</string> + <key>allopones</key> + <string>allophones</string> + <key>allready</key> + <string>already</string> + <key>allthough</key> + <string>although</string> + <key>alltime</key> + <string>all-time</string> + <key>alltogether</key> + <string>altogether</string> + <key>almsot</key> + <string>almost</string> + <key>alochol</key> + <string>alcohol</string> + <key>alomst</key> + <string>almost</string> + <key>alot</key> + <string>a lot</string> + <key>alotted</key> + <string>allotted</string> + <key>alowed</key> + <string>allowed</string> + <key>alowing</key> + <string>allowing</string> + <key>alreayd</key> + <string>already</string> + <key>alse</key> + <string>else</string> + <key>alsot</key> + <string>also</string> + <key>alternitives</key> + <string>alternatives</string> + <key>altho</key> + <string>although</string> + <key>althought</key> + <string>although</string> + <key>altough</key> + <string>although</string> + <key>alusion</key> + <string>allusion</string> + <key>alwasy</key> + <string>always</string> + <key>alwyas</key> + <string>always</string> + <key>amalgomated</key> + <string>amalgamated</string> + <key>amatuer</key> + <string>amateur</string> + <key>amature</key> + <string>armature</string> + <key>amendmant</key> + <string>amendment</string> + <key>amerliorate</key> + <string>ameliorate</string> + <key>amke</key> + <string>make</string> + <key>amking</key> + <string>making</string> + <key>ammend</key> + <string>amend</string> + <key>ammended</key> + <string>amended</string> + <key>ammendment</key> + <string>amendment</string> + <key>ammendments</key> + <string>amendments</string> + <key>ammount</key> + <string>amount</string> + <key>ammused</key> + <string>amused</string> + <key>amoung</key> + <string>among</string> + <key>amoungst</key> + <string>amongst</string> + <key>amung</key> + <string>among</string> + <key>amunition</key> + <string>ammunition</string> + <key>analagous</key> + <string>analogous</string> + <key>analitic</key> + <string>analytic</string> + <key>analogeous</key> + <string>analogous</string> + <key>anarchim</key> + <string>anarchism</string> + <key>anarchistm</key> + <string>anarchism</string> + <key>anbd</key> + <string>and</string> + <key>ancestory</key> + <string>ancestry</string> + <key>ancilliary</key> + <string>ancillary</string> + <key>androgenous</key> + <string>androgynous</string> + <key>androgeny</key> + <string>androgyny</string> + <key>anihilation</key> + <string>annihilation</string> + <key>aniversary</key> + <string>anniversary</string> + <key>annoint</key> + <string>anoint</string> + <key>annointed</key> + <string>anointed</string> + <key>annointing</key> + <string>anointing</string> + <key>annoints</key> + <string>anoints</string> + <key>annouced</key> + <string>announced</string> + <key>annualy</key> + <string>annually</string> + <key>annuled</key> + <string>annulled</string> + <key>anohter</key> + <string>another</string> + <key>anomolies</key> + <string>anomalies</string> + <key>anomolous</key> + <string>anomalous</string> + <key>anomoly</key> + <string>anomaly</string> + <key>anonimity</key> + <string>anonymity</string> + <key>anounced</key> + <string>announced</string> + <key>anouncement</key> + <string>announcement</string> + <key>ansalisation</key> + <string>nasalisation</string> + <key>ansalization</key> + <string>nasalization</string> + <key>ansestors</key> + <string>ancestors</string> + <key>antartic</key> + <string>antarctic</string> + <key>anthromorphization</key> + <string>anthropomorphization</string> + <key>anthropolgist</key> + <string>anthropologist</string> + <key>anthropolgy</key> + <string>anthropology</string> + <key>anual</key> + <string>annual</string> + <key>anulled</key> + <string>annulled</string> + <key>anwsered</key> + <string>answered</string> + <key>anyhwere</key> + <string>anywhere</string> + <key>anyother</key> + <string>any other</string> + <key>anytying</key> + <string>anything</string> + <key>aparent</key> + <string>apparent</string> + <key>aparment</key> + <string>apartment</string> + <key>apenines</key> + <string>apennines</string> + <key>aplication</key> + <string>application</string> + <key>aplied</key> + <string>applied</string> + <key>apolegetics</key> + <string>apologetics</string> + <key>apon</key> + <string>apron</string> + <key>apparant</key> + <string>apparent</string> + <key>apparantly</key> + <string>apparently</string> + <key>appart</key> + <string>apart</string> + <key>appartment</key> + <string>apartment</string> + <key>appartments</key> + <string>apartments</string> + <key>appealling</key> + <string>appealing</string> + <key>appeareance</key> + <string>appearance</string> + <key>appearence</key> + <string>appearance</string> + <key>appearences</key> + <string>appearances</string> + <key>apperance</key> + <string>appearance</string> + <key>apperances</key> + <string>appearances</string> + <key>appereance</key> + <string>appearance</string> + <key>appereances</key> + <string>appearances</string> + <key>applicaiton</key> + <string>application</string> + <key>applicaitons</key> + <string>applications</string> + <key>appologies</key> + <string>apologies</string> + <key>appology</key> + <string>apology</string> + <key>apprearance</key> + <string>appearance</string> + <key>apprieciate</key> + <string>appreciate</string> + <key>approachs</key> + <string>approaches</string> + <key>appropiate</key> + <string>appropriate</string> + <key>appropraite</key> + <string>appropriate</string> + <key>appropropiate</key> + <string>appropriate</string> + <key>approproximate</key> + <string>approximate</string> + <key>approxamately</key> + <string>approximately</string> + <key>approxiately</key> + <string>approximately</string> + <key>approximitely</key> + <string>approximately</string> + <key>aprehensive</key> + <string>apprehensive</string> + <key>apropriate</key> + <string>appropriate</string> + <key>aproximate</key> + <string>approximate</string> + <key>aproximately</key> + <string>approximately</string> + <key>aquaduct</key> + <string>aqueduct</string> + <key>aquaintance</key> + <string>acquaintance</string> + <key>aquainted</key> + <string>acquainted</string> + <key>aquiantance</key> + <string>acquaintance</string> + <key>aquire</key> + <string>acquire</string> + <key>aquired</key> + <string>acquired</string> + <key>aquiring</key> + <string>acquiring</string> + <key>aquisition</key> + <string>acquisition</string> + <key>aquitted</key> + <string>acquitted</string> + <key>aranged</key> + <string>arranged</string> + <key>arangement</key> + <string>arrangement</string> + <key>arbitarily</key> + <string>arbitrarily</string> + <key>arbitary</key> + <string>arbitrary</string> + <key>archaelogists</key> + <string>archaeologists</string> + <key>archaelogy</key> + <string>archaeology</string> + <key>archaoelogy</key> + <string>archaeology</string> + <key>archaology</key> + <string>archaeology</string> + <key>archeaologist</key> + <string>archaeologist</string> + <key>archeaologists</key> + <string>archaeologists</string> + <key>archetect</key> + <string>architect</string> + <key>archetects</key> + <string>architects</string> + <key>archetectural</key> + <string>architectural</string> + <key>archetecturally</key> + <string>architecturally</string> + <key>archetecture</key> + <string>architecture</string> + <key>archiac</key> + <string>archaic</string> + <key>archictect</key> + <string>architect</string> + <key>archimedian</key> + <string>archimedean</string> + <key>architecht</key> + <string>architect</string> + <key>architechturally</key> + <string>architecturally</string> + <key>architechture</key> + <string>architecture</string> + <key>architechtures</key> + <string>architectures</string> + <key>architectual</key> + <string>architectural</string> + <key>archtype</key> + <string>archetype</string> + <key>archtypes</key> + <string>archetypes</string> + <key>aready</key> + <string>already</string> + <key>areodynamics</key> + <string>aerodynamics</string> + <key>argubly</key> + <string>arguably</string> + <key>arguement</key> + <string>argument</string> + <key>arguements</key> + <string>arguments</string> + <key>arised</key> + <string>arose</string> + <key>arival</key> + <string>arrival</string> + <key>armamant</key> + <string>armament</string> + <key>armistace</key> + <string>armistice</string> + <key>arogant</key> + <string>arrogant</string> + <key>arogent</key> + <string>arrogant</string> + <key>aroud</key> + <string>around</string> + <key>arrangment</key> + <string>arrangement</string> + <key>arrangments</key> + <string>arrangements</string> + <key>arround</key> + <string>around</string> + <key>artical</key> + <string>article</string> + <key>artice</key> + <string>article</string> + <key>articel</key> + <string>article</string> + <key>artifical</key> + <string>artificial</string> + <key>artifically</key> + <string>artificially</string> + <key>artillary</key> + <string>artillery</string> + <key>arund</key> + <string>around</string> + <key>asetic</key> + <string>ascetic</string> + <key>asfar</key> + <string>as far</string> + <key>asign</key> + <string>assign</string> + <key>aslo</key> + <string>also</string> + <key>asociated</key> + <string>associated</string> + <key>asorbed</key> + <string>absorbed</string> + <key>asphyxation</key> + <string>asphyxiation</string> + <key>assasin</key> + <string>assassin</string> + <key>assasinate</key> + <string>assassinate</string> + <key>assasinated</key> + <string>assassinated</string> + <key>assasinates</key> + <string>assassinates</string> + <key>assasination</key> + <string>assassination</string> + <key>assasinations</key> + <string>assassinations</string> + <key>assasined</key> + <string>assassinated</string> + <key>assasins</key> + <string>assassins</string> + <key>assassintation</key> + <string>assassination</string> + <key>assemple</key> + <string>assemble</string> + <key>assertation</key> + <string>assertion</string> + <key>asside</key> + <string>aside</string> + <key>assisnate</key> + <string>assassinate</string> + <key>assit</key> + <string>assist</string> + <key>assitant</key> + <string>assistant</string> + <key>assocation</key> + <string>association</string> + <key>assoicate</key> + <string>associate</string> + <key>assoicated</key> + <string>associated</string> + <key>assoicates</key> + <string>associates</string> + <key>assosication</key> + <string>assassination</string> + <key>asssassans</key> + <string>assassins</string> + <key>assualt</key> + <string>assault</string> + <key>assualted</key> + <string>assaulted</string> + <key>assymetric</key> + <string>asymmetric</string> + <key>assymetrical</key> + <string>asymmetrical</string> + <key>asteriod</key> + <string>asteroid</string> + <key>asthetic</key> + <string>aesthetic</string> + <key>asthetical</key> + <string>aesthetical</string> + <key>asthetically</key> + <string>aesthetically</string> + <key>asume</key> + <string>assume</string> + <key>aswell</key> + <string>as well</string> + <key>atain</key> + <string>attain</string> + <key>atempting</key> + <string>attempting</string> + <key>atheistical</key> + <string>atheistic</string> + <key>athenean</key> + <string>athenian</string> + <key>atheneans</key> + <string>athenians</string> + <key>athiesm</key> + <string>atheism</string> + <key>athiest</key> + <string>atheist</string> + <key>atorney</key> + <string>attorney</string> + <key>atribute</key> + <string>attribute</string> + <key>atributed</key> + <string>attributed</string> + <key>atributes</key> + <string>attributes</string> + <key>attaindre</key> + <string>attainder</string> + <key>attemp</key> + <string>attempt</string> + <key>attemped</key> + <string>attempted</string> + <key>attemt</key> + <string>attempt</string> + <key>attemted</key> + <string>attempted</string> + <key>attemting</key> + <string>attempting</string> + <key>attemts</key> + <string>attempts</string> + <key>attendence</key> + <string>attendance</string> + <key>attendent</key> + <string>attendant</string> + <key>attendents</key> + <string>attendants</string> + <key>attened</key> + <string>attended</string> + <key>attension</key> + <string>attention</string> + <key>attitide</key> + <string>attitude</string> + <key>attributred</key> + <string>attributed</string> + <key>attrocities</key> + <string>atrocities</string> + <key>audeince</key> + <string>audience</string> + <key>auromated</key> + <string>automated</string> + <key>austrailia</key> + <string>Australia</string> + <key>austrailian</key> + <string>Australian</string> + <key>auther</key> + <string>author</string> + <key>authobiographic</key> + <string>autobiographic</string> + <key>authobiography</key> + <string>autobiography</string> + <key>authorative</key> + <string>authoritative</string> + <key>authorites</key> + <string>authorities</string> + <key>authorithy</key> + <string>authority</string> + <key>authoritiers</key> + <string>authorities</string> + <key>authoritive</key> + <string>authoritative</string> + <key>authrorities</key> + <string>authorities</string> + <key>autochtonous</key> + <string>autochthonous</string> + <key>autoctonous</key> + <string>autochthonous</string> + <key>automaticly</key> + <string>automatically</string> + <key>automibile</key> + <string>automobile</string> + <key>automonomous</key> + <string>autonomous</string> + <key>autor</key> + <string>author</string> + <key>autority</key> + <string>authority</string> + <key>auxilary</key> + <string>auxiliary</string> + <key>auxillaries</key> + <string>auxiliaries</string> + <key>auxillary</key> + <string>auxiliary</string> + <key>auxilliaries</key> + <string>auxiliaries</string> + <key>auxilliary</key> + <string>auxiliary</string> + <key>availabe</key> + <string> available</string> + <key>availablity</key> + <string>availability</string> + <key>availaible</key> + <string>available</string> + <key>availble</key> + <string>available</string> + <key>availiable</key> + <string>available</string> + <key>availible</key> + <string>available</string> + <key>avalable</key> + <string>available</string> + <key>avalance</key> + <string>avalanche</string> + <key>avaliable</key> + <string>available</string> + <key>avation</key> + <string>aviation</string> + <key>avengence</key> + <string>a vengeance</string> + <key>averageed</key> + <string>averaged</string> + <key>avilable</key> + <string>available</string> + <key>awared</key> + <string>awarded</string> + <key>awya</key> + <string>away</string> + <key>baceause</key> + <string>because</string> + <key>backgorund</key> + <string>background</string> + <key>backrounds</key> + <string>backgrounds</string> + <key>bakc</key> + <string>back</string> + <key>banannas</key> + <string>bananas</string> + <key>bandwith</key> + <string>bandwidth</string> + <key>bankrupcy</key> + <string>bankruptcy</string> + <key>banruptcy</key> + <string>bankruptcy</string> + <key>baout</key> + <string>about</string> + <key>basicaly</key> + <string>basically</string> + <key>basicly</key> + <string>basically</string> + <key>bcak</key> + <string>back</string> + <key>beachead</key> + <string>beachhead</string> + <key>beacuse</key> + <string>because</string> + <key>beastiality</key> + <string>bestiality</string> + <key>beatiful</key> + <string>beautiful</string> + <key>beaurocracy</key> + <string>bureaucracy</string> + <key>beaurocratic</key> + <string>bureaucratic</string> + <key>beautyfull</key> + <string>beautiful</string> + <key>becamae</key> + <string>became</string> + <key>becames</key> + <string>becomes</string> + <key>becasue</key> + <string>because</string> + <key>beccause</key> + <string>because</string> + <key>becomeing</key> + <string>becoming</string> + <key>becomming</key> + <string>becoming</string> + <key>becouse</key> + <string>because</string> + <key>becuase</key> + <string>because</string> + <key>bedore</key> + <string>before</string> + <key>befoer</key> + <string>before</string> + <key>beggin</key> + <string>begin</string> + <key>begginer</key> + <string>beginner</string> + <key>begginers</key> + <string>beginners</string> + <key>beggining</key> + <string>beginning</string> + <key>begginings</key> + <string>beginnings</string> + <key>beggins</key> + <string>begins</string> + <key>begining</key> + <string>beginning</string> + <key>beginnig</key> + <string>beginning</string> + <key>behavour</key> + <string>behavior</string> + <key>beleagured</key> + <string>beleaguered</string> + <key>beleif</key> + <string>belief</string> + <key>beleive</key> + <string>believe</string> + <key>beleived</key> + <string>believed</string> + <key>beleives</key> + <string>believes</string> + <key>beleiving</key> + <string>believing</string> + <key>beligum</key> + <string>belgium</string> + <key>belive</key> + <string>believe</string> + <key>belived</key> + <string>believed</string> + <key>belives</key> + <string>believes</string> + <key>belligerant</key> + <string>belligerent</string> + <key>bellweather</key> + <string>bellwether</string> + <key>bemusemnt</key> + <string>bemusement</string> + <key>beneficary</key> + <string>beneficiary</string> + <key>beng</key> + <string>being</string> + <key>benificial</key> + <string>beneficial</string> + <key>benifit</key> + <string>benefit</string> + <key>benifits</key> + <string>benefits</string> + <key>bergamont</key> + <string>bergamot</string> + <key>beseige</key> + <string>besiege</string> + <key>beseiged</key> + <string>besieged</string> + <key>beseiging</key> + <string>besieging</string> + <key>betwen</key> + <string>between</string> + <key>beween</key> + <string>between</string> + <key>bewteen</key> + <string>between</string> + <key>bilateraly</key> + <string>bilaterally</string> + <key>billingualism</key> + <string>bilingualism</string> + <key>binominal</key> + <string>binomial</string> + <key>bizzare</key> + <string>bizarre</string> + <key>blaim</key> + <string>blame</string> + <key>blaimed</key> + <string>blamed</string> + <key>blessure</key> + <string>blessing</string> + <key>bodydbuilder</key> + <string>bodybuilder</string> + <key>bombardement</key> + <string>bombardment</string> + <key>bombarment</key> + <string>bombardment</string> + <key>bondary</key> + <string>boundary</string> + <key>borke</key> + <string>broke</string> + <key>boundry</key> + <string>boundary</string> + <key>bouyancy</key> + <string>buoyancy</string> + <key>bouyant</key> + <string>buoyant</string> + <key>boyant</key> + <string>buoyant</string> + <key>breakthough</key> + <string>breakthrough</string> + <key>breakthroughts</key> + <string>breakthroughs</string> + <key>breif</key> + <string>brief</string> + <key>breifly</key> + <string>briefly</string> + <key>brethen</key> + <string>brethren</string> + <key>bretheren</key> + <string>brethren</string> + <key>briliant</key> + <string>brilliant</string> + <key>brillant</key> + <string>brilliant</string> + <key>brimestone</key> + <string>brimstone</string> + <key>broacasted</key> + <string>broadcast</string> + <key>broadacasting</key> + <string>broadcasting</string> + <key>broady</key> + <string>broadly</string> + <key>buisness</key> + <string>business</string> + <key>buisnessman</key> + <string>businessman</string> + <key>buoancy</key> + <string>buoyancy</string> + <key>burried</key> + <string>buried</string> + <key>busineses</key> + <string>businesses</string> + <key>busness</key> + <string>business</string> + <key>bussiness</key> + <string>business</string> + <key>caculater</key> + <string>calculator</string> + <key>cacuses</key> + <string>caucuses</string> + <key>cahracters</key> + <string>characters</string> + <key>calaber</key> + <string>caliber</string> + <key>calculater</key> + <string>calculator</string> + <key>calculs</key> + <string>calculus</string> + <key>calenders</key> + <string>calendars</string> + <key>caligraphy</key> + <string>calligraphy</string> + <key>caluclate</key> + <string>calculate</string> + <key>caluclated</key> + <string>calculated</string> + <key>caluculate</key> + <string>calculate</string> + <key>caluculated</key> + <string>calculated</string> + <key>calulate</key> + <string>calculate</string> + <key>calulated</key> + <string>calculated</string> + <key>calulater</key> + <string>calculator</string> + <key>camoflage</key> + <string>camouflage</string> + <key>campain</key> + <string>campaign</string> + <key>campains</key> + <string>campaigns</string> + <key>candadate</key> + <string>candidate</string> + <key>candiate</key> + <string>candidate</string> + <key>candidiate</key> + <string>candidate</string> + <key>cannister</key> + <string>canister</string> + <key>cannisters</key> + <string>canisters</string> + <key>cannnot</key> + <string>cannot</string> + <key>cannonical</key> + <string>canonical</string> + <key>cannotation</key> + <string>connotation</string> + <key>cannotations</key> + <string>connotations</string> + <key>cant</key> + <string>can't</string> + <key>caost</key> + <string>coast</string> + <key>caperbility</key> + <string>capability</string> + <key>capible</key> + <string>capable</string> + <key>captial</key> + <string>capital</string> + <key>captued</key> + <string>captured</string> + <key>capturd</key> + <string>captured</string> + <key>carachter</key> + <string>character</string> + <key>caracterized</key> + <string>characterized</string> + <key>carcas</key> + <string>carcass</string> + <key>carefull</key> + <string>careful</string> + <key>careing</key> + <string>caring</string> + <key>carismatic</key> + <string>charismatic</string> + <key>carnege</key> + <string>carnage</string> + <key>carnige</key> + <string>carnage</string> + <key>carniverous</key> + <string>carnivorous</string> + <key>carreer</key> + <string>career</string> + <key>carrers</key> + <string>careers</string> + <key>cartdridge</key> + <string>cartridge</string> + <key>carthographer</key> + <string>cartographer</string> + <key>cartilege</key> + <string>cartilage</string> + <key>cartilidge</key> + <string>cartilage</string> + <key>cartrige</key> + <string>cartridge</string> + <key>casette</key> + <string>cassette</string> + <key>casion</key> + <string>caisson</string> + <key>cassawory</key> + <string>cassowary</string> + <key>cassowarry</key> + <string>cassowary</string> + <key>casulaties</key> + <string>casualties</string> + <key>casulaty</key> + <string>casualty</string> + <key>catagories</key> + <string>categories</string> + <key>catagorized</key> + <string>categorized</string> + <key>catagory</key> + <string>category</string> + <key>catapillar</key> + <string>caterpillar</string> + <key>catapillars</key> + <string>caterpillars</string> + <key>catapiller</key> + <string>caterpillar</string> + <key>catapillers</key> + <string>caterpillars</string> + <key>catepillar</key> + <string>caterpillar</string> + <key>catepillars</key> + <string>caterpillars</string> + <key>catergorize</key> + <string>categorize</string> + <key>catergorized</key> + <string>categorized</string> + <key>caterpilar</key> + <string>caterpillar</string> + <key>caterpilars</key> + <string>caterpillars</string> + <key>caterpiller</key> + <string>caterpillar</string> + <key>caterpillers</key> + <string>caterpillars</string> + <key>cathlic</key> + <string>catholic</string> + <key>catholocism</key> + <string>catholicism</string> + <key>catterpilar</key> + <string>caterpillar</string> + <key>catterpilars</key> + <string>caterpillars</string> + <key>catterpillar</key> + <string>caterpillar</string> + <key>catterpillars</key> + <string>caterpillars</string> + <key>cattleship</key> + <string>battleship</string> + <key>causalities</key> + <string>casualties</string> + <key>cellpading</key> + <string>cellpadding</string> + <key>cementary</key> + <string>cemetery</string> + <key>cemetarey</key> + <string>cemetery</string> + <key>cemetaries</key> + <string>cemeteries</string> + <key>cemetary</key> + <string>cemetery</string> + <key>cencus</key> + <string>census</string> + <key>censur</key> + <string>censor</string> + <key>cententenial</key> + <string>centennial</string> + <key>centruies</key> + <string>centuries</string> + <key>centruy</key> + <string>century</string> + <key>ceratin</key> + <string>certain</string> + <key>cerimonial</key> + <string>ceremonial</string> + <key>cerimonies</key> + <string>ceremonies</string> + <key>cerimonious</key> + <string>ceremonious</string> + <key>cerimony</key> + <string>ceremony</string> + <key>ceromony</key> + <string>ceremony</string> + <key>certainity</key> + <string>certainty</string> + <key>certian</key> + <string>certain</string> + <key>chalenging</key> + <string>challenging</string> + <key>challange</key> + <string>challenge</string> + <key>challanged</key> + <string>challenged</string> + <key>challege</key> + <string>challenge</string> + <key>changable</key> + <string>changeable</string> + <key>charachter</key> + <string>character</string> + <key>charachters</key> + <string>characters</string> + <key>charactersistic</key> + <string>characteristic</string> + <key>charactor</key> + <string>character </string> + <key>charactors</key> + <string>characters</string> + <key>charasmatic</key> + <string>charismatic</string> + <key>charaterized</key> + <string>characterized</string> + <key>chariman</key> + <string>chairman</string> + <key>charistics</key> + <string>characteristics</string> + <key>cheif</key> + <string>chief</string> + <key>cheifs</key> + <string>chiefs</string> + <key>chemcial</key> + <string>chemical</string> + <key>chemcially</key> + <string>chemically</string> + <key>chemestry</key> + <string>chemistry</string> + <key>chemicaly</key> + <string>chemically</string> + <key>childbird</key> + <string>childbirth</string> + <key>childen</key> + <string>children</string> + <key>choosen</key> + <string>chosen</string> + <key>chracter</key> + <string>character</string> + <key>chuch</key> + <string>church</string> + <key>churchs</key> + <string>churches</string> + <key>circulaton</key> + <string>circulation</string> + <key>circumsicion</key> + <string>circumcision</string> + <key>circut</key> + <string>circuit</string> + <key>ciricuit</key> + <string>circuit</string> + <key>ciriculum</key> + <string>curriculum</string> + <key>civillian</key> + <string>civilian</string> + <key>claer</key> + <string>clear</string> + <key>claerer</key> + <string>clearer</string> + <key>claerly</key> + <string>clearly</string> + <key>claimes</key> + <string>claims</string> + <key>clas</key> + <string>class</string> + <key>clasic</key> + <string>classic</string> + <key>clasical</key> + <string>classical</string> + <key>clasically</key> + <string>classically</string> + <key>cleareance</key> + <string>clearance</string> + <key>clera</key> + <string>clear</string> + <key>clincial</key> + <string>clinical</string> + <key>clinicaly</key> + <string>clinically</string> + <key>cmo</key> + <string>com</string> + <key>cmoputer</key> + <string>computer</string> + <key>co-incided</key> + <string>coincided</string> + <key>coctail</key> + <string>cocktail</string> + <key>coform</key> + <string>conform</string> + <key>cognizent</key> + <string>cognizant</string> + <key>coincedentally</key> + <string>coincidentally</string> + <key>colaborations</key> + <string>collaborations</string> + <key>colateral</key> + <string>collateral</string> + <key>colelctive</key> + <string>collective</string> + <key>collaberative</key> + <string>collaborative</string> + <key>collecton</key> + <string>collection</string> + <key>collegue</key> + <string>colleague</string> + <key>collegues</key> + <string>colleagues</string> + <key>collonade</key> + <string>colonnade</string> + <key>collonies</key> + <string>colonies</string> + <key>collony</key> + <string>colony </string> + <key>collosal</key> + <string>colossal</string> + <key>colonizators</key> + <string>colonizers</string> + <key>comander</key> + <string>commander</string> + <key>comando</key> + <string>commando</string> + <key>comandos</key> + <string>commandos</string> + <key>comany</key> + <string>company</string> + <key>comapany</key> + <string>company</string> + <key>comback</key> + <string>comeback</string> + <key>combanations</key> + <string>combinations</string> + <key>combinatins</key> + <string>combinations</string> + <key>combusion</key> + <string>combustion</string> + <key>comdemnation</key> + <string>condemnation</string> + <key>comemmorates</key> + <string>commemorates</string> + <key>comemoretion</key> + <string>commemoration</string> + <key>comision</key> + <string>commission</string> + <key>comisioned</key> + <string>commissioned</string> + <key>comisioner</key> + <string>commissioner</string> + <key>comisioning</key> + <string>commissioning</string> + <key>comisions</key> + <string>commissions</string> + <key>comission</key> + <string>commission</string> + <key>comissioned</key> + <string>commissioned</string> + <key>comissioner</key> + <string>commissioner</string> + <key>comissioning</key> + <string>commissioning</string> + <key>comissions</key> + <string>commissions</string> + <key>comited</key> + <string>committed</string> + <key>comiting</key> + <string>committing</string> + <key>comitted</key> + <string>committed</string> + <key>comittee</key> + <string>committee</string> + <key>comitting</key> + <string>committing</string> + <key>commandoes</key> + <string>commandos</string> + <key>commedic</key> + <string>comedic</string> + <key>commemerative</key> + <string>commemorative</string> + <key>commemmorate</key> + <string>commemorate</string> + <key>commemmorating</key> + <string>commemorating</string> + <key>commerical</key> + <string>commercial</string> + <key>commerically</key> + <string>commercially</string> + <key>commericial</key> + <string>commercial</string> + <key>commericially</key> + <string>commercially</string> + <key>commerorative</key> + <string>commemorative</string> + <key>comming</key> + <string>coming</string> + <key>comminication</key> + <string>communication</string> + <key>commision</key> + <string>commission</string> + <key>commisioned</key> + <string>commissioned</string> + <key>commisioner</key> + <string>commissioner</string> + <key>commisioning</key> + <string>commissioning</string> + <key>commisions</key> + <string>commissions</string> + <key>commited</key> + <string>committed</string> + <key>commitee</key> + <string>committee</string> + <key>commiting</key> + <string>committing</string> + <key>committe</key> + <string>committee</string> + <key>committment</key> + <string>commitment</string> + <key>committments</key> + <string>commitments</string> + <key>commmemorated</key> + <string>commemorated</string> + <key>commongly</key> + <string>commonly</string> + <key>commonweath</key> + <string>commonwealth</string> + <key>commuications</key> + <string>communications</string> + <key>commuinications</key> + <string>communications</string> + <key>communciation</key> + <string>communication</string> + <key>communiation</key> + <string>communication</string> + <key>communites</key> + <string>communities</string> + <key>compability</key> + <string>compatibility</string> + <key>comparision</key> + <string>comparison</string> + <key>comparisions</key> + <string>comparisons</string> + <key>comparitive</key> + <string>comparative</string> + <key>comparitively</key> + <string>comparatively</string> + <key>compatabilities</key> + <string>compatibilities</string> + <key>compatability</key> + <string>compatibility</string> + <key>compatable</key> + <string>compatible</string> + <key>compatablities</key> + <string>compatibilities</string> + <key>compatablity</key> + <string>compatibility</string> + <key>compatiable</key> + <string>compatible</string> + <key>compatiblities</key> + <string>compatibilities</string> + <key>compatiblity</key> + <string>compatibility</string> + <key>compeitions</key> + <string>competitions</string> + <key>compensantion</key> + <string>compensation</string> + <key>competance</key> + <string>competence</string> + <key>competant</key> + <string>competent</string> + <key>competative</key> + <string>competitive</string> + <key>competion</key> + <string>competition</string> + <key>competitiion</key> + <string>competition</string> + <key>competive</key> + <string>competitive</string> + <key>competiveness</key> + <string>competitiveness</string> + <key>comphrehensive</key> + <string>comprehensive</string> + <key>compitent</key> + <string>competent</string> + <key>completedthe</key> + <string>completed the</string> + <key>completelyl</key> + <string>completely</string> + <key>completetion</key> + <string>completion</string> + <key>complier</key> + <string>compiler</string> + <key>componant</key> + <string>component</string> + <key>comprable</key> + <string>comparable</string> + <key>comprimise</key> + <string>compromise</string> + <key>compulsary</key> + <string>compulsory</string> + <key>compulsery</key> + <string>compulsory</string> + <key>computarized</key> + <string>computerized</string> + <key>concensus</key> + <string>consensus</string> + <key>concider</key> + <string>consider</string> + <key>concidered</key> + <string>considered</string> + <key>concidering</key> + <string>considering</string> + <key>conciders</key> + <string>considers</string> + <key>concieted</key> + <string>conceited</string> + <key>concieved</key> + <string>conceived</string> + <key>concious</key> + <string>conscious</string> + <key>conciously</key> + <string>consciously</string> + <key>conciousness</key> + <string>consciousness</string> + <key>condamned</key> + <string>condemned</string> + <key>condemmed</key> + <string>condemned</string> + <key>condidtion</key> + <string>condition</string> + <key>condidtions</key> + <string>conditions</string> + <key>conditionsof</key> + <string>conditions of</string> + <key>conected</key> + <string>connected</string> + <key>conection</key> + <string>connection</string> + <key>conesencus</key> + <string>consensus</string> + <key>confidental</key> + <string>confidential</string> + <key>confidentally</key> + <string>confidentially</string> + <key>confids</key> + <string>confides</string> + <key>configureable</key> + <string>configurable</string> + <key>confortable</key> + <string>comfortable</string> + <key>congradulations</key> + <string>congratulations</string> + <key>congresional</key> + <string>congressional</string> + <key>conived</key> + <string>connived</string> + <key>conjecutre</key> + <string>conjecture</string> + <key>conjuction</key> + <string>conjunction</string> + <key>conotations</key> + <string>connotations</string> + <key>conquerd</key> + <string>conquered</string> + <key>conquerer</key> + <string>conqueror</string> + <key>conquerers</key> + <string>conquerors</string> + <key>conqured</key> + <string>conquered</string> + <key>conscent</key> + <string>consent</string> + <key>consciouness</key> + <string>consciousness</string> + <key>consdider</key> + <string>consider</string> + <key>consdidered</key> + <string>considered</string> + <key>consdiered</key> + <string>considered</string> + <key>consectutive</key> + <string>consecutive</string> + <key>consenquently</key> + <string>consequently</string> + <key>consentrate</key> + <string>concentrate</string> + <key>consentrated</key> + <string>concentrated</string> + <key>consentrates</key> + <string>concentrates</string> + <key>consept</key> + <string>concept</string> + <key>consequentually</key> + <string>consequently</string> + <key>consequeseces</key> + <string>consequences</string> + <key>consern</key> + <string>concern</string> + <key>conserned</key> + <string>concerned</string> + <key>conserning</key> + <string>concerning</string> + <key>conservitive</key> + <string>conservative</string> + <key>consiciousness</key> + <string>consciousness</string> + <key>consicousness</key> + <string>consciousness</string> + <key>considerd</key> + <string>considered</string> + <key>consideres</key> + <string>considered</string> + <key>consious</key> + <string>conscious</string> + <key>consistant</key> + <string>consistent</string> + <key>consistantly</key> + <string>consistently</string> + <key>consituencies</key> + <string>constituencies</string> + <key>consituency</key> + <string>constituency</string> + <key>consituted</key> + <string>constituted</string> + <key>consitution</key> + <string>constitution</string> + <key>consitutional</key> + <string>constitutional</string> + <key>consolodate</key> + <string>consolidate</string> + <key>consolodated</key> + <string>consolidated</string> + <key>consonent</key> + <string>consonant</string> + <key>consonents</key> + <string>consonants</string> + <key>consorcium</key> + <string>consortium</string> + <key>conspiracys</key> + <string>conspiracies</string> + <key>conspiriator</key> + <string>conspirator</string> + <key>constaints</key> + <string>constraints</string> + <key>constanly</key> + <string>constantly</string> + <key>constarnation</key> + <string>consternation</string> + <key>constatn</key> + <string>constant</string> + <key>constinually</key> + <string>continually</string> + <key>constituant</key> + <string>constituent</string> + <key>constituants</key> + <string>constituents</string> + <key>constituion</key> + <string>constitution</string> + <key>constituional</key> + <string>constitutional</string> + <key>consttruction</key> + <string>construction</string> + <key>constuction</key> + <string>construction</string> + <key>consulant</key> + <string>consultant</string> + <key>consumate</key> + <string>consummate</string> + <key>consumated</key> + <string>consummated</string> + <key>contaiminate</key> + <string>contaminate</string> + <key>containes</key> + <string>contains</string> + <key>contamporaries</key> + <string>contemporaries</string> + <key>contamporary</key> + <string>contemporary</string> + <key>contempoary</key> + <string>contemporary</string> + <key>contemporaneus</key> + <string>contemporaneous</string> + <key>contempory</key> + <string>contemporary</string> + <key>contendor</key> + <string>contender</string> + <key>contibute</key> + <string>contribute </string> + <key>contibuted</key> + <string>contributed </string> + <key>contibutes</key> + <string>contributes </string> + <key>contigent</key> + <string>contingent</string> + <key>contined</key> + <string>continued</string> + <key>continous</key> + <string>continuous</string> + <key>continously</key> + <string>continuously</string> + <key>continueing</key> + <string>continuing</string> + <key>contravercial</key> + <string>controversial</string> + <key>contraversy</key> + <string>controversy</string> + <key>contributer</key> + <string>contributor</string> + <key>contributers</key> + <string>contributors</string> + <key>contritutions</key> + <string>contributions</string> + <key>controled</key> + <string>controlled</string> + <key>controling</key> + <string>controlling</string> + <key>controll</key> + <string>control</string> + <key>controlls</key> + <string>controls</string> + <key>controvercial</key> + <string>controversial</string> + <key>controvercy</key> + <string>controversy</string> + <key>controveries</key> + <string>controversies</string> + <key>controversal</key> + <string>controversial</string> + <key>controversey</key> + <string>controversy</string> + <key>controvertial</key> + <string>controversial</string> + <key>controvery</key> + <string>controversy</string> + <key>contruction</key> + <string>construction</string> + <key>conveinent</key> + <string>convenient</string> + <key>convenant</key> + <string>covenant</string> + <key>convential</key> + <string>conventional</string> + <key>convertables</key> + <string>convertibles</string> + <key>convertion</key> + <string>conversion</string> + <key>conveyer</key> + <string>conveyor</string> + <key>conviced</key> + <string>convinced</string> + <key>convienient</key> + <string>convenient</string> + <key>coordiantion</key> + <string>coordination</string> + <key>coorperations</key> + <string>corporations</string> + <key>copmetitors</key> + <string>competitors</string> + <key>coputer</key> + <string>computer</string> + <key>copywrite</key> + <string>copyright</string> + <key>coridal</key> + <string>cordial</string> + <key>cornmitted</key> + <string>committed</string> + <key>corosion</key> + <string>corrosion</string> + <key>corparate</key> + <string>corporate</string> + <key>corperations</key> + <string>corporations</string> + <key>correcters</key> + <string>correctors</string> + <key>correponding</key> + <string>corresponding</string> + <key>correposding</key> + <string>corresponding</string> + <key>correspondant</key> + <string>correspondent</string> + <key>correspondants</key> + <string>correspondents</string> + <key>corridoors</key> + <string>corridors</string> + <key>corrispond</key> + <string>correspond</string> + <key>corrispondant</key> + <string>correspondent</string> + <key>corrispondants</key> + <string>correspondents</string> + <key>corrisponded</key> + <string>corresponded</string> + <key>corrisponding</key> + <string>corresponding</string> + <key>corrisponds</key> + <string>corresponds</string> + <key>costitution</key> + <string>constitution</string> + <key>coucil</key> + <string>council</string> + <key>counries</key> + <string>countries</string> + <key>countains</key> + <string>contains</string> + <key>countires</key> + <string>countries</string> + <key>coururier</key> + <string>courier</string> + <key>coverted</key> + <string>converted</string> + <key>cpoy</key> + <string>copy</string> + <key>creaeted</key> + <string>created</string> + <key>creedence</key> + <string>credence</string> + <key>critereon</key> + <string>criterion</string> + <key>criterias</key> + <string>criteria</string> + <key>criticists</key> + <string>critics</string> + <key>critising</key> + <string>criticising</string> + <key>critisising</key> + <string>criticising</string> + <key>critisism</key> + <string>criticism</string> + <key>critisisms</key> + <string>criticisms</string> + <key>critisize</key> + <string>criticise</string> + <key>critisized</key> + <string>criticised</string> + <key>critisizes</key> + <string>criticises</string> + <key>critisizing</key> + <string>criticising</string> + <key>critized</key> + <string>criticized</string> + <key>critizing</key> + <string>criticizing</string> + <key>crockodiles</key> + <string>crocodiles</string> + <key>crowm</key> + <string>crown</string> + <key>crtical</key> + <string>critical</string> + <key>crticised</key> + <string>criticised</string> + <key>crucifiction</key> + <string>crucifixion</string> + <key>crusies</key> + <string>cruises</string> + <key>crystalisation</key> + <string>crystallisation</string> + <key>culiminating</key> + <string>culminating</string> + <key>cumulatative</key> + <string>cumulative</string> + <key>curch</key> + <string>church</string> + <key>curcuit</key> + <string>circuit</string> + <key>currenly</key> + <string>currently</string> + <key>curriculem</key> + <string>curriculum</string> + <key>cxan</key> + <string>cyan</string> + <key>cyclinder</key> + <string>cylinder</string> + <key>dacquiri</key> + <string>daiquiri</string> + <key>dael</key> + <string>deal</string> + <key>dalmation</key> + <string>dalmatian</string> + <key>damenor</key> + <string>demeanor</string> + <key>dammage</key> + <string>damage</string> + <key>daugher</key> + <string>daughter</string> + <key>debateable</key> + <string>debatable</string> + <key>decendant</key> + <string>descendant</string> + <key>decendants</key> + <string>descendants</string> + <key>decendent</key> + <string>descendant</string> + <key>decendents</key> + <string>descendants</string> + <key>decideable</key> + <string>decidable</string> + <key>decidely</key> + <string>decidedly</string> + <key>decieved</key> + <string>deceived</string> + <key>decison</key> + <string>decision</string> + <key>decomissioned</key> + <string>decommissioned</string> + <key>decomposit</key> + <string>decompose</string> + <key>decomposited</key> + <string>decomposed</string> + <key>decompositing</key> + <string>decomposing</string> + <key>decomposits</key> + <string>decomposes</string> + <key>decress</key> + <string>decrees</string> + <key>decribe</key> + <string>describe</string> + <key>decribed</key> + <string>described</string> + <key>decribes</key> + <string>describes</string> + <key>decribing</key> + <string>describing</string> + <key>dectect</key> + <string>detect</string> + <key>defendent</key> + <string>defendant</string> + <key>defendents</key> + <string>defendants</string> + <key>deffensively</key> + <string>defensively</string> + <key>deffine</key> + <string>define</string> + <key>deffined</key> + <string>defined</string> + <key>definance</key> + <string>defiance</string> + <key>definate</key> + <string>definite</string> + <key>definately</key> + <string>definitely</string> + <key>definatly</key> + <string>definitely</string> + <key>definetly</key> + <string>definitely</string> + <key>definining</key> + <string>defining</string> + <key>definit</key> + <string>definite</string> + <key>definitly</key> + <string>definitely</string> + <key>definiton</key> + <string>definition</string> + <key>defintion</key> + <string>definition</string> + <key>degrate</key> + <string>degrade</string> + <key>delagates</key> + <string>delegates</string> + <key>delapidated</key> + <string>dilapidated</string> + <key>delerious</key> + <string>delirious</string> + <key>delevopment</key> + <string>development</string> + <key>deliberatly</key> + <string>deliberately</string> + <key>delusionally</key> + <string>delusively</string> + <key>demenor</key> + <string>demeanor</string> + <key>demographical</key> + <string>demographic</string> + <key>demolision</key> + <string>demolition</string> + <key>demorcracy</key> + <string>democracy</string> + <key>demostration</key> + <string>demonstration</string> + <key>denegrating</key> + <string>denigrating</string> + <key>densly</key> + <string>densely</string> + <key>deparment</key> + <string>department</string> + <key>deparmental</key> + <string>departmental</string> + <key>deparments</key> + <string>departments</string> + <key>dependance</key> + <string>dependence</string> + <key>dependancy</key> + <string>dependency</string> + <key>dependant</key> + <string>dependent</string> + <key>deram</key> + <string>dream</string> + <key>deriviated</key> + <string>derived</string> + <key>derivitive</key> + <string>derivative</string> + <key>derogitory</key> + <string>derogatory</string> + <key>descendands</key> + <string>descendants</string> + <key>descibed</key> + <string>described</string> + <key>descision</key> + <string>decision</string> + <key>descisions</key> + <string>decisions</string> + <key>descriibes</key> + <string>describes</string> + <key>descripters</key> + <string>descriptors</string> + <key>descripton</key> + <string>description</string> + <key>desctruction</key> + <string>destruction</string> + <key>descuss</key> + <string>discuss</string> + <key>desgined</key> + <string>designed</string> + <key>deside</key> + <string>decide</string> + <key>desigining</key> + <string>designing</string> + <key>desinations</key> + <string>destinations</string> + <key>desintegrated</key> + <string>disintegrated</string> + <key>desintegration</key> + <string>disintegration</string> + <key>desireable</key> + <string>desirable</string> + <key>desitned</key> + <string>destined</string> + <key>desktiop</key> + <string>desktop</string> + <key>desorder</key> + <string>disorder</string> + <key>desoriented</key> + <string>disoriented</string> + <key>desparate</key> + <string>desperate</string> + <key>despict</key> + <string>depict</string> + <key>despiration</key> + <string>desperation</string> + <key>dessicated</key> + <string>desiccated</string> + <key>dessigned</key> + <string>designed</string> + <key>destablized</key> + <string>destabilized</string> + <key>destory</key> + <string>destroy</string> + <key>detailled</key> + <string>detailed</string> + <key>detatched</key> + <string>detached</string> + <key>deteoriated</key> + <string>deteriorated</string> + <key>deteriate</key> + <string>deteriorate</string> + <key>deterioriating</key> + <string>deteriorating</string> + <key>determinining</key> + <string>determining</string> + <key>detremental</key> + <string>detrimental</string> + <key>devasted</key> + <string>devastated</string> + <key>develope</key> + <string>develop</string> + <key>developement</key> + <string>development</string> + <key>developped</key> + <string>developed</string> + <key>develpment</key> + <string>development</string> + <key>devels</key> + <string>delves</string> + <key>devestated</key> + <string>devastated</string> + <key>devestating</key> + <string>devastating</string> + <key>devide</key> + <string>divide</string> + <key>devided</key> + <string>divided</string> + <key>devistating</key> + <string>devastating</string> + <key>devolopement</key> + <string>development</string> + <key>diablical</key> + <string>diabolical</string> + <key>diamons</key> + <string>diamonds</string> + <key>diaster</key> + <string>disaster</string> + <key>dichtomy</key> + <string>dichotomy</string> + <key>diconnects</key> + <string>disconnects</string> + <key>dicover</key> + <string>discover</string> + <key>dicovered</key> + <string>discovered</string> + <key>dicovering</key> + <string>discovering</string> + <key>dicovers</key> + <string>discovers</string> + <key>dicovery</key> + <string>discovery</string> + <key>dicussed</key> + <string>discussed</string> + <key>didnt</key> + <string>didn't</string> + <key>diea</key> + <string>idea</string> + <key>dieing</key> + <string>dying</string> + <key>dieties</key> + <string>deities</string> + <key>diety</key> + <string>deity</string> + <key>diferent</key> + <string>different</string> + <key>diferrent</key> + <string>different</string> + <key>differentiatiations</key> + <string>differentiations</string> + <key>differnt</key> + <string>different</string> + <key>difficulity</key> + <string>difficulty</string> + <key>diffrent</key> + <string>different</string> + <key>dificulties</key> + <string>difficulties</string> + <key>dificulty</key> + <string>difficulty</string> + <key>dimenions</key> + <string>dimensions</string> + <key>dimention</key> + <string>dimension</string> + <key>dimentional</key> + <string>dimensional</string> + <key>dimentions</key> + <string>dimensions</string> + <key>dimesnional</key> + <string>dimensional</string> + <key>diminuitive</key> + <string>diminutive</string> + <key>dimunitive</key> + <string>diminutive</string> + <key>diosese</key> + <string>diocese</string> + <key>diphtong</key> + <string>diphthong</string> + <key>diphtongs</key> + <string>diphthongs</string> + <key>diplomancy</key> + <string>diplomacy</string> + <key>dipthong</key> + <string>diphthong</string> + <key>dipthongs</key> + <string>diphthongs</string> + <key>dirived</key> + <string>derived</string> + <key>disagreeed</key> + <string>disagreed</string> + <key>disapeared</key> + <string>disappeared</string> + <key>disapointing</key> + <string>disappointing</string> + <key>disappearred</key> + <string>disappeared</string> + <key>disaproval</key> + <string>disapproval</string> + <key>disasterous</key> + <string>disastrous</string> + <key>disatisfaction</key> + <string>dissatisfaction</string> + <key>disatisfied</key> + <string>dissatisfied</string> + <key>disatrous</key> + <string>disastrous</string> + <key>discontentment</key> + <string>discontent</string> + <key>discribe</key> + <string>describe</string> + <key>discribed</key> + <string>described</string> + <key>discribes</key> + <string>describes</string> + <key>discribing</key> + <string>describing</string> + <key>disctinction</key> + <string>distinction</string> + <key>disctinctive</key> + <string>distinctive</string> + <key>disemination</key> + <string>dissemination</string> + <key>disenchanged</key> + <string>disenchanted</string> + <key>disiplined</key> + <string>disciplined</string> + <key>disobediance</key> + <string>disobedience</string> + <key>disobediant</key> + <string>disobedient</string> + <key>disolved</key> + <string>dissolved</string> + <key>disover</key> + <string>discover</string> + <key>dispair</key> + <string>despair</string> + <key>disparingly</key> + <string>disparagingly</string> + <key>dispence</key> + <string>dispense</string> + <key>dispenced</key> + <string>dispensed</string> + <key>dispencing</key> + <string>dispensing</string> + <key>dispicable</key> + <string>despicable</string> + <key>dispite</key> + <string>despite</string> + <key>dispostion</key> + <string>disposition</string> + <key>disproportiate</key> + <string>disproportionate</string> + <key>disputandem</key> + <string>disputandum</string> + <key>disricts</key> + <string>districts</string> + <key>dissagreement</key> + <string>disagreement</string> + <key>dissapear</key> + <string>disappear</string> + <key>dissapearance</key> + <string>disappearance</string> + <key>dissapeared</key> + <string>disappeared</string> + <key>dissapearing</key> + <string>disappearing</string> + <key>dissapears</key> + <string>disappears</string> + <key>dissappear</key> + <string>disappear</string> + <key>dissappears</key> + <string>disappears</string> + <key>dissappointed</key> + <string>disappointed</string> + <key>dissarray</key> + <string>disarray</string> + <key>dissobediance</key> + <string>disobedience</string> + <key>dissobediant</key> + <string>disobedient</string> + <key>dissobedience</key> + <string>disobedience</string> + <key>dissobedient</key> + <string>disobedient</string> + <key>distiction</key> + <string>distinction</string> + <key>distingish</key> + <string>distinguish</string> + <key>distingished</key> + <string>distinguished</string> + <key>distingishes</key> + <string>distinguishes</string> + <key>distingishing</key> + <string>distinguishing</string> + <key>distingquished</key> + <string>distinguished</string> + <key>distrubution</key> + <string>distribution</string> + <key>distruction</key> + <string>destruction</string> + <key>distructive</key> + <string>destructive</string> + <key>ditributed</key> + <string>distributed</string> + <key>diversed</key> + <string>diverged</string> + <key>divice</key> + <string>device</string> + <key>divison</key> + <string>division</string> + <key>divisons</key> + <string>divisions</string> + <key>doccument</key> + <string>document</string> + <key>doccumented</key> + <string>documented</string> + <key>doccuments</key> + <string>documents</string> + <key>docrines</key> + <string>doctrines</string> + <key>doctines</key> + <string>doctrines</string> + <key>documenatry</key> + <string>documentary</string> + <key>doens</key> + <string>does</string> + <key>doesnt</key> + <string>doesn't</string> + <key>doign</key> + <string>doing</string> + <key>dominaton</key> + <string>domination</string> + <key>dominent</key> + <string>dominant</string> + <key>dominiant</key> + <string>dominant</string> + <key>donig</key> + <string>doing</string> + <key>dont</key> + <string>don't</string> + <key>dosen't</key> + <string>doesn't</string> + <key>doub</key> + <string>doubt</string> + <key>doulbe</key> + <string>double</string> + <key>dowloads</key> + <string>downloads</string> + <key>dramtic</key> + <string>dramatic</string> + <key>draughtman</key> + <string>draughtsman</string> + <key>dreasm</key> + <string>dreams</string> + <key>driectly</key> + <string>directly</string> + <key>drnik</key> + <string>drink</string> + <key>druming</key> + <string>drumming</string> + <key>drummless</key> + <string>drumless</string> + <key>dupicate</key> + <string>duplicate</string> + <key>durig</key> + <string>during</string> + <key>durring</key> + <string>during</string> + <key>duting</key> + <string>during</string> + <key>dyas</key> + <string>dryas</string> + <key>eahc</key> + <string>each</string> + <key>ealier</key> + <string>earlier</string> + <key>earlies</key> + <string>earliest</string> + <key>earnt</key> + <string>earned</string> + <key>ecclectic</key> + <string>eclectic</string> + <key>eceonomy</key> + <string>economy</string> + <key>ecidious</key> + <string>deciduous</string> + <key>eclispe</key> + <string>eclipse</string> + <key>ecomonic</key> + <string>economic</string> + <key>ect</key> + <string>etc</string> + <key>eearly</key> + <string>early</string> + <key>efel</key> + <string>evil</string> + <key>effeciency</key> + <string>efficiency</string> + <key>effecient</key> + <string>efficient</string> + <key>effeciently</key> + <string>efficiently</string> + <key>efficency</key> + <string>efficiency</string> + <key>efficent</key> + <string>efficient</string> + <key>efficently</key> + <string>efficiently</string> + <key>efford</key> + <string>effort</string> + <key>effords</key> + <string>efforts</string> + <key>effulence</key> + <string>effluence</string> + <key>eigth</key> + <string>eight</string> + <key>eiter</key> + <string>either</string> + <key>elction</key> + <string>election</string> + <key>electic</key> + <string>electric</string> + <key>electon</key> + <string>electron</string> + <key>electrial</key> + <string>electrical</string> + <key>electricly</key> + <string>electrically</string> + <key>electricty</key> + <string>electricity</string> + <key>elementay</key> + <string>elementary</string> + <key>eleminated</key> + <string>eliminated</string> + <key>eleminating</key> + <string>eliminating</string> + <key>eles</key> + <string>eels</string> + <key>eletricity</key> + <string>electricity</string> + <key>elicided</key> + <string>elicited</string> + <key>eligable</key> + <string>eligible</string> + <key>elimentary</key> + <string>elementary</string> + <key>ellected</key> + <string>elected</string> + <key>elphant</key> + <string>elephant</string> + <key>embarass</key> + <string>embarrass</string> + <key>embarassed</key> + <string>embarrassed</string> + <key>embarassing</key> + <string>embarrassing</string> + <key>embarassment</key> + <string>embarrassment</string> + <key>embargos</key> + <string>embargoes</string> + <key>embarras</key> + <string>embarrass</string> + <key>embarrased</key> + <string>embarrassed</string> + <key>embarrasing</key> + <string>embarrassing</string> + <key>embarrasment</key> + <string>embarrassment</string> + <key>embezelled</key> + <string>embezzled</string> + <key>emblamatic</key> + <string>emblematic</string> + <key>eminate</key> + <string>emanate</string> + <key>eminated</key> + <string>emanated</string> + <key>emision</key> + <string>emission</string> + <key>emited</key> + <string>emitted</string> + <key>emiting</key> + <string>emitting</string> + <key>emition</key> + <string>emission</string> + <key>emmediately</key> + <string>immediately</string> + <key>emmigrated</key> + <string>immigrated</string> + <key>emminently</key> + <string>eminently</string> + <key>emmisaries</key> + <string>emissaries</string> + <key>emmisarries</key> + <string>emissaries</string> + <key>emmisarry</key> + <string>emissary</string> + <key>emmisary</key> + <string>emissary</string> + <key>emmision</key> + <string>emission</string> + <key>emmisions</key> + <string>emissions</string> + <key>emmited</key> + <string>emitted</string> + <key>emmiting</key> + <string>emitting</string> + <key>emmitted</key> + <string>emitted</string> + <key>emmitting</key> + <string>emitting</string> + <key>emnity</key> + <string>enmity</string> + <key>emperical</key> + <string>empirical</string> + <key>emphaised</key> + <string>emphasised</string> + <key>emphsis</key> + <string>emphasis</string> + <key>emphysyma</key> + <string>emphysema</string> + <key>emprisoned</key> + <string>imprisoned</string> + <key>enameld</key> + <string>enameled</string> + <key>enchancement</key> + <string>enhancement</string> + <key>encouraing</key> + <string>encouraging</string> + <key>encryptiion</key> + <string>encryption</string> + <key>encylopedia</key> + <string>encyclopedia</string> + <key>endevors</key> + <string>endeavors</string> + <key>endevour</key> + <string>endeavour</string> + <key>endig</key> + <string>ending</string> + <key>endolithes</key> + <string>endoliths</string> + <key>enduce</key> + <string>induce</string> + <key>ened</key> + <string>need</string> + <key>enflamed</key> + <string>inflamed</string> + <key>enforceing</key> + <string>enforcing</string> + <key>engagment</key> + <string>engagement</string> + <key>engeneer</key> + <string>engineer</string> + <key>engeneering</key> + <string>engineering</string> + <key>engieneer</key> + <string>engineer</string> + <key>engieneers</key> + <string>engineers</string> + <key>enlargment</key> + <string>enlargement</string> + <key>enlargments</key> + <string>enlargements</string> + <key>enourmous</key> + <string>enormous</string> + <key>enourmously</key> + <string>enormously</string> + <key>ensconsed</key> + <string>ensconced</string> + <key>entaglements</key> + <string>entanglements</string> + <key>enteratinment</key> + <string>entertainment</string> + <key>enthusiatic</key> + <string>enthusiastic</string> + <key>entitity</key> + <string>entity</string> + <key>entitlied</key> + <string>entitled</string> + <key>entrepeneur</key> + <string>entrepreneur</string> + <key>entrepeneurs</key> + <string>entrepreneurs</string> + <key>enviorment</key> + <string>environment</string> + <key>enviormental</key> + <string>environmental</string> + <key>enviormentally</key> + <string>environmentally</string> + <key>enviorments</key> + <string>environments</string> + <key>enviornment</key> + <string>environment</string> + <key>enviornmental</key> + <string>environmental</string> + <key>enviornmentalist</key> + <string>environmentalist</string> + <key>enviornmentally</key> + <string>environmentally</string> + <key>enviornments</key> + <string>environments</string> + <key>enviroment</key> + <string>environment</string> + <key>enviromental</key> + <string>environmental</string> + <key>enviromentalist</key> + <string>environmentalist</string> + <key>enviromentally</key> + <string>environmentally</string> + <key>enviroments</key> + <string>environments</string> + <key>envolutionary</key> + <string>evolutionary</string> + <key>envrionments</key> + <string>environments</string> + <key>enxt</key> + <string>next</string> + <key>epidsodes</key> + <string>episodes</string> + <key>epsiode</key> + <string>episode</string> + <key>equialent</key> + <string>equivalent</string> + <key>equilibium</key> + <string>equilibrium</string> + <key>equilibrum</key> + <string>equilibrium</string> + <key>equiped</key> + <string>equipped</string> + <key>equippment</key> + <string>equipment</string> + <key>equitorial</key> + <string>equatorial</string> + <key>equivelant</key> + <string>equivalent</string> + <key>equivelent</key> + <string>equivalent</string> + <key>equivilant</key> + <string>equivalent</string> + <key>equivilent</key> + <string>equivalent</string> + <key>equivlalent</key> + <string>equivalent</string> + <key>erally</key> + <string>really</string> + <key>eratic</key> + <string>erratic</string> + <key>eratically</key> + <string>erratically</string> + <key>eraticly</key> + <string>erratically</string> + <key>errupted</key> + <string>erupted</string> + <key>esential</key> + <string>essential</string> + <key>esitmated</key> + <string>estimated</string> + <key>esle</key> + <string>else</string> + <key>especialy</key> + <string>especially</string> + <key>essencial</key> + <string>essential</string> + <key>essense</key> + <string>essence</string> + <key>essentail</key> + <string>essential</string> + <key>essentialy</key> + <string>essentially</string> + <key>essentual</key> + <string>essential</string> + <key>essesital</key> + <string>essential</string> + <key>estabishes</key> + <string>establishes</string> + <key>establising</key> + <string>establishing</string> + <key>ethnocentricm</key> + <string>ethnocentrism</string> + <key>ethose</key> + <string>those</string> + <key>evenhtually</key> + <string>eventually</string> + <key>eventally</key> + <string>eventually</string> + <key>eventhough</key> + <string>even though</string> + <key>eventially</key> + <string>eventually</string> + <key>eventualy</key> + <string>eventually</string> + <key>everthing</key> + <string>everything</string> + <key>everytime</key> + <string>every time</string> + <key>everyting</key> + <string>everything</string> + <key>eveyr</key> + <string>every</string> + <key>evidentally</key> + <string>evidently</string> + <key>exagerate</key> + <string>exaggerate</string> + <key>exagerated</key> + <string>exaggerated</string> + <key>exagerates</key> + <string>exaggerates</string> + <key>exagerating</key> + <string>exaggerating</string> + <key>exagerrate</key> + <string>exaggerate</string> + <key>exagerrated</key> + <string>exaggerated</string> + <key>exagerrates</key> + <string>exaggerates</string> + <key>exagerrating</key> + <string>exaggerating</string> + <key>examinated</key> + <string>examined</string> + <key>exampt</key> + <string>exempt</string> + <key>exapansion</key> + <string>expansion</string> + <key>excact</key> + <string>exact</string> + <key>excange</key> + <string>exchange</string> + <key>excecute</key> + <string>execute</string> + <key>excecuted</key> + <string>executed</string> + <key>excecutes</key> + <string>executes</string> + <key>excecuting</key> + <string>executing</string> + <key>excecution</key> + <string>execution</string> + <key>excedded</key> + <string>exceeded</string> + <key>excelent</key> + <string>excellent</string> + <key>excell</key> + <string>excel</string> + <key>excellance</key> + <string>excellence</string> + <key>excellant</key> + <string>excellent</string> + <key>excells</key> + <string>excels</string> + <key>excercise</key> + <string>exercise</string> + <key>exchanching</key> + <string>exchanging</string> + <key>excisted</key> + <string>existed</string> + <key>exculsivly</key> + <string>exclusively</string> + <key>execising</key> + <string>exercising</string> + <key>exection</key> + <string>execution</string> + <key>exectued</key> + <string>executed</string> + <key>exeedingly</key> + <string>exceedingly</string> + <key>exelent</key> + <string>excellent</string> + <key>exellent</key> + <string>excellent</string> + <key>exemple</key> + <string>example</string> + <key>exept</key> + <string>except</string> + <key>exeptional</key> + <string>exceptional</string> + <key>exerbate</key> + <string>exacerbate</string> + <key>exerbated</key> + <string>exacerbated</string> + <key>exerciese</key> + <string>exercises</string> + <key>exerpt</key> + <string>excerpt</string> + <key>exerpts</key> + <string>excerpts</string> + <key>exersize</key> + <string>exercise</string> + <key>exerternal</key> + <string>external</string> + <key>exhalted</key> + <string>exalted</string> + <key>exhibtion</key> + <string>exhibition</string> + <key>exibition</key> + <string>exhibition</string> + <key>exibitions</key> + <string>exhibitions</string> + <key>exicting</key> + <string>exciting</string> + <key>exinct</key> + <string>extinct</string> + <key>existance</key> + <string>existence</string> + <key>existant</key> + <string>existent</string> + <key>existince</key> + <string>existence</string> + <key>exliled</key> + <string>exiled</string> + <key>exludes</key> + <string>excludes</string> + <key>exmaple</key> + <string>example</string> + <key>exonorate</key> + <string>exonerate</string> + <key>exoskelaton</key> + <string>exoskeleton</string> + <key>expalin</key> + <string>explain</string> + <key>expatriot</key> + <string>expatriate</string> + <key>expeced</key> + <string>expected</string> + <key>expecially</key> + <string>especially</string> + <key>expeditonary</key> + <string>expeditionary</string> + <key>expeiments</key> + <string>experiments</string> + <key>expell</key> + <string>expel</string> + <key>expells</key> + <string>expels</string> + <key>experiance</key> + <string>experience</string> + <key>experianced</key> + <string>experienced</string> + <key>expiditions</key> + <string>expeditions</string> + <key>expierence</key> + <string>experience</string> + <key>explaination</key> + <string>explanation</string> + <key>explaning</key> + <string>explaining</string> + <key>explictly</key> + <string>explicitly</string> + <key>exploititive</key> + <string>exploitative</string> + <key>explotation</key> + <string>exploitation</string> + <key>expropiated</key> + <string>expropriated</string> + <key>expropiation</key> + <string>expropriation</string> + <key>exressed</key> + <string>expressed</string> + <key>extemely</key> + <string>extremely</string> + <key>extention</key> + <string>extension</string> + <key>extentions</key> + <string>extensions</string> + <key>extered</key> + <string>exerted</string> + <key>extermist</key> + <string>extremist</string> + <key>extint</key> + <string>extinct</string> + <key>extradiction</key> + <string>extradition</string> + <key>extraterrestial</key> + <string>extraterrestrial</string> + <key>extraterrestials</key> + <string>extraterrestrials</string> + <key>extravagent</key> + <string>extravagant</string> + <key>extrememly</key> + <string>extremely</string> + <key>extremeophile</key> + <string>extremophile</string> + <key>extremly</key> + <string>extremely</string> + <key>extrordinarily</key> + <string>extraordinarily</string> + <key>extrordinary</key> + <string>extraordinary</string> + <key>eyar</key> + <string>year</string> + <key>eyars</key> + <string>years</string> + <key>eyasr</key> + <string>years</string> + <key>faciliate</key> + <string>facilitate</string> + <key>faciliated</key> + <string>facilitated</string> + <key>faciliates</key> + <string>facilitates</string> + <key>facilites</key> + <string>facilities</string> + <key>facillitate</key> + <string>facilitate</string> + <key>facinated</key> + <string>fascinated</string> + <key>facist</key> + <string>fascist</string> + <key>familes</key> + <string>families</string> + <key>familliar</key> + <string>familiar</string> + <key>famoust</key> + <string>famous</string> + <key>fanatism</key> + <string>fanaticism</string> + <key>fatc</key> + <string>fact</string> + <key>faught</key> + <string>fought</string> + <key>favoutrable</key> + <string>favourable</string> + <key>feasable</key> + <string>feasible</string> + <key>fedreally</key> + <string>federally</string> + <key>feromone</key> + <string>pheromone</string> + <key>fertily</key> + <string>fertility</string> + <key>fianite</key> + <string>finite</string> + <key>fianlly</key> + <string>finally</string> + <key>ficticious</key> + <string>fictitious</string> + <key>fictious</key> + <string>fictitious</string> + <key>fidn</key> + <string>find</string> + <key>fiercly</key> + <string>fiercely</string> + <key>fightings</key> + <string>fighting</string> + <key>filiament</key> + <string>filament</string> + <key>fimilies</key> + <string>families</string> + <key>finacial</key> + <string>financial</string> + <key>finaly</key> + <string>finally</string> + <key>financialy</key> + <string>financially</string> + <key>firends</key> + <string>friends</string> + <key>firts</key> + <string>first</string> + <key>fisionable</key> + <string>fissionable</string> + <key>flamable</key> + <string>flammable</string> + <key>flawess</key> + <string>flawless</string> + <key>fleed</key> + <string>fled</string> + <key>florescent</key> + <string>fluorescent</string> + <key>flourescent</key> + <string>fluorescent</string> + <key>flourine</key> + <string>fluorine</string> + <key>fluorish</key> + <string>flourish</string> + <key>follwoing</key> + <string>following</string> + <key>folowing</key> + <string>following</string> + <key>fomed</key> + <string>formed</string> + <key>fomr</key> + <string>from</string> + <key>fonetic</key> + <string>phonetic</string> + <key>fontrier</key> + <string>fontier</string> + <key>foootball</key> + <string>football</string> + <key>forbad</key> + <string>forbade</string> + <key>forbiden</key> + <string>forbidden</string> + <key>foreward</key> + <string>foreword</string> + <key>forfiet</key> + <string>forfeit</string> + <key>forhead</key> + <string>forehead</string> + <key>foriegn</key> + <string>foreign</string> + <key>formallize</key> + <string>formalize</string> + <key>formallized</key> + <string>formalized</string> + <key>formaly</key> + <string>formally</string> + <key>formelly</key> + <string>formerly</string> + <key>formidible</key> + <string>formidable</string> + <key>formost</key> + <string>foremost</string> + <key>forsaw</key> + <string>foresaw</string> + <key>forseeable</key> + <string>foreseeable</string> + <key>fortelling</key> + <string>foretelling</string> + <key>forunner</key> + <string>forerunner</string> + <key>foucs</key> + <string>focus</string> + <key>foudn</key> + <string>found</string> + <key>fougth</key> + <string>fought</string> + <key>foundaries</key> + <string>foundries</string> + <key>foundary</key> + <string>foundry</string> + <key>fourties</key> + <string>forties</string> + <key>fourty</key> + <string>forty</string> + <key>fouth</key> + <string>fourth</string> + <key>foward</key> + <string>forward</string> + <key>freind</key> + <string>friend</string> + <key>freindly</key> + <string>friendly</string> + <key>frequentily</key> + <string>frequently</string> + <key>frome</key> + <string>from</string> + <key>fromed</key> + <string>formed</string> + <key>froniter</key> + <string>frontier</string> + <key>fucntion</key> + <string>function</string> + <key>fucntioning</key> + <string>functioning</string> + <key>fufill</key> + <string>fulfill</string> + <key>fufilled</key> + <string>fulfilled</string> + <key>fulfiled</key> + <string>fulfilled</string> + <key>fullfill</key> + <string>fulfill</string> + <key>fullfilled</key> + <string>fulfilled</string> + <key>fundametal</key> + <string>fundamental</string> + <key>fundametals</key> + <string>fundamentals</string> + <key>funguses</key> + <string>fungi</string> + <key>funtion</key> + <string>function</string> + <key>furuther</key> + <string>further</string> + <key>futher</key> + <string>further</string> + <key>futhermore</key> + <string>furthermore</string> + <key>galatic</key> + <string>galactic</string> + <key>gallaxies</key> + <string>galaxies</string> + <key>galvinized</key> + <string>galvanized</string> + <key>ganerate</key> + <string>generate</string> + <key>ganes</key> + <string>games</string> + <key>ganster</key> + <string>gangster</string> + <key>garantee</key> + <string>guarantee</string> + <key>garanteed</key> + <string>guaranteed</string> + <key>garantees</key> + <string>guarantees</string> + <key>garnison</key> + <string>garrison</string> + <key>gaurantee</key> + <string>guarantee</string> + <key>gauranteed</key> + <string>guaranteed</string> + <key>gaurantees</key> + <string>guarantees</string> + <key>gaurd</key> + <string>guard</string> + <key>gaurentee</key> + <string>guarantee</string> + <key>gaurenteed</key> + <string>guaranteed</string> + <key>gaurentees</key> + <string>guarantees</string> + <key>geneological</key> + <string>genealogical</string> + <key>geneologies</key> + <string>genealogies</string> + <key>geneology</key> + <string>genealogy</string> + <key>generaly</key> + <string>generally</string> + <key>generatting</key> + <string>generating</string> + <key>genialia</key> + <string>genitalia</string> + <key>geographicial</key> + <string>geographical</string> + <key>geometrician</key> + <string>geometer</string> + <key>geometricians</key> + <string>geometers</string> + <key>gerat</key> + <string>great</string> + <key>glight</key> + <string>flight</string> + <key>gnawwed</key> + <string>gnawed</string> + <key>godess</key> + <string>goddess</string> + <key>godesses</key> + <string>goddesses</string> + <key>gogin</key> + <string>going</string> + <key>goign</key> + <string>going</string> + <key>gonig</key> + <string>going</string> + <key>gouvener</key> + <string>governor</string> + <key>govement</key> + <string>government</string> + <key>govenment</key> + <string>government</string> + <key>govenrment</key> + <string>government</string> + <key>goverance</key> + <string>governance</string> + <key>goverment</key> + <string>government</string> + <key>govermental</key> + <string>governmental</string> + <key>governer</key> + <string>governor</string> + <key>governmnet</key> + <string>government</string> + <key>govorment</key> + <string>government</string> + <key>govormental</key> + <string>governmental</string> + <key>govornment</key> + <string>government</string> + <key>gracefull</key> + <string>graceful</string> + <key>graet</key> + <string>great</string> + <key>grafitti</key> + <string>graffiti</string> + <key>gramatically</key> + <string>grammatically</string> + <key>grammaticaly</key> + <string>grammatically</string> + <key>grammer</key> + <string>grammar</string> + <key>grat</key> + <string>great</string> + <key>gratuitious</key> + <string>gratuitous</string> + <key>greatful</key> + <string>grateful</string> + <key>greatfully</key> + <string>gratefully</string> + <key>greif</key> + <string>grief</string> + <key>gridles</key> + <string>griddles</string> + <key>gropu</key> + <string>group</string> + <key>grwo</key> + <string>grow</string> + <key>guage</key> + <string>gauge</string> + <key>guarentee</key> + <string>guarantee</string> + <key>guarenteed</key> + <string>guaranteed</string> + <key>guarentees</key> + <string>guarantees</string> + <key>guerilla</key> + <string>guerrilla</string> + <key>guerillas</key> + <string>guerrillas</string> + <key>guerrila</key> + <string>guerrilla</string> + <key>guerrilas</key> + <string>guerrillas</string> + <key>guidence</key> + <string>guidance</string> + <key>gunanine</key> + <string>guanine</string> + <key>gurantee</key> + <string>guarantee</string> + <key>guranteed</key> + <string>guaranteed</string> + <key>gurantees</key> + <string>guarantees</string> + <key>guttaral</key> + <string>guttural</string> + <key>gutteral</key> + <string>guttural</string> + <key>habaeus</key> + <string>habeas</string> + <key>habeus</key> + <string>habeas</string> + <key>haemorrage</key> + <string>haemorrhage</string> + <key>haev</key> + <string>have</string> + <key>halp</key> + <string>help</string> + <key>hapen</key> + <string>happen</string> + <key>hapened</key> + <string>happened</string> + <key>hapening</key> + <string>happening</string> + <key>happend</key> + <string>happened</string> + <key>happended</key> + <string>happened</string> + <key>happenned</key> + <string>happened</string> + <key>harased</key> + <string>harassed</string> + <key>harases</key> + <string>harasses</string> + <key>harasment</key> + <string>harassment</string> + <key>harasments</key> + <string>harassments</string> + <key>harassement</key> + <string>harassment</string> + <key>harras</key> + <string>harass</string> + <key>harrased</key> + <string>harassed</string> + <key>harrases</key> + <string>harasses</string> + <key>harrasing</key> + <string>harassing</string> + <key>harrasment</key> + <string>harassment</string> + <key>harrasments</key> + <string>harassments</string> + <key>harrassed</key> + <string>harassed</string> + <key>harrasses</key> + <string>harassed</string> + <key>harrassing</key> + <string>harassing</string> + <key>harrassment</key> + <string>harassment</string> + <key>harrassments</key> + <string>harassments</string> + <key>hasnt</key> + <string>hasn't</string> + <key>haviest</key> + <string>heaviest</string> + <key>headquarer</key> + <string>headquarter</string> + <key>headquater</key> + <string>headquarter</string> + <key>headquatered</key> + <string>headquartered</string> + <key>headquaters</key> + <string>headquarters</string> + <key>healthercare</key> + <string>healthcare</string> + <key>heared</key> + <string>heard</string> + <key>heathy</key> + <string>healthy</string> + <key>heigher</key> + <string>higher</string> + <key>heirarchy</key> + <string>hierarchy</string> + <key>heiroglyphics</key> + <string>hieroglyphics</string> + <key>helment</key> + <string>helmet</string> + <key>helpfull</key> + <string>helpful</string> + <key>helpped</key> + <string>helped</string> + <key>hemmorhage</key> + <string>hemorrhage</string> + <key>herad</key> + <string>heard</string> + <key>heridity</key> + <string>heredity</string> + <key>heroe</key> + <string>hero</string> + <key>heros</key> + <string>heroes</string> + <key>hertiage</key> + <string>heritage</string> + <key>hertzs</key> + <string>hertz</string> + <key>hesistant</key> + <string>hesitant</string> + <key>heterogenous</key> + <string>heterogeneous</string> + <key>hieght</key> + <string>height</string> + <key>hierachical</key> + <string>hierarchical</string> + <key>hierachies</key> + <string>hierarchies</string> + <key>hierachy</key> + <string>hierarchy</string> + <key>hierarcical</key> + <string>hierarchical</string> + <key>hierarcy</key> + <string>hierarchy</string> + <key>hieroglph</key> + <string>hieroglyph</string> + <key>hieroglphs</key> + <string>hieroglyphs</string> + <key>higer</key> + <string>higher</string> + <key>higest</key> + <string>highest</string> + <key>higway</key> + <string>highway</string> + <key>hillarious</key> + <string>hilarious</string> + <key>himselv</key> + <string>himself</string> + <key>hinderance</key> + <string>hindrance</string> + <key>hinderence</key> + <string>hindrance</string> + <key>hindrence</key> + <string>hindrance</string> + <key>hipopotamus</key> + <string>hippopotamus</string> + <key>hismelf</key> + <string>himself</string> + <key>histocompatability</key> + <string>histocompatibility</string> + <key>historicians</key> + <string>historians</string> + <key>hitsingles</key> + <string>hit singles</string> + <key>holliday</key> + <string>holiday</string> + <key>homestate</key> + <string>home state</string> + <key>homogeneize</key> + <string>homogenize</string> + <key>homogeneized</key> + <string>homogenized</string> + <key>honory</key> + <string>honorary</string> + <key>horrifing</key> + <string>horrifying</string> + <key>hosited</key> + <string>hoisted</string> + <key>hospitible</key> + <string>hospitable</string> + <key>hounour</key> + <string>honour</string> + <key>housr</key> + <string>hours</string> + <key>howver</key> + <string>however</string> + <key>hsitorians</key> + <string>historians</string> + <key>hstory</key> + <string>history</string> + <key>hten</key> + <string>then</string> + <key>htere</key> + <string>there</string> + <key>htey</key> + <string>they</string> + <key>htikn</key> + <string>think</string> + <key>hting</key> + <string>thing</string> + <key>htink</key> + <string>think</string> + <key>htis</key> + <string>this</string> + <key>humer</key> + <string>humor</string> + <key>humerous</key> + <string>humorous</string> + <key>huminoid</key> + <string>humanoid</string> + <key>humoural</key> + <string>humoral</string> + <key>humurous</key> + <string>humorous</string> + <key>husban</key> + <string>husband</string> + <key>hvae</key> + <string>have</string> + <key>hvaing</key> + <string>having</string> + <key>hvea</key> + <string>have</string> + <key>hwihc</key> + <string>which</string> + <key>hwile</key> + <string>while</string> + <key>hwole</key> + <string>whole</string> + <key>hydogen</key> + <string>hydrogen</string> + <key>hydropile</key> + <string>hydrophile</string> + <key>hydropilic</key> + <string>hydrophilic</string> + <key>hydropobe</key> + <string>hydrophobe</string> + <key>hydropobic</key> + <string>hydrophobic</string> + <key>hygeine</key> + <string>hygiene</string> + <key>hypocracy</key> + <string>hypocrisy</string> + <key>hypocrasy</key> + <string>hypocrisy</string> + <key>hypocricy</key> + <string>hypocrisy</string> + <key>hypocrit</key> + <string>hypocrite</string> + <key>hypocrits</key> + <string>hypocrites</string> + <key>i</key> + <string>I</string> + <key>iconclastic</key> + <string>iconoclastic</string> + <key>idaeidae</key> + <string>idea</string> + <key>idaes</key> + <string>ideas</string> + <key>idealogies</key> + <string>ideologies</string> + <key>idealogy</key> + <string>ideology</string> + <key>identicial</key> + <string>identical</string> + <key>identifers</key> + <string>identifiers</string> + <key>ideosyncratic</key> + <string>idiosyncratic</string> + <key>idesa</key> + <string>ideas</string> + <key>idiosyncracy</key> + <string>idiosyncrasy</string> + <key>illegimacy</key> + <string>illegitimacy</string> + <key>illegitmate</key> + <string>illegitimate</string> + <key>illess</key> + <string>illness</string> + <key>illiegal</key> + <string>illegal</string> + <key>illution</key> + <string>illusion</string> + <key>ilness</key> + <string>illness</string> + <key>ilogical</key> + <string>illogical</string> + <key>imagenary</key> + <string>imaginary</string> + <key>imagin</key> + <string>imagine</string> + <key>imaginery</key> + <string>imaginary</string> + <key>imcomplete</key> + <string>incomplete</string> + <key>imediately</key> + <string>immediately</string> + <key>imense</key> + <string>immense</string> + <key>immediatley</key> + <string>immediately</string> + <key>immediatly</key> + <string>immediately</string> + <key>immidately</key> + <string>immediately</string> + <key>immidiately</key> + <string>immediately</string> + <key>immitate</key> + <string>imitate</string> + <key>immitated</key> + <string>imitated</string> + <key>immitating</key> + <string>imitating</string> + <key>immitator</key> + <string>imitator</string> + <key>immunosupressant</key> + <string>immunosuppressant</string> + <key>impecabbly</key> + <string>impeccably</string> + <key>impedence</key> + <string>impedance</string> + <key>implamenting</key> + <string>implementing</string> + <key>impliment</key> + <string>implement</string> + <key>implimented</key> + <string>implemented</string> + <key>imploys</key> + <string>employs</string> + <key>importamt</key> + <string>important</string> + <key>imprioned</key> + <string>imprisoned</string> + <key>imprisonned</key> + <string>imprisoned</string> + <key>improvision</key> + <string>improvisation</string> + <key>improvments</key> + <string>improvements</string> + <key>inablility</key> + <string>inability</string> + <key>inaccessable</key> + <string>inaccessible</string> + <key>inadiquate</key> + <string>inadequate</string> + <key>inadquate</key> + <string>inadequate</string> + <key>inadvertant</key> + <string>inadvertent</string> + <key>inadvertantly</key> + <string>inadvertently</string> + <key>inagurated</key> + <string>inaugurated</string> + <key>inaguration</key> + <string>inauguration</string> + <key>inappropiate</key> + <string>inappropriate</string> + <key>inaugures</key> + <string>inaugurates</string> + <key>inbalance</key> + <string>imbalance</string> + <key>inbalanced</key> + <string>imbalanced</string> + <key>inbetween</key> + <string>between</string> + <key>incarcirated</key> + <string>incarcerated</string> + <key>incidentially</key> + <string>incidentally</string> + <key>incidently</key> + <string>incidentally</string> + <key>inclreased</key> + <string>increased</string> + <key>includ</key> + <string>include</string> + <key>includng</key> + <string>including</string> + <key>incompatabilities</key> + <string>incompatibilities</string> + <key>incompatability</key> + <string>incompatibility</string> + <key>incompatable</key> + <string>incompatible</string> + <key>incompatablities</key> + <string>incompatibilities</string> + <key>incompatablity</key> + <string>incompatibility</string> + <key>incompatiblities</key> + <string>incompatibilities</string> + <key>incompatiblity</key> + <string>incompatibility</string> + <key>incompetance</key> + <string>incompetence</string> + <key>incompetant</key> + <string>incompetent</string> + <key>incomptable</key> + <string>incompatible</string> + <key>incomptetent</key> + <string>incompetent</string> + <key>inconsistant</key> + <string>inconsistent</string> + <key>incoroporated</key> + <string>incorporated</string> + <key>incorperation</key> + <string>incorporation</string> + <key>incorportaed</key> + <string>incorporated</string> + <key>incorprates</key> + <string>incorporates</string> + <key>incorruptable</key> + <string>incorruptible</string> + <key>incramentally</key> + <string>incrementally</string> + <key>increadible</key> + <string>incredible</string> + <key>incredable</key> + <string>incredible</string> + <key>inctroduce</key> + <string>introduce</string> + <key>inctroduced</key> + <string>introduced</string> + <key>incuding</key> + <string>including</string> + <key>incunabla</key> + <string>incunabula</string> + <key>indefinately</key> + <string>indefinitely</string> + <key>indefineable</key> + <string>undefinable</string> + <key>indefinitly</key> + <string>indefinitely</string> + <key>indentical</key> + <string>identical</string> + <key>indepedantly</key> + <string>independently</string> + <key>indepedence</key> + <string>independence</string> + <key>independance</key> + <string>independence</string> + <key>independant</key> + <string>independent</string> + <key>independantly</key> + <string>independently</string> + <key>independece</key> + <string>independence</string> + <key>independendet</key> + <string>independent</string> + <key>indespensable</key> + <string>indispensable</string> + <key>indespensible</key> + <string>indispensable</string> + <key>indictement</key> + <string>indictment</string> + <key>indigineous</key> + <string>indigenous</string> + <key>indipendence</key> + <string>independence</string> + <key>indipendent</key> + <string>independent</string> + <key>indipendently</key> + <string>independently</string> + <key>indispensible</key> + <string>indispensable</string> + <key>indisputible</key> + <string>indisputable</string> + <key>indisputibly</key> + <string>indisputably</string> + <key>indite</key> + <string>indict</string> + <key>individualy</key> + <string>individually</string> + <key>indpendent</key> + <string>independent</string> + <key>indpendently</key> + <string>independently</string> + <key>indulgue</key> + <string>indulge</string> + <key>indutrial</key> + <string>industrial</string> + <key>indviduals</key> + <string>individuals</string> + <key>inefficienty</key> + <string>inefficiently</string> + <key>inevatible</key> + <string>inevitable</string> + <key>inevitible</key> + <string>inevitable</string> + <key>inevititably</key> + <string>inevitably</string> + <key>infalability</key> + <string>infallibility</string> + <key>infallable</key> + <string>infallible</string> + <key>infectuous</key> + <string>infectious</string> + <key>infered</key> + <string>inferred</string> + <key>infilitrate</key> + <string>infiltrate</string> + <key>infilitrated</key> + <string>infiltrated</string> + <key>infilitration</key> + <string>infiltration</string> + <key>infinit</key> + <string>infinite</string> + <key>inflamation</key> + <string>inflammation</string> + <key>influencial</key> + <string>influential</string> + <key>influented</key> + <string>influenced</string> + <key>infomation</key> + <string>information</string> + <key>informtion</key> + <string>information</string> + <key>infrantryman</key> + <string>infantryman</string> + <key>infrigement</key> + <string>infringement</string> + <key>ingenius</key> + <string>ingenious</string> + <key>ingreediants</key> + <string>ingredients</string> + <key>inhabitans</key> + <string>inhabitants</string> + <key>inherantly</key> + <string>inherently</string> + <key>inheritence</key> + <string>inheritance</string> + <key>inital</key> + <string>initial</string> + <key>initally</key> + <string>initially</string> + <key>initation</key> + <string>initiation</string> + <key>initiaitive</key> + <string>initiative</string> + <key>inlcuding</key> + <string>including</string> + <key>inmigrant</key> + <string>immigrant</string> + <key>inmigrants</key> + <string>immigrants</string> + <key>innoculated</key> + <string>inoculated</string> + <key>inocence</key> + <string>innocence</string> + <key>inofficial</key> + <string>unofficial</string> + <key>inot</key> + <string>into</string> + <key>inpeach</key> + <string>impeach</string> + <key>inpolite</key> + <string>impolite</string> + <key>inprisonment</key> + <string>imprisonment</string> + <key>inproving</key> + <string>improving</string> + <key>insectiverous</key> + <string>insectivorous</string> + <key>insensative</key> + <string>insensitive</string> + <key>inseperable</key> + <string>inseparable</string> + <key>insistance</key> + <string>insistence</string> + <key>insitution</key> + <string>institution</string> + <key>insitutions</key> + <string>institutions</string> + <key>inspite</key> + <string>in spite</string> + <key>instade</key> + <string>instead</string> + <key>instatance</key> + <string>instance</string> + <key>institue</key> + <string>institute</string> + <key>instuction</key> + <string>instruction</string> + <key>instuments</key> + <string>instruments</string> + <key>instutionalized</key> + <string>institutionalized</string> + <key>instutions</key> + <string>intuitions</string> + <key>insurence</key> + <string>insurance</string> + <key>intelectual</key> + <string>intellectual</string> + <key>inteligence</key> + <string>intelligence</string> + <key>inteligent</key> + <string>intelligent</string> + <key>intenational</key> + <string>international</string> + <key>intented</key> + <string>intended</string> + <key>intepretation</key> + <string>interpretation</string> + <key>intepretator</key> + <string>interpretor</string> + <key>interational</key> + <string>international</string> + <key>interbread</key> + <string>interbreed</string> + <key>interchangable</key> + <string>interchangeable</string> + <key>interchangably</key> + <string>interchangeably</string> + <key>intercontinetal</key> + <string>intercontinental</string> + <key>intered</key> + <string>interred</string> + <key>interelated</key> + <string>interrelated</string> + <key>interferance</key> + <string>interference</string> + <key>interfereing</key> + <string>interfering</string> + <key>intergrated</key> + <string>integrated</string> + <key>intergration</key> + <string>integration</string> + <key>interm</key> + <string>interim</string> + <key>internation</key> + <string>international</string> + <key>interpet</key> + <string>interpret</string> + <key>interrim</key> + <string>interim</string> + <key>interrugum</key> + <string>interregnum</string> + <key>intertaining</key> + <string>entertaining</string> + <key>interupt</key> + <string>interrupt</string> + <key>intervines</key> + <string>intervenes</string> + <key>intevene</key> + <string>intervene</string> + <key>intial</key> + <string>initial</string> + <key>intially</key> + <string>initially</string> + <key>intrduced</key> + <string>introduced</string> + <key>intrest</key> + <string>interest</string> + <key>introdued</key> + <string>introduced</string> + <key>intruduced</key> + <string>introduced</string> + <key>intrument</key> + <string>instrument</string> + <key>intrumental</key> + <string>instrumental</string> + <key>intruments</key> + <string>instruments</string> + <key>intrusted</key> + <string>entrusted</string> + <key>intutive</key> + <string>intuitive</string> + <key>intutively</key> + <string>intuitively</string> + <key>inudstry</key> + <string>industry</string> + <key>inventer</key> + <string>inventor</string> + <key>invertibrates</key> + <string>invertebrates</string> + <key>investingate</key> + <string>investigate</string> + <key>involvment</key> + <string>involvement</string> + <key>irelevent</key> + <string>irrelevant</string> + <key>iresistable</key> + <string>irresistible</string> + <key>iresistably</key> + <string>irresistibly</string> + <key>iresistible</key> + <string>irresistible</string> + <key>iresistibly</key> + <string>irresistibly</string> + <key>iritable</key> + <string>irritable</string> + <key>iritated</key> + <string>irritated</string> + <key>ironicly</key> + <string>ironically</string> + <key>irregardless</key> + <string>regardless</string> + <key>irrelevent</key> + <string>irrelevant</string> + <key>irreplacable</key> + <string>irreplaceable</string> + <key>irresistable</key> + <string>irresistible</string> + <key>irresistably</key> + <string>irresistibly</string> + <key>isnt</key> + <string>isn't</string> + <key>issueing</key> + <string>issuing</string> + <key>itnroduced</key> + <string>introduced</string> + <key>iunior</key> + <string>junior</string> + <key>iwll</key> + <string>will</string> + <key>iwth</key> + <string>with</string> + <key>jaques</key> + <string>jacques</string> + <key>jeapardy</key> + <string>jeopardy</string> + <key>jewllery</key> + <string>jewellery</string> + <key>jouney</key> + <string>journey</string> + <key>journied</key> + <string>journeyed</string> + <key>journies</key> + <string>journeys</string> + <key>jstu</key> + <string>just</string> + <key>jsut</key> + <string>just</string> + <key>judical</key> + <string>judicial</string> + <key>judisuary</key> + <string>judiciary</string> + <key>juducial</key> + <string>judicial</string> + <key>juristiction</key> + <string>jurisdiction</string> + <key>juristictions</key> + <string>jurisdictions</string> + <key>kindergarden</key> + <string>kindergarten</string> + <key>klenex</key> + <string>kleenex</string> + <key>knifes</key> + <string>knives</string> + <key>knive</key> + <string>knife</string> + <key>knowlege</key> + <string>knowledge</string> + <key>knowlegeable</key> + <string>knowledgeable</string> + <key>knwo</key> + <string>know</string> + <key>knwos</key> + <string>knows</string> + <key>konw</key> + <string>know</string> + <key>konws</key> + <string>knows</string> + <key>kwno</key> + <string>know</string> + <key>labatory</key> + <string>laboratory</string> + <key>labratory</key> + <string>laboratory</string> + <key>laguage</key> + <string>language</string> + <key>laguages</key> + <string>languages</string> + <key>larg</key> + <string>large</string> + <key>largst</key> + <string>largest</string> + <key>larrry</key> + <string>larry</string> + <key>lastr</key> + <string>last</string> + <key>lattitude</key> + <string>latitude</string> + <key>launhed</key> + <string>launched</string> + <key>lavae</key> + <string>larvae</string> + <key>layed</key> + <string>laid</string> + <key>lazyness</key> + <string>laziness</string> + <key>leage</key> + <string>league</string> + <key>leanr</key> + <string>learn</string> + <key>leathal</key> + <string>lethal</string> + <key>lefted</key> + <string>left</string> + <key>legitamate</key> + <string>legitimate</string> + <key>legitmate</key> + <string>legitimate</string> + <key>leibnitz</key> + <string>leibniz</string> + <key>lenght</key> + <string>length</string> + <key>leran</key> + <string>learn</string> + <key>lerans</key> + <string>learns</string> + <key>leutenant</key> + <string>lieutenant</string> + <key>levetate</key> + <string>levitate</string> + <key>levetated</key> + <string>levitated</string> + <key>levetates</key> + <string>levitates</string> + <key>levetating</key> + <string>levitating</string> + <key>levle</key> + <string>level</string> + <key>liasion</key> + <string>liaison</string> + <key>liason</key> + <string>liaison</string> + <key>liasons</key> + <string>liaisons</string> + <key>libary</key> + <string>library</string> + <key>libell</key> + <string>libel</string> + <key>libguistic</key> + <string>linguistic</string> + <key>libguistics</key> + <string>linguistics</string> + <key>libitarianisn</key> + <string>libertarianism</string> + <key>lieing</key> + <string>lying</string> + <key>liek</key> + <string>like</string> + <key>liekd</key> + <string>liked</string> + <key>liesure</key> + <string>leisure</string> + <key>lieuenant</key> + <string>lieutenant</string> + <key>lieved</key> + <string>lived</string> + <key>liftime</key> + <string>lifetime</string> + <key>lightyear</key> + <string>light year</string> + <key>lightyears</key> + <string>light years</string> + <key>likelyhood</key> + <string>likelihood</string> + <key>linnaena</key> + <string>linnaean</string> + <key>lippizaner</key> + <string>lipizzaner</string> + <key>liquify</key> + <string>liquefy</string> + <key>liscense</key> + <string>license</string> + <key>lisence</key> + <string>license</string> + <key>lisense</key> + <string>license</string> + <key>listners</key> + <string>listeners</string> + <key>litature</key> + <string>literature</string> + <key>literaly</key> + <string>literally</string> + <key>literture</key> + <string>literature</string> + <key>littel</key> + <string>little</string> + <key>litterally</key> + <string>literally</string> + <key>liuke</key> + <string>like</string> + <key>livley</key> + <string>lively</string> + <key>lmits</key> + <string>limits</string> + <key>loev</key> + <string>love</string> + <key>lonelyness</key> + <string>loneliness</string> + <key>longitudonal</key> + <string>longitudinal</string> + <key>lonley</key> + <string>lonely</string> + <key>lonly</key> + <string>lonely</string> + <key>loosing</key> + <string>losing</string> + <key>lotharingen</key> + <string>lothringen</string> + <key>lsat</key> + <string>last</string> + <key>lukid</key> + <string>likud</string> + <key>lveo</key> + <string>love</string> + <key>lvoe</key> + <string>love</string> + <key>maching</key> + <string>machine</string> + <key>mackeral</key> + <string>mackerel</string> + <key>magasine</key> + <string>magazine</string> + <key>magincian</key> + <string>magician</string> + <key>magnificient</key> + <string>magnificent</string> + <key>magolia</key> + <string>magnolia</string> + <key>mailny</key> + <string>mainly</string> + <key>maintainance</key> + <string>maintenance</string> + <key>maintainence</key> + <string>maintenance</string> + <key>maintance</key> + <string>maintenance</string> + <key>maintenence</key> + <string>maintenance</string> + <key>maintinaing</key> + <string>maintaining</string> + <key>maintioned</key> + <string>mentioned</string> + <key>majoroty</key> + <string>majority</string> + <key>maked</key> + <string>marked</string> + <key>makse</key> + <string>makes</string> + <key>maltesian</key> + <string>Maltese</string> + <key>mamal</key> + <string>mammal</string> + <key>mamalian</key> + <string>mammalian</string> + <key>managable</key> + <string>manageable</string> + <key>managment</key> + <string>management</string> + <key>maneouvre</key> + <string>manoeuvre</string> + <key>maneouvred</key> + <string>manoeuvred</string> + <key>maneouvres</key> + <string>manoeuvres</string> + <key>maneouvring</key> + <string>manoeuvring</string> + <key>manisfestations</key> + <string>manifestations</string> + <key>manoeuverability</key> + <string>maneuverability</string> + <key>manouver</key> + <string>maneuver</string> + <key>manouverability</key> + <string>maneuverability</string> + <key>manouverable</key> + <string>maneuverable</string> + <key>manouvers</key> + <string>maneuvers</string> + <key>mantained</key> + <string>maintained</string> + <key>manuever</key> + <string>maneuver</string> + <key>manuevers</key> + <string>maneuvers</string> + <key>manufacturedd</key> + <string>manufactured</string> + <key>manufature</key> + <string>manufacture</string> + <key>manufatured</key> + <string>manufactured</string> + <key>manufaturing</key> + <string>manufacturing</string> + <key>manuver</key> + <string>maneuver</string> + <key>mariage</key> + <string>marriage</string> + <key>marjority</key> + <string>majority</string> + <key>markes</key> + <string>marks</string> + <key>marketting</key> + <string>marketing</string> + <key>marmelade</key> + <string>marmalade</string> + <key>marrage</key> + <string>marriage</string> + <key>marraige</key> + <string>marriage</string> + <key>marrtyred</key> + <string>martyred</string> + <key>marryied</key> + <string>married</string> + <key>massmedia</key> + <string>mass media</string> + <key>masterbation</key> + <string>masturbation</string> + <key>mataphysical</key> + <string>metaphysical</string> + <key>materalists</key> + <string>materialist</string> + <key>mathamatics</key> + <string>mathematics</string> + <key>mathematican</key> + <string>mathematician</string> + <key>mathematicas</key> + <string>mathematics</string> + <key>matheticians</key> + <string>mathematicians</string> + <key>mathmatically</key> + <string>mathematically</string> + <key>mathmatician</key> + <string>mathematician</string> + <key>mathmaticians</key> + <string>mathematicians</string> + <key>mccarthyst</key> + <string>mccarthyist</string> + <key>mchanics</key> + <string>mechanics</string> + <key>meaninng</key> + <string>meaning</string> + <key>mear</key> + <string>wear</string> + <key>mechandise</key> + <string>merchandise</string> + <key>medacine</key> + <string>medicine</string> + <key>medeival</key> + <string>medieval</string> + <key>medevial</key> + <string>medieval</string> + <key>mediciney</key> + <string>mediciny</string> + <key>medievel</key> + <string>medieval</string> + <key>mediterainnean</key> + <string>mediterranean</string> + <key>meerkrat</key> + <string>meerkat</string> + <key>melieux</key> + <string>milieux</string> + <key>membranaphone</key> + <string>membranophone</string> + <key>memeber</key> + <string>member</string> + <key>menally</key> + <string>mentally</string> + <key>meranda</key> + <string>Miranda</string> + <key>mercentile</key> + <string>mercantile</string> + <key>messanger</key> + <string>messenger</string> + <key>messenging</key> + <string>messaging</string> + <key>metalic</key> + <string>metallic</string> + <key>metalurgic</key> + <string>metallurgic</string> + <key>metalurgical</key> + <string>metallurgical</string> + <key>metalurgy</key> + <string>metallurgy</string> + <key>metamorphysis</key> + <string>metamorphosis</string> + <key>metaphoricial</key> + <string>metaphorical</string> + <key>meterologist</key> + <string>meteorologist</string> + <key>meterology</key> + <string>meteorology</string> + <key>methaphor</key> + <string>metaphor</string> + <key>methaphors</key> + <string>metaphors</string> + <key>micoscopy</key> + <string>microscopy</string> + <key>midwifes</key> + <string>midwives</string> + <key>mileau</key> + <string>milieu</string> + <key>milennia</key> + <string>millennia</string> + <key>milennium</key> + <string>millennium</string> + <key>mileu</key> + <string>milieu</string> + <key>miliary</key> + <string>military</string> + <key>milion</key> + <string>million</string> + <key>miliraty</key> + <string>military</string> + <key>millenia</key> + <string>millennia</string> + <key>millenial</key> + <string>millennial</string> + <key>millenialism</key> + <string>millennialism</string> + <key>millenium</key> + <string>millennium</string> + <key>millepede</key> + <string>millipede</string> + <key>millioniare</key> + <string>millionaire</string> + <key>millitary</key> + <string>military</string> + <key>millon</key> + <string>million</string> + <key>miltary</key> + <string>military</string> + <key>minature</key> + <string>miniature</string> + <key>minerial</key> + <string>mineral</string> + <key>miniscule</key> + <string>minuscule</string> + <key>ministery</key> + <string>ministry</string> + <key>minstries</key> + <string>ministries</string> + <key>minstry</key> + <string>ministry</string> + <key>minumum</key> + <string>minimum</string> + <key>mirrorred</key> + <string>mirrored</string> + <key>miscelaneous</key> + <string>miscellaneous</string> + <key>miscellanious</key> + <string>miscellaneous</string> + <key>miscellanous</key> + <string>miscellaneous</string> + <key>mischeivous</key> + <string>mischievous</string> + <key>mischevious</key> + <string>mischievous</string> + <key>mischievious</key> + <string>mischievous</string> + <key>misdameanor</key> + <string>misdemeanor</string> + <key>misdameanors</key> + <string>misdemeanors</string> + <key>misdemenor</key> + <string>misdemeanor</string> + <key>misdemenors</key> + <string>misdemeanors</string> + <key>misfourtunes</key> + <string>misfortunes</string> + <key>misile</key> + <string>missile</string> + <key>mispell</key> + <string>misspell</string> + <key>mispelled</key> + <string>misspelled</string> + <key>mispelling</key> + <string>misspelling</string> + <key>missen</key> + <string>mizzen</string> + <key>missle</key> + <string>missile</string> + <key>missonary</key> + <string>missionary</string> + <key>misterious</key> + <string>mysterious</string> + <key>mistery</key> + <string>mystery</string> + <key>misteryous</key> + <string>mysterious</string> + <key>mkae</key> + <string>make</string> + <key>mkaes</key> + <string>makes</string> + <key>mkaing</key> + <string>making</string> + <key>mkea</key> + <string>make</string> + <key>moderm</key> + <string>modem</string> + <key>modle</key> + <string>model</string> + <key>moent</key> + <string>moment</string> + <key>moeny</key> + <string>money</string> + <key>mohammedans</key> + <string>muslims</string> + <key>moil</key> + <string>soil</string> + <key>moleclues</key> + <string>molecules</string> + <key>momento</key> + <string>memento</string> + <key>monestaries</key> + <string>monasteries</string> + <key>monestary</key> + <string>monastery</string> + <key>monickers</key> + <string>monikers</string> + <key>monolite</key> + <string>monolithic</string> + <key>montains</key> + <string>mountains</string> + <key>montanous</key> + <string>mountainous</string> + <key>monts</key> + <string>months</string> + <key>montypic</key> + <string>monotypic</string> + <key>moreso</key> + <string>more so</string> + <key>morgage</key> + <string>mortgage</string> + <key>morroccan</key> + <string>moroccan</string> + <key>morrocco</key> + <string>morocco</string> + <key>morroco</key> + <string>morocco</string> + <key>mortage</key> + <string>mortgage</string> + <key>mosture</key> + <string>moisture</string> + <key>motiviated</key> + <string>motivated</string> + <key>mounth</key> + <string>month</string> + <key>movei</key> + <string>movie</string> + <key>movment</key> + <string>movement</string> + <key>mroe</key> + <string>more</string> + <key>mucuous</key> + <string>mucous</string> + <key>muder</key> + <string>murder</string> + <key>mudering</key> + <string>murdering</string> + <key>muhammadan</key> + <string>muslim</string> + <key>multicultralism</key> + <string>multiculturalism</string> + <key>multipled</key> + <string>multiplied</string> + <key>multiplers</key> + <string>multipliers</string> + <key>munbers</key> + <string>numbers</string> + <key>muncipalities</key> + <string>municipalities</string> + <key>muncipality</key> + <string>municipality</string> + <key>munnicipality</key> + <string>municipality</string> + <key>muscels</key> + <string>muscles</string> + <key>muscial</key> + <string>musical</string> + <key>muscician</key> + <string>musician</string> + <key>muscicians</key> + <string>musicians</string> + <key>mutiliated</key> + <string>mutilated</string> + <key>myraid</key> + <string>myriad</string> + <key>mysef</key> + <string>myself</string> + <key>mysogynist</key> + <string>misogynist</string> + <key>mysogyny</key> + <string>misogyny</string> + <key>mysterous</key> + <string>mysterious</string> + <key>naieve</key> + <string>naive</string> + <key>naturaly</key> + <string>naturally</string> + <key>naturely</key> + <string>naturally</string> + <key>naturual</key> + <string>natural</string> + <key>naturually</key> + <string>naturally</string> + <key>neccesarily</key> + <string>necessarily</string> + <key>neccesary</key> + <string>necessary</string> + <key>neccessarily</key> + <string>necessarily</string> + <key>neccessary</key> + <string>necessary</string> + <key>neccessities</key> + <string>necessities</string> + <key>necesarily</key> + <string>necessarily</string> + <key>necesary</key> + <string>necessary</string> + <key>necessiate</key> + <string>necessitate</string> + <key>neglible</key> + <string>negligible</string> + <key>negligable</key> + <string>negligible</string> + <key>negociate</key> + <string>negotiate</string> + <key>negociation</key> + <string>negotiation</string> + <key>negociations</key> + <string>negotiations</string> + <key>negotation</key> + <string>negotiation</string> + <key>neice</key> + <string>niece</string> + <key>neigborhood</key> + <string>neighborhood</string> + <key>neigbour</key> + <string>neighbour</string> + <key>neigbourhood</key> + <string>neighbourhood</string> + <key>neolitic</key> + <string>neolithic</string> + <key>nessasarily</key> + <string>necessarily</string> + <key>nessecary</key> + <string>necessary</string> + <key>nestin</key> + <string>nesting</string> + <key>neverthless</key> + <string>nevertheless</string> + <key>newletters</key> + <string>newsletters</string> + <key>nickle</key> + <string>nickel</string> + <key>nightfa;;</key> + <string>nightfall</string> + <key>nightime</key> + <string>nighttime</string> + <key>nineth</key> + <string>ninth</string> + <key>ninteenth</key> + <string>nineteenth</string> + <key>ninties</key> + <string>1990s</string> + <key>ninty</key> + <string>ninety</string> + <key>nkow</key> + <string>know</string> + <key>nkwo</key> + <string>know</string> + <key>nmae</key> + <string>name</string> + <key>noncombatents</key> + <string>noncombatants</string> + <key>nonsence</key> + <string>nonsense</string> + <key>nontheless</key> + <string>nonetheless</string> + <key>noone</key> + <string>no one</string> + <key>norhern</key> + <string>northern</string> + <key>northen</key> + <string>northern</string> + <key>northereastern</key> + <string>northeastern</string> + <key>notabley</key> + <string>notably</string> + <key>noteable</key> + <string>notable</string> + <key>noteably</key> + <string>notably</string> + <key>noteriety</key> + <string>notoriety</string> + <key>noth</key> + <string>north</string> + <key>nothern</key> + <string>northern</string> + <key>noticable</key> + <string>noticeable</string> + <key>noticably</key> + <string>noticeably</string> + <key>noticeing</key> + <string>noticing</string> + <key>noticible</key> + <string>noticeable</string> + <key>notwhithstanding</key> + <string>notwithstanding</string> + <key>noveau</key> + <string>nouveau</string> + <key>nowdays</key> + <string>nowadays</string> + <key>nowe</key> + <string>now</string> + <key>nto</key> + <string>not</string> + <key>nucular</key> + <string>nuclear</string> + <key>nuculear</key> + <string>nuclear</string> + <key>nuisanse</key> + <string>nuisance</string> + <key>numberous</key> + <string>numerous</string> + <key>nusance</key> + <string>nuisance</string> + <key>nutritent</key> + <string>nutrient</string> + <key>nutritents</key> + <string>nutrients</string> + <key>nuturing</key> + <string>nurturing</string> + <key>obediance</key> + <string>obedience</string> + <key>obediant</key> + <string>obedient</string> + <key>obession</key> + <string>obsession</string> + <key>obssessed</key> + <string>obsessed</string> + <key>obstacal</key> + <string>obstacle</string> + <key>obstancles</key> + <string>obstacles</string> + <key>obstruced</key> + <string>obstructed</string> + <key>ocasion</key> + <string>occasion</string> + <key>ocasional</key> + <string>occasional</string> + <key>ocasionally</key> + <string>occasionally</string> + <key>ocasionaly</key> + <string>occasionally</string> + <key>ocasioned</key> + <string>occasioned</string> + <key>ocasions</key> + <string>occasions</string> + <key>ocassion</key> + <string>occasion</string> + <key>ocassional</key> + <string>occasional</string> + <key>ocassionally</key> + <string>occasionally</string> + <key>ocassionaly</key> + <string>occasionally</string> + <key>ocassioned</key> + <string>occasioned</string> + <key>ocassions</key> + <string>occasions</string> + <key>occaison</key> + <string>occasion</string> + <key>occassion</key> + <string>occasion</string> + <key>occassional</key> + <string>occasional</string> + <key>occassionally</key> + <string>occasionally</string> + <key>occassionaly</key> + <string>occasionally</string> + <key>occassioned</key> + <string>occasioned</string> + <key>occassions</key> + <string>occasions</string> + <key>occationally</key> + <string>occasionally</string> + <key>occour</key> + <string>occur</string> + <key>occurance</key> + <string>occurrence</string> + <key>occurances</key> + <string>occurrences</string> + <key>occured</key> + <string>occurred</string> + <key>occurence</key> + <string>occurrence</string> + <key>occurences</key> + <string>occurrences</string> + <key>occuring</key> + <string>occurring</string> + <key>occurr</key> + <string>occur</string> + <key>occurrance</key> + <string>occurrence</string> + <key>occurrances</key> + <string>occurrences</string> + <key>octohedra</key> + <string>octahedra</string> + <key>octohedral</key> + <string>octahedral</string> + <key>octohedron</key> + <string>octahedron</string> + <key>ocuntries</key> + <string>countries</string> + <key>ocuntry</key> + <string>country</string> + <key>ocurr</key> + <string>occur</string> + <key>ocurrance</key> + <string>occurrence</string> + <key>ocurred</key> + <string>occurred</string> + <key>ocurrence</key> + <string>occurrence</string> + <key>offcers</key> + <string>officers</string> + <key>offcially</key> + <string>officially</string> + <key>offereings</key> + <string>offerings</string> + <key>offical</key> + <string>official</string> + <key>offically</key> + <string>officially</string> + <key>officals</key> + <string>officials</string> + <key>officaly</key> + <string>officially</string> + <key>officialy</key> + <string>officially</string> + <key>offred</key> + <string>offered</string> + <key>oftenly</key> + <string>often</string> + <key>oging</key> + <string>going</string> + <key>omision</key> + <string>omission</string> + <key>omited</key> + <string>omitted</string> + <key>omiting</key> + <string>omitting</string> + <key>omlette</key> + <string>omelette</string> + <key>ommision</key> + <string>omission</string> + <key>ommited</key> + <string>omitted</string> + <key>ommiting</key> + <string>omitting</string> + <key>ommitted</key> + <string>omitted</string> + <key>ommitting</key> + <string>omitting</string> + <key>omniverous</key> + <string>omnivorous</string> + <key>omniverously</key> + <string>omnivorously</string> + <key>omre</key> + <string>more</string> + <key>onot</key> + <string>note</string> + <key>onxy</key> + <string>onyx</string> + <key>onyl</key> + <string>only</string> + <key>openess</key> + <string>openness</string> + <key>oponent</key> + <string>opponent</string> + <key>oportunity</key> + <string>opportunity</string> + <key>opose</key> + <string>oppose</string> + <key>oposite</key> + <string>opposite</string> + <key>oposition</key> + <string>opposition</string> + <key>oppenly</key> + <string>openly</string> + <key>oppinion</key> + <string>opinion</string> + <key>opponant</key> + <string>opponent</string> + <key>oppononent</key> + <string>opponent</string> + <key>oppositition</key> + <string>opposition</string> + <key>oppossed</key> + <string>opposed</string> + <key>opprotunity</key> + <string>opportunity</string> + <key>opression</key> + <string>oppression</string> + <key>opressive</key> + <string>oppressive</string> + <key>opthalmic</key> + <string>ophthalmic</string> + <key>opthalmologist</key> + <string>ophthalmologist</string> + <key>opthalmology</key> + <string>ophthalmology</string> + <key>opthamologist</key> + <string>ophthalmologist</string> + <key>optmizations</key> + <string>optimizations</string> + <key>optomism</key> + <string>optimism</string> + <key>orded</key> + <string>ordered</string> + <key>organim</key> + <string>organism</string> + <key>organistion</key> + <string>organisation</string> + <key>organiztion</key> + <string>organization</string> + <key>orgin</key> + <string>origin</string> + <key>orginal</key> + <string>original</string> + <key>orginally</key> + <string>originally</string> + <key>orginize</key> + <string>organise</string> + <key>oridinarily</key> + <string>ordinarily</string> + <key>origanaly</key> + <string>originally</string> + <key>originall</key> + <string>original</string> + <key>originaly</key> + <string>originally</string> + <key>originially</key> + <string>originally</string> + <key>originnally</key> + <string>originally</string> + <key>origional</key> + <string>original</string> + <key>orignally</key> + <string>originally</string> + <key>orignially</key> + <string>originally</string> + <key>otehr</key> + <string>other</string> + <key>oublisher</key> + <string>publisher</string> + <key>ouevre</key> + <string>oeuvre</string> + <key>oustanding</key> + <string>outstanding</string> + <key>overshaddowed</key> + <string>overshadowed</string> + <key>overthere</key> + <string>over there</string> + <key>overwelming</key> + <string>overwhelming</string> + <key>overwheliming</key> + <string>overwhelming</string> + <key>owrk</key> + <string>work</string> + <key>owudl</key> + <string>would</string> + <key>oxigen</key> + <string>oxygen</string> + <key>oximoron</key> + <string>oxymoron</string> + <key>p0enis</key> + <string>penis</string> + <key>paide</key> + <string>paid</string> + <key>paitience</key> + <string>patience</string> + <key>palce</key> + <string>place</string> + <key>paleolitic</key> + <string>paleolithic</string> + <key>paliamentarian</key> + <string>parliamentarian</string> + <key>pallete</key> + <string>palette</string> + <key>pamflet</key> + <string>pamphlet</string> + <key>pamplet</key> + <string>pamphlet</string> + <key>pantomine</key> + <string>pantomime</string> + <key>paralel</key> + <string>parallel</string> + <key>paralell</key> + <string>parallel</string> + <key>paralelly</key> + <string>parallelly</string> + <key>paralely</key> + <string>parallelly</string> + <key>parallely</key> + <string>parallelly</string> + <key>paranthesis</key> + <string>parenthesis</string> + <key>paraphenalia</key> + <string>paraphernalia</string> + <key>parellels</key> + <string>parallels</string> + <key>parituclar</key> + <string>particular</string> + <key>parliment</key> + <string>parliament</string> + <key>parrakeets</key> + <string>parakeets</string> + <key>parralel</key> + <string>parallel</string> + <key>parrallel</key> + <string>parallel</string> + <key>parrallell</key> + <string>parallel</string> + <key>parrallelly</key> + <string>parallelly</string> + <key>parrallely</key> + <string>parallelly</string> + <key>partialy</key> + <string>partially</string> + <key>particually</key> + <string>particularly</string> + <key>particualr</key> + <string>particular</string> + <key>particuarly</key> + <string>particularly</string> + <key>particularily</key> + <string>particularly</string> + <key>particulary</key> + <string>particularly</string> + <key>pary</key> + <string>party</string> + <key>pased</key> + <string>passed</string> + <key>pasengers</key> + <string>passengers</string> + <key>passerbys</key> + <string>passersby</string> + <key>pasttime</key> + <string>pastime</string> + <key>pastural</key> + <string>pastoral</string> + <key>paticular</key> + <string>particular</string> + <key>pattented</key> + <string>patented</string> + <key>pavillion</key> + <string>pavilion</string> + <key>payed</key> + <string>paid</string> + <key>pblisher</key> + <string>publisher</string> + <key>pbulisher</key> + <string>publisher</string> + <key>peacefuland</key> + <string>peaceful and</string> + <key>peageant</key> + <string>pageant</string> + <key>peculure</key> + <string>peculiar</string> + <key>pedestrain</key> + <string>pedestrian</string> + <key>peformed</key> + <string>performed</string> + <key>peice</key> + <string>piece</string> + <key>penatly</key> + <string>penalty</string> + <key>penerator</key> + <string>penetrator</string> + <key>penisula</key> + <string>peninsula</string> + <key>penisular</key> + <string>peninsular</string> + <key>penninsula</key> + <string>peninsula</string> + <key>penninsular</key> + <string>peninsular</string> + <key>pennisula</key> + <string>peninsula</string> + <key>pensinula</key> + <string>peninsula</string> + <key>peom</key> + <string>poem</string> + <key>peoms</key> + <string>poems</string> + <key>peopel</key> + <string>people</string> + <key>peotry</key> + <string>poetry</string> + <key>perade</key> + <string>parade</string> + <key>percepted</key> + <string>perceived</string> + <key>percieve</key> + <string>perceive</string> + <key>percieved</key> + <string>perceived</string> + <key>perenially</key> + <string>perennially</string> + <key>perfomance</key> + <string>performance</string> + <key>perfomers</key> + <string>performers</string> + <key>performence</key> + <string>performance</string> + <key>performes</key> + <string>performed</string> + <key>perhasp</key> + <string>perhaps</string> + <key>perheaps</key> + <string>perhaps</string> + <key>perhpas</key> + <string>perhaps</string> + <key>peripathetic</key> + <string>peripatetic</string> + <key>peristent</key> + <string>persistent</string> + <key>perjery</key> + <string>perjury</string> + <key>perjorative</key> + <string>pejorative</string> + <key>permanant</key> + <string>permanent</string> + <key>permenant</key> + <string>permanent</string> + <key>permenantly</key> + <string>permanently</string> + <key>permissable</key> + <string>permissible</string> + <key>perogative</key> + <string>prerogative</string> + <key>peronal</key> + <string>personal</string> + <key>perosnality</key> + <string>personality</string> + <key>perphas</key> + <string>perhaps</string> + <key>perpindicular</key> + <string>perpendicular</string> + <key>perseverence</key> + <string>perseverance</string> + <key>persistance</key> + <string>persistence</string> + <key>persistant</key> + <string>persistent</string> + <key>personel</key> + <string>personnel</string> + <key>personell</key> + <string>personnel</string> + <key>personnell</key> + <string>personnel</string> + <key>persuded</key> + <string>persuaded</string> + <key>persue</key> + <string>pursue</string> + <key>persued</key> + <string>pursued</string> + <key>persuing</key> + <string>pursuing</string> + <key>persuit</key> + <string>pursuit</string> + <key>persuits</key> + <string>pursuits</string> + <key>pertubation</key> + <string>perturbation</string> + <key>pertubations</key> + <string>perturbations</string> + <key>pessiary</key> + <string>pessary</string> + <key>petetion</key> + <string>petition</string> + <key>phenomenom</key> + <string>phenomenon</string> + <key>phenomenonal</key> + <string>phenomenal</string> + <key>phenomenonly</key> + <string>phenomenally</string> + <key>phenomonenon</key> + <string>phenomenon</string> + <key>phenomonon</key> + <string>phenomenon</string> + <key>phenonmena</key> + <string>phenomena</string> + <key>philisopher</key> + <string>philosopher</string> + <key>philisophical</key> + <string>philosophical</string> + <key>philisophy</key> + <string>philosophy</string> + <key>phillosophically</key> + <string>philosophically</string> + <key>philospher</key> + <string>philosopher</string> + <key>philosphies</key> + <string>philosophies</string> + <key>philosphy</key> + <string>philosophy</string> + <key>phongraph</key> + <string>phonograph</string> + <key>phylosophical</key> + <string>philosophical</string> + <key>physicaly</key> + <string>physically</string> + <key>piblisher</key> + <string>publisher</string> + <key>pich</key> + <string>pitch</string> + <key>pilgrimmage</key> + <string>pilgrimage</string> + <key>pilgrimmages</key> + <string>pilgrimages</string> + <key>pinapple</key> + <string>pineapple</string> + <key>pinnaple</key> + <string>pineapple</string> + <key>pinoneered</key> + <string>pioneered</string> + <key>plagarism</key> + <string>plagiarism</string> + <key>planation</key> + <string>plantation</string> + <key>planed</key> + <string>planned</string> + <key>plantiff</key> + <string>plaintiff</string> + <key>plateu</key> + <string>plateau</string> + <key>plausable</key> + <string>plausible</string> + <key>playright</key> + <string>playwright</string> + <key>playwrite</key> + <string>playwright</string> + <key>playwrites</key> + <string>playwrights</string> + <key>pleasent</key> + <string>pleasant</string> + <key>plebicite</key> + <string>plebiscite</string> + <key>plesant</key> + <string>pleasant</string> + <key>poenis</key> + <string>penis</string> + <key>poeoples</key> + <string>peoples</string> + <key>poety</key> + <string>poetry</string> + <key>poisin</key> + <string>poison</string> + <key>polical</key> + <string>political</string> + <key>polinator</key> + <string>pollinator</string> + <key>polinators</key> + <string>pollinators</string> + <key>politican</key> + <string>politician</string> + <key>politicans</key> + <string>politicians</string> + <key>poltical</key> + <string>political</string> + <key>polute</key> + <string>pollute</string> + <key>poluted</key> + <string>polluted</string> + <key>polutes</key> + <string>pollutes</string> + <key>poluting</key> + <string>polluting</string> + <key>polution</key> + <string>pollution</string> + <key>polyphonyic</key> + <string>polyphonic</string> + <key>polysaccaride</key> + <string>polysaccharide</string> + <key>polysaccharid</key> + <string>polysaccharide</string> + <key>pomegranite</key> + <string>pomegranate</string> + <key>pomotion</key> + <string>promotion</string> + <key>poportional</key> + <string>proportional</string> + <key>popoulation</key> + <string>population</string> + <key>popularaty</key> + <string>popularity</string> + <key>populare</key> + <string>popular</string> + <key>populer</key> + <string>popular</string> + <key>portait</key> + <string>portrait</string> + <key>portayed</key> + <string>portrayed</string> + <key>portraing</key> + <string>portraying</string> + <key>portuguease</key> + <string>portuguese</string> + <key>portugues</key> + <string>Portuguese</string> + <key>posess</key> + <string>possess</string> + <key>posessed</key> + <string>possessed</string> + <key>posesses</key> + <string>possesses</string> + <key>posessing</key> + <string>possessing</string> + <key>posession</key> + <string>possession</string> + <key>posessions</key> + <string>possessions</string> + <key>posion</key> + <string>poison</string> + <key>positon</key> + <string>position</string> + <key>possable</key> + <string>possible</string> + <key>possably</key> + <string>possibly</string> + <key>posseses</key> + <string>possesses</string> + <key>possesing</key> + <string>possessing</string> + <key>possesion</key> + <string>possession</string> + <key>possessess</key> + <string>possesses</string> + <key>possibile</key> + <string>possible</string> + <key>possibilty</key> + <string>possibility</string> + <key>possiblility</key> + <string>possibility</string> + <key>possiblilty</key> + <string>possibility</string> + <key>possiblities</key> + <string>possibilities</string> + <key>possiblity</key> + <string>possibility</string> + <key>possition</key> + <string>position</string> + <key>posthomous</key> + <string>posthumous</string> + <key>postion</key> + <string>position</string> + <key>postive</key> + <string>positive</string> + <key>potatos</key> + <string>potatoes</string> + <key>potrait</key> + <string>portrait</string> + <key>potrayed</key> + <string>portrayed</string> + <key>poulations</key> + <string>populations</string> + <key>poverful</key> + <string>powerful</string> + <key>poweful</key> + <string>powerful</string> + <key>powerfull</key> + <string>powerful</string> + <key>ppublisher</key> + <string>publisher</string> + <key>practial</key> + <string>practical</string> + <key>practially</key> + <string>practically</string> + <key>practicaly</key> + <string>practically</string> + <key>practicioner</key> + <string>practitioner</string> + <key>practicioners</key> + <string>practitioners</string> + <key>practicly</key> + <string>practically</string> + <key>practioner</key> + <string>practitioner</string> + <key>practioners</key> + <string>practitioners</string> + <key>prairy</key> + <string>prairie</string> + <key>prarie</key> + <string>prairie</string> + <key>praries</key> + <string>prairies</string> + <key>pratice</key> + <string>practice</string> + <key>preample</key> + <string>preamble</string> + <key>precedessor</key> + <string>predecessor</string> + <key>preceed</key> + <string>precede</string> + <key>preceeded</key> + <string>preceded</string> + <key>preceeding</key> + <string>preceding</string> + <key>preceeds</key> + <string>precedes</string> + <key>precentage</key> + <string>percentage</string> + <key>precice</key> + <string>precise</string> + <key>precisly</key> + <string>precisely</string> + <key>precurser</key> + <string>precursor</string> + <key>predecesors</key> + <string>predecessors</string> + <key>predicatble</key> + <string>predictable</string> + <key>predicitons</key> + <string>predictions</string> + <key>predomiantly</key> + <string>predominately</string> + <key>prefered</key> + <string>preferred</string> + <key>prefering</key> + <string>preferring</string> + <key>preferrably</key> + <string>preferably</string> + <key>pregancies</key> + <string>pregnancies</string> + <key>preiod</key> + <string>period</string> + <key>preliferation</key> + <string>proliferation</string> + <key>premeire</key> + <string>premiere</string> + <key>premeired</key> + <string>premiered</string> + <key>premillenial</key> + <string>premillennial</string> + <key>preminence</key> + <string>preeminence</string> + <key>premission</key> + <string>permission</string> + <key>preocupation</key> + <string>preoccupation</string> + <key>prepair</key> + <string>prepare</string> + <key>prepartion</key> + <string>preparation</string> + <key>prepatory</key> + <string>preparatory</string> + <key>preperation</key> + <string>preparation</string> + <key>preperations</key> + <string>preparations</string> + <key>preriod</key> + <string>period</string> + <key>presedential</key> + <string>presidential</string> + <key>presense</key> + <string>presence</string> + <key>presidenital</key> + <string>presidential</string> + <key>presidental</key> + <string>presidential</string> + <key>presitgious</key> + <string>prestigious</string> + <key>prespective</key> + <string>perspective</string> + <key>prestigeous</key> + <string>prestigious</string> + <key>prestigous</key> + <string>prestigious</string> + <key>presumabely</key> + <string>presumably</string> + <key>presumibly</key> + <string>presumably</string> + <key>pretection</key> + <string>protection</string> + <key>prevelant</key> + <string>prevalent</string> + <key>preverse</key> + <string>perverse</string> + <key>previvous</key> + <string>previous</string> + <key>pricipal</key> + <string>principal</string> + <key>priciple</key> + <string>principle</string> + <key>priestood</key> + <string>priesthood</string> + <key>primarly</key> + <string>primarily</string> + <key>primative</key> + <string>primitive</string> + <key>primatively</key> + <string>primitively</string> + <key>primatives</key> + <string>primitives</string> + <key>primordal</key> + <string>primordial</string> + <key>priveledges</key> + <string>privileges</string> + <key>privelege</key> + <string>privilege</string> + <key>priveleged</key> + <string>privileged</string> + <key>priveleges</key> + <string>privileges</string> + <key>privelige</key> + <string>privilege</string> + <key>priveliged</key> + <string>privileged</string> + <key>priveliges</key> + <string>privileges</string> + <key>privelleges</key> + <string>privileges</string> + <key>privilage</key> + <string>privilege</string> + <key>priviledge</key> + <string>privilege</string> + <key>priviledges</key> + <string>privileges</string> + <key>privledge</key> + <string>privilege</string> + <key>privte</key> + <string>private</string> + <key>probabilaty</key> + <string>probability</string> + <key>probablistic</key> + <string>probabilistic</string> + <key>probablly</key> + <string>probably</string> + <key>probalibity</key> + <string>probability</string> + <key>probaly</key> + <string>probably</string> + <key>probelm</key> + <string>problem</string> + <key>proccess</key> + <string>process</string> + <key>proccessing</key> + <string>processing</string> + <key>procede</key> + <string>proceed</string> + <key>proceded</key> + <string>proceeded</string> + <key>procedes</key> + <string>proceeds</string> + <key>procedger</key> + <string>procedure</string> + <key>proceding</key> + <string>proceeding</string> + <key>procedings</key> + <string>proceedings</string> + <key>proceedure</key> + <string>procedure</string> + <key>proces</key> + <string>process</string> + <key>processer</key> + <string>processor</string> + <key>proclaimation</key> + <string>proclamation</string> + <key>proclamed</key> + <string>proclaimed</string> + <key>proclaming</key> + <string>proclaiming</string> + <key>proclomation</key> + <string>proclamation</string> + <key>profesion</key> + <string>profession</string> + <key>profesor</key> + <string>professor</string> + <key>professer</key> + <string>professor</string> + <key>proffesed</key> + <string>professed</string> + <key>proffesion</key> + <string>profession</string> + <key>proffesional</key> + <string>professional</string> + <key>proffesor</key> + <string>professor</string> + <key>profilic</key> + <string>prolific</string> + <key>progessed</key> + <string>progressed</string> + <key>programable</key> + <string>programmable</string> + <key>progrom</key> + <string>program</string> + <key>progroms</key> + <string>programs</string> + <key>prohabition</key> + <string>prohibition</string> + <key>prologomena</key> + <string>prolegomena</string> + <key>prominance</key> + <string>prominence</string> + <key>prominant</key> + <string>prominent</string> + <key>prominantly</key> + <string>prominently</string> + <key>prominately</key> + <string>prominently</string> + <key>promiscous</key> + <string>promiscuous</string> + <key>promotted</key> + <string>promoted</string> + <key>pronomial</key> + <string>pronominal</string> + <key>pronouced</key> + <string>pronounced</string> + <key>pronounched</key> + <string>pronounced</string> + <key>pronounciation</key> + <string>pronunciation</string> + <key>proove</key> + <string>prove</string> + <key>prooved</key> + <string>proved</string> + <key>prophacy</key> + <string>prophecy</string> + <key>propietary</key> + <string>proprietary</string> + <key>propmted</key> + <string>prompted</string> + <key>propoganda</key> + <string>propaganda</string> + <key>propogate</key> + <string>propagate</string> + <key>propogates</key> + <string>propagates</string> + <key>propogation</key> + <string>propagation</string> + <key>propostion</key> + <string>proposition</string> + <key>propotions</key> + <string>proportions</string> + <key>propper</key> + <string>proper</string> + <key>propperly</key> + <string>properly</string> + <key>proprietory</key> + <string>proprietary</string> + <key>proseletyzing</key> + <string>proselytizing</string> + <key>protaganist</key> + <string>protagonist</string> + <key>protaganists</key> + <string>protagonists</string> + <key>protocal</key> + <string>protocol</string> + <key>protoganist</key> + <string>protagonist</string> + <key>protrayed</key> + <string>portrayed</string> + <key>protruberance</key> + <string>protuberance</string> + <key>protruberances</key> + <string>protuberances</string> + <key>prouncements</key> + <string>pronouncements</string> + <key>provacative</key> + <string>provocative</string> + <key>provded</key> + <string>provided</string> + <key>provicial</key> + <string>provincial</string> + <key>provinicial</key> + <string>provincial</string> + <key>provisiosn</key> + <string>provision</string> + <key>provisonal</key> + <string>provisional</string> + <key>proximty</key> + <string>proximity</string> + <key>pseudononymous</key> + <string>pseudonymous</string> + <key>pseudonyn</key> + <string>pseudonym</string> + <key>psuedo</key> + <string>pseudo</string> + <key>psycology</key> + <string>psychology</string> + <key>psyhic</key> + <string>psychic</string> + <key>pubilsher</key> + <string>publisher</string> + <key>pubisher</key> + <string>publisher</string> + <key>publiaher</key> + <string>publisher</string> + <key>publically</key> + <string>publicly</string> + <key>publicaly</key> + <string>publicly</string> + <key>publicher</key> + <string>publisher</string> + <key>publihser</key> + <string>publisher</string> + <key>publisehr</key> + <string>publisher</string> + <key>publiser</key> + <string>publisher</string> + <key>publisger</key> + <string>publisher</string> + <key>publisheed</key> + <string>published</string> + <key>publisherr</key> + <string>publisher</string> + <key>publishher</key> + <string>publisher</string> + <key>publishor</key> + <string>publisher</string> + <key>publishre</key> + <string>publisher</string> + <key>publissher</key> + <string>publisher</string> + <key>publlisher</key> + <string>publisher</string> + <key>publsiher</key> + <string>publisher</string> + <key>publusher</key> + <string>publisher</string> + <key>puchasing</key> + <string>purchasing</string> + <key>pulisher</key> + <string>publisher</string> + <key>pumkin</key> + <string>pumpkin</string> + <key>puplisher</key> + <string>publisher</string> + <key>puritannical</key> + <string>puritanical</string> + <key>purposedly</key> + <string>purposely</string> + <key>purpotedly</key> + <string>purportedly</string> + <key>pursuade</key> + <string>persuade</string> + <key>pursuaded</key> + <string>persuaded</string> + <key>pursuades</key> + <string>persuades</string> + <key>pususading</key> + <string>persuading</string> + <key>puting</key> + <string>putting</string> + <key>pwoer</key> + <string>power</string> + <key>pyscic</key> + <string>psychic</string> + <key>qtuie</key> + <string>quiet</string> + <key>quantaty</key> + <string>quantity</string> + <key>quantitiy</key> + <string>quantity</string> + <key>quarantaine</key> + <string>quarantine</string> + <key>questonable</key> + <string>questionable</string> + <key>quicklyu</key> + <string>quickly</string> + <key>quinessential</key> + <string>quintessential</string> + <key>quitted</key> + <string>quit</string> + <key>quizes</key> + <string>quizzes</string> + <key>qutie</key> + <string>quiet</string> + <key>rabinnical</key> + <string>rabbinical</string> + <key>racaus</key> + <string>raucous</string> + <key>radiactive</key> + <string>radioactive</string> + <key>radify</key> + <string>ratify</string> + <key>raelly</key> + <string>really</string> + <key>rarified</key> + <string>rarefied</string> + <key>reaccurring</key> + <string>recurring</string> + <key>reacing</key> + <string>reaching</string> + <key>reacll</key> + <string>recall</string> + <key>readmition</key> + <string>readmission</string> + <key>realitvely</key> + <string>relatively</string> + <key>realsitic</key> + <string>realistic</string> + <key>realtions</key> + <string>relations</string> + <key>realy</key> + <string>really</string> + <key>realyl</key> + <string>really</string> + <key>reasearch</key> + <string>research</string> + <key>rebiulding</key> + <string>rebuilding</string> + <key>rebllions</key> + <string>rebellions</string> + <key>rebounce</key> + <string>rebound</string> + <key>reccomend</key> + <string>recommend</string> + <key>reccomendations</key> + <string>recommendations</string> + <key>reccomended</key> + <string>recommended</string> + <key>reccomending</key> + <string>recommending</string> + <key>reccommend</key> + <string>recommend</string> + <key>reccommended</key> + <string>recommended</string> + <key>reccommending</key> + <string>recommending</string> + <key>reccuring</key> + <string>recurring</string> + <key>receeded</key> + <string>receded</string> + <key>receeding</key> + <string>receding</string> + <key>receivedfrom</key> + <string>received from</string> + <key>recepient</key> + <string>recipient</string> + <key>recepients</key> + <string>recipients</string> + <key>receving</key> + <string>receiving</string> + <key>rechargable</key> + <string>rechargeable</string> + <key>reched</key> + <string>reached</string> + <key>recide</key> + <string>reside</string> + <key>recided</key> + <string>resided</string> + <key>recident</key> + <string>resident</string> + <key>recidents</key> + <string>residents</string> + <key>reciding</key> + <string>residing</string> + <key>reciepents</key> + <string>recipients</string> + <key>reciept</key> + <string>receipt</string> + <key>recieve</key> + <string>receive</string> + <key>recieved</key> + <string>received</string> + <key>reciever</key> + <string>receiver</string> + <key>recievers</key> + <string>receivers</string> + <key>recieves</key> + <string>receives</string> + <key>recieving</key> + <string>receiving</string> + <key>recipiant</key> + <string>recipient</string> + <key>recipiants</key> + <string>recipients</string> + <key>recived</key> + <string>received</string> + <key>recivership</key> + <string>receivership</string> + <key>recogise</key> + <string>recognise</string> + <key>recogize</key> + <string>recognize</string> + <key>recomend</key> + <string>recommend</string> + <key>recomended</key> + <string>recommended</string> + <key>recomending</key> + <string>recommending</string> + <key>recomends</key> + <string>recommends</string> + <key>recommedations</key> + <string>recommendations</string> + <key>reconaissance</key> + <string>reconnaissance</string> + <key>reconcilation</key> + <string>reconciliation</string> + <key>reconized</key> + <string>recognized</string> + <key>reconnaisance</key> + <string>reconnaissance</string> + <key>reconnaissence</key> + <string>reconnaissance</string> + <key>recontructed</key> + <string>reconstructed</string> + <key>recordproducer</key> + <string>record producer</string> + <key>recquired</key> + <string>required</string> + <key>recrational</key> + <string>recreational</string> + <key>recrod</key> + <string>record</string> + <key>recuiting</key> + <string>recruiting</string> + <key>recuring</key> + <string>recurring</string> + <key>recurrance</key> + <string>recurrence</string> + <key>rediculous</key> + <string>ridiculous</string> + <key>reedeming</key> + <string>redeeming</string> + <key>reenforced</key> + <string>reinforced</string> + <key>refect</key> + <string>reflect</string> + <key>refedendum</key> + <string>referendum</string> + <key>referal</key> + <string>referral</string> + <key>referece</key> + <string>reference</string> + <key>refereces</key> + <string>references</string> + <key>refered</key> + <string>referred</string> + <key>referemce</key> + <string>reference</string> + <key>referemces</key> + <string>references</string> + <key>referencs</key> + <string>references</string> + <key>referenece</key> + <string>reference</string> + <key>refereneced</key> + <string>referenced</string> + <key>refereneces</key> + <string>references</string> + <key>referiang</key> + <string>referring</string> + <key>refering</key> + <string>referring</string> + <key>refernce</key> + <string>references</string> + <key>refernces</key> + <string>references</string> + <key>referrence</key> + <string>reference</string> + <key>referrences</key> + <string>references</string> + <key>referrs</key> + <string>refers</string> + <key>reffered</key> + <string>referred</string> + <key>refference</key> + <string>reference</string> + <key>reffering</key> + <string>referring</string> + <key>refrence</key> + <string>reference</string> + <key>refrences</key> + <string>references</string> + <key>refrers</key> + <string>refers</string> + <key>refridgeration</key> + <string>refrigeration</string> + <key>refridgerator</key> + <string>refrigerator</string> + <key>refromist</key> + <string>reformist</string> + <key>refusla</key> + <string>refusal</string> + <key>regardes</key> + <string>regards</string> + <key>regluar</key> + <string>regular</string> + <key>reguarly</key> + <string>regularly</string> + <key>regulaion</key> + <string>regulation</string> + <key>regulaotrs</key> + <string>regulators</string> + <key>regularily</key> + <string>regularly</string> + <key>rehersal</key> + <string>rehearsal</string> + <key>reicarnation</key> + <string>reincarnation</string> + <key>reigining</key> + <string>reigning</string> + <key>reknown</key> + <string>renown</string> + <key>reknowned</key> + <string>renowned</string> + <key>rela</key> + <string>real</string> + <key>relaly</key> + <string>really</string> + <key>relatiopnship</key> + <string>relationship</string> + <key>relativly</key> + <string>relatively</string> + <key>relected</key> + <string>reelected</string> + <key>releive</key> + <string>relieve</string> + <key>releived</key> + <string>relieved</string> + <key>releiver</key> + <string>reliever</string> + <key>releses</key> + <string>releases</string> + <key>relevence</key> + <string>relevance</string> + <key>relevent</key> + <string>relevant</string> + <key>reliablity</key> + <string>reliability</string> + <key>relient</key> + <string>reliant</string> + <key>religeous</key> + <string>religious</string> + <key>religous</key> + <string>religious</string> + <key>religously</key> + <string>religiously</string> + <key>relinqushment</key> + <string>relinquishment</string> + <key>relitavely</key> + <string>relatively</string> + <key>relized</key> + <string>realized</string> + <key>relpacement</key> + <string>replacement</string> + <key>remaing</key> + <string>remaining</string> + <key>remeber</key> + <string>remember</string> + <key>rememberable</key> + <string>memorable</string> + <key>rememberance</key> + <string>remembrance</string> + <key>remembrence</key> + <string>remembrance</string> + <key>remenant</key> + <string>remnant</string> + <key>remenicent</key> + <string>reminiscent</string> + <key>reminent</key> + <string>remnant</string> + <key>reminescent</key> + <string>reminiscent</string> + <key>reminscent</key> + <string>reminiscent</string> + <key>reminsicent</key> + <string>reminiscent</string> + <key>rendevous</key> + <string>rendezvous</string> + <key>rendezous</key> + <string>rendezvous</string> + <key>renedered</key> + <string>rende</string> + <key>renewl</key> + <string>renewal</string> + <key>rennovate</key> + <string>renovate</string> + <key>rennovated</key> + <string>renovated</string> + <key>rennovating</key> + <string>renovating</string> + <key>rennovation</key> + <string>renovation</string> + <key>rentors</key> + <string>renters</string> + <key>reoccurrence</key> + <string>recurrence</string> + <key>reorganision</key> + <string>reorganisation</string> + <key>repatition</key> + <string>repetition</string> + <key>repectively</key> + <string>respectively</string> + <key>repeition</key> + <string>repetition</string> + <key>repentence</key> + <string>repentance</string> + <key>repentent</key> + <string>repentant</string> + <key>repeteadly</key> + <string>repeatedly</string> + <key>repetion</key> + <string>repetition</string> + <key>repid</key> + <string>rapid</string> + <key>reponse</key> + <string>response</string> + <key>reponsible</key> + <string>responsible</string> + <key>reportadly</key> + <string>reportedly</string> + <key>represantative</key> + <string>representative</string> + <key>representive</key> + <string>representative</string> + <key>representives</key> + <string>representatives</string> + <key>reproducable</key> + <string>reproducible</string> + <key>reprtoire</key> + <string>repertoire</string> + <key>repsectively</key> + <string>respectively</string> + <key>reptition</key> + <string>repetition</string> + <key>requirment</key> + <string>requirement</string> + <key>requred</key> + <string>required</string> + <key>resaurant</key> + <string>restaurant</string> + <key>resembelance</key> + <string>resemblance</string> + <key>resembes</key> + <string>resembles</string> + <key>resemblence</key> + <string>resemblance</string> + <key>resevoir</key> + <string>reservoir</string> + <key>residental</key> + <string>residential</string> + <key>resignement</key> + <string>resignment</string> + <key>resistable</key> + <string>resistible</string> + <key>resistence</key> + <string>resistance</string> + <key>resistent</key> + <string>resistant</string> + <key>respectivly</key> + <string>respectively</string> + <key>responce</key> + <string>response</string> + <key>responibilities</key> + <string>responsibilities</string> + <key>responisble</key> + <string>responsible</string> + <key>responnsibilty</key> + <string>responsibility</string> + <key>responsability</key> + <string>responsibility</string> + <key>responsibile</key> + <string>responsible</string> + <key>responsibilites</key> + <string>responsibilities</string> + <key>responsiblities</key> + <string>responsibilities</string> + <key>responsiblity</key> + <string>responsibility</string> + <key>ressemblance</key> + <string>resemblance</string> + <key>ressemble</key> + <string>resemble</string> + <key>ressembled</key> + <string>resembled</string> + <key>ressemblence</key> + <string>resemblance</string> + <key>ressembling</key> + <string>resembling</string> + <key>resssurecting</key> + <string>resurrecting</string> + <key>ressurect</key> + <string>resurrect</string> + <key>ressurected</key> + <string>resurrected</string> + <key>ressurection</key> + <string>resurrection</string> + <key>ressurrection</key> + <string>resurrection</string> + <key>restarant</key> + <string>restaurant</string> + <key>restarants</key> + <string>restaurants</string> + <key>restaraunt</key> + <string>restaurant</string> + <key>restaraunteur</key> + <string>restaurateur</string> + <key>restaraunteurs</key> + <string>restaurateurs</string> + <key>restaraunts</key> + <string>restaurants</string> + <key>restauranteurs</key> + <string>restaurateurs</string> + <key>restauration</key> + <string>restoration</string> + <key>restauraunt</key> + <string>restaurant</string> + <key>resteraunt</key> + <string>restaurant</string> + <key>resteraunts</key> + <string>restaurants</string> + <key>resticted</key> + <string>restricted</string> + <key>restraunt</key> + <string>restraint</string> + <key>resturant</key> + <string>restaurant</string> + <key>resturants</key> + <string>restaurants</string> + <key>resturaunt</key> + <string>restaurant</string> + <key>resturaunts</key> + <string>restaurants</string> + <key>resurecting</key> + <string>resurrecting</string> + <key>retalitated</key> + <string>retaliated</string> + <key>retalitation</key> + <string>retaliation</string> + <key>retreive</key> + <string>retrieve</string> + <key>returnd</key> + <string>returned</string> + <key>revaluated</key> + <string>reevaluated</string> + <key>reveiw</key> + <string>review</string> + <key>reveral</key> + <string>reversal</string> + <key>reversable</key> + <string>reversible</string> + <key>revolutionar</key> + <string>revolutionary</string> + <key>rewitten</key> + <string>rewritten</string> + <key>rewriet</key> + <string>rewrite</string> + <key>rference</key> + <string>reference</string> + <key>rferences</key> + <string>references</string> + <key>rhymme</key> + <string>rhyme</string> + <key>rhythem</key> + <string>rhythm</string> + <key>rhythim</key> + <string>rhythm</string> + <key>rhytmic</key> + <string>rhythmic</string> + <key>rigourous</key> + <string>rigorous</string> + <key>rininging</key> + <string>ringing</string> + <key>rised</key> + <string>rose</string> + <key>rococco</key> + <string>rococo</string> + <key>rocord</key> + <string>record</string> + <key>roomate</key> + <string>roommate</string> + <key>rougly</key> + <string>roughly</string> + <key>rucuperate</key> + <string>recuperate</string> + <key>rudimentatry</key> + <string>rudimentary</string> + <key>rulle</key> + <string>rule</string> + <key>runing</key> + <string>running</string> + <key>runnung</key> + <string>running</string> + <key>russina</key> + <string>Russian</string> + <key>rwite</key> + <string>write</string> + <key>rythem</key> + <string>rhythm</string> + <key>rythim</key> + <string>rhythm</string> + <key>rythm</key> + <string>rhythm</string> + <key>rythmic</key> + <string>rhythmic</string> + <key>rythyms</key> + <string>rhythms</string> + <key>sacrafice</key> + <string>sacrifice</string> + <key>sacreligious</key> + <string>sacrilegious</string> + <key>sacrifical</key> + <string>sacrificial</string> + <key>saftey</key> + <string>safety</string> + <key>safty</key> + <string>safety</string> + <key>salery</key> + <string>salary</string> + <key>sanctionning</key> + <string>sanctioning</string> + <key>sandwhich</key> + <string>sandwich</string> + <key>santioned</key> + <string>sanctioned</string> + <key>sargant</key> + <string>sergeant</string> + <key>sargeant</key> + <string>sergeant</string> + <key>satelite</key> + <string>satellite</string> + <key>satelites</key> + <string>satellites</string> + <key>satisfactority</key> + <string>satisfactorily</string> + <key>satric</key> + <string>satiric</string> + <key>satrical</key> + <string>satirical</string> + <key>satrically</key> + <string>satirically</string> + <key>sattelite</key> + <string>satellite</string> + <key>sattelites</key> + <string>satellites</string> + <key>saught</key> + <string>sought</string> + <key>saveing</key> + <string>saving</string> + <key>saxaphone</key> + <string>saxophone</string> + <key>scaleable</key> + <string>scalable</string> + <key>scandanavia</key> + <string>Scandinavia</string> + <key>scaricity</key> + <string>scarcity</string> + <key>scavanged</key> + <string>scavenged</string> + <key>schedual</key> + <string>schedule</string> + <key>scholarhip</key> + <string>scholarship</string> + <key>scholarstic</key> + <string>scholastic</string> + <key>scientfic</key> + <string>scientific</string> + <key>scientifc</key> + <string>scientific</string> + <key>scientis</key> + <string>scientist</string> + <key>scince</key> + <string>science</string> + <key>scinece</key> + <string>science</string> + <key>scirpt</key> + <string>script</string> + <key>scoll</key> + <string>scroll</string> + <key>screenwrighter</key> + <string>screenwriter</string> + <key>scrutinity</key> + <string>scrutiny</string> + <key>scuptures</key> + <string>sculptures</string> + <key>seach</key> + <string>search</string> + <key>seached</key> + <string>searched</string> + <key>seaches</key> + <string>searches</string> + <key>secratary</key> + <string>secretary</string> + <key>secretery</key> + <string>secretary</string> + <key>sedereal</key> + <string>sidereal</string> + <key>seeked</key> + <string>sought</string> + <key>segementation</key> + <string>segmentation</string> + <key>seguoys</key> + <string>segues</string> + <key>seige</key> + <string>siege</string> + <key>seing</key> + <string>seeing</string> + <key>seinor</key> + <string>senior</string> + <key>seldomly</key> + <string>seldom</string> + <key>senarios</key> + <string>scenarios</string> + <key>senstive</key> + <string>sensitive</string> + <key>sensure</key> + <string>censure</string> + <key>seperate</key> + <string>separate</string> + <key>seperated</key> + <string>separated</string> + <key>seperately</key> + <string>separately</string> + <key>seperates</key> + <string>separates</string> + <key>seperating</key> + <string>separating</string> + <key>seperation</key> + <string>separation</string> + <key>seperatism</key> + <string>separatism</string> + <key>seperatist</key> + <string>separatist</string> + <key>sepina</key> + <string>subpoena</string> + <key>sergent</key> + <string>sergeant</string> + <key>settelement</key> + <string>settlement</string> + <key>settlment</key> + <string>settlement</string> + <key>severeal</key> + <string>several</string> + <key>severley</key> + <string>severely</string> + <key>severly</key> + <string>severely</string> + <key>sevice</key> + <string>service</string> + <key>shadasloo</key> + <string>shadaloo</string> + <key>shaddow</key> + <string>shadow</string> + <key>shadoloo</key> + <string>shadaloo</string> + <key>shamen</key> + <string>shaman</string> + <key>sheat</key> + <string>sheath</string> + <key>sheild</key> + <string>shield</string> + <key>sherif</key> + <string>sheriff</string> + <key>shineing</key> + <string>shining</string> + <key>shiped</key> + <string>shipped</string> + <key>shiping</key> + <string>shipping</string> + <key>shopkeeepers</key> + <string>shopkeepers</string> + <key>shorly</key> + <string>shortly</string> + <key>shortwhile</key> + <string>short while</string> + <key>shoudl</key> + <string>should</string> + <key>shoudln</key> + <string>shouldn't</string> + <key>shouldnt</key> + <string>shouldn't</string> + <key>shreak</key> + <string>shriek</string> + <key>shrinked</key> + <string>shrunk</string> + <key>sicne</key> + <string>since</string> + <key>sideral</key> + <string>sidereal</string> + <key>siezure</key> + <string>seizure</string> + <key>siezures</key> + <string>seizures</string> + <key>siginificant</key> + <string>significant</string> + <key>signficant</key> + <string>significant</string> + <key>signficiant</key> + <string>significant</string> + <key>signfies</key> + <string>signifies</string> + <key>signifantly</key> + <string>significantly</string> + <key>significently</key> + <string>significantly</string> + <key>signifigant</key> + <string>significant</string> + <key>signifigantly</key> + <string>significantly</string> + <key>signitories</key> + <string>signatories</string> + <key>signitory</key> + <string>signatory</string> + <key>similarily</key> + <string>similarly</string> + <key>similiar</key> + <string>similar</string> + <key>similiarity</key> + <string>similarity</string> + <key>similiarly</key> + <string>similarly</string> + <key>simmilar</key> + <string>similar</string> + <key>simpley</key> + <string>simply</string> + <key>simplier</key> + <string>simpler</string> + <key>simultanous</key> + <string>simultaneous</string> + <key>simultanously</key> + <string>simultaneously</string> + <key>sincerley</key> + <string>sincerely</string> + <key>singsog</key> + <string>singsong</string> + <key>sinse</key> + <string>since</string> + <key>skateing</key> + <string>skating</string> + <key>slaugterhouses</key> + <string>slaughterhouses</string> + <key>slighly</key> + <string>slightly</string> + <key>slowy</key> + <string>slowly</string> + <key>smae</key> + <string>same</string> + <key>smealting</key> + <string>smelting</string> + <key>smoe</key> + <string>some</string> + <key>sneeks</key> + <string>sneaks</string> + <key>snese</key> + <string>sneeze</string> + <key>socalism</key> + <string>socialism</string> + <key>socities</key> + <string>societies</string> + <key>soem</key> + <string>some</string> + <key>sofware</key> + <string>software</string> + <key>sohw</key> + <string>show</string> + <key>soilders</key> + <string>soldiers</string> + <key>solatary</key> + <string>solitary</string> + <key>soley</key> + <string>solely</string> + <key>soliders</key> + <string>soldiers</string> + <key>soliliquy</key> + <string>soliloquy</string> + <key>soluable</key> + <string>soluble</string> + <key>somene</key> + <string>someone</string> + <key>somtimes</key> + <string>sometimes</string> + <key>somwhere</key> + <string>somewhere</string> + <key>sophicated</key> + <string>sophisticated</string> + <key>sophmore</key> + <string>sophomore</string> + <key>sorceror</key> + <string>sorcerer</string> + <key>sorrounding</key> + <string>surrounding</string> + <key>sotry</key> + <string>story</string> + <key>sotyr</key> + <string>story</string> + <key>soudn</key> + <string>sound</string> + <key>soudns</key> + <string>sounds</string> + <key>sould</key> + <string>could</string> + <key>sountrack</key> + <string>soundtrack</string> + <key>sourth</key> + <string>south</string> + <key>sourthern</key> + <string>southern</string> + <key>souvenier</key> + <string>souvenir</string> + <key>souveniers</key> + <string>souvenirs</string> + <key>soveits</key> + <string>soviets</string> + <key>sovereignity</key> + <string>sovereignty</string> + <key>soverign</key> + <string>sovereign</string> + <key>soverignity</key> + <string>sovereignty</string> + <key>soverignty</key> + <string>sovereignty</string> + <key>spainish</key> + <string>Spanish</string> + <key>speach</key> + <string>speech</string> + <key>specfic</key> + <string>specific</string> + <key>speciallized</key> + <string>specialized</string> + <key>specifiying</key> + <string>specifying</string> + <key>speciman</key> + <string>specimen</string> + <key>spectauclar</key> + <string>spectacular</string> + <key>spectaulars</key> + <string>spectaculars</string> + <key>spectum</key> + <string>spectrum</string> + <key>speices</key> + <string>species</string> + <key>spendour</key> + <string>splendour</string> + <key>spermatozoan</key> + <string>spermatozoon</string> + <key>spoace</key> + <string>space</string> + <key>sponser</key> + <string>sponsor</string> + <key>sponsered</key> + <string>sponsored</string> + <key>spontanous</key> + <string>spontaneous</string> + <key>sponzored</key> + <string>sponsored</string> + <key>spoonfulls</key> + <string>spoonfuls</string> + <key>sppeches</key> + <string>speeches</string> + <key>spreaded</key> + <string>spread</string> + <key>sprech</key> + <string>speech</string> + <key>spred</key> + <string>spread</string> + <key>spriritual</key> + <string>spiritual</string> + <key>spritual</key> + <string>spiritual</string> + <key>sqaure</key> + <string>square</string> + <key>stablility</key> + <string>stability</string> + <key>stainlees</key> + <string>stainless</string> + <key>staion</key> + <string>station</string> + <key>standars</key> + <string>standards</string> + <key>stange</key> + <string>strange</string> + <key>startegic</key> + <string>strategic</string> + <key>startegies</key> + <string>strategies</string> + <key>startegy</key> + <string>strategy</string> + <key>stateman</key> + <string>statesman</string> + <key>statememts</key> + <string>statements</string> + <key>statment</key> + <string>statement</string> + <key>steriods</key> + <string>steroids</string> + <key>sterotypes</key> + <string>stereotypes</string> + <key>stilus</key> + <string>stylus</string> + <key>stingent</key> + <string>stringent</string> + <key>stiring</key> + <string>stirring</string> + <key>stirrs</key> + <string>stirs</string> + <key>stlye</key> + <string>style</string> + <key>stomache</key> + <string>stomach</string> + <key>stong</key> + <string>strong</string> + <key>stopry</key> + <string>story</string> + <key>storeis</key> + <string>stories</string> + <key>storise</key> + <string>stories</string> + <key>stornegst</key> + <string>strongest</string> + <key>stoyr</key> + <string>story</string> + <key>stpo</key> + <string>stop</string> + <key>stradegies</key> + <string>strategies</string> + <key>stradegy</key> + <string>strategy</string> + <key>strat</key> + <string>start</string> + <key>stratagically</key> + <string>strategically</string> + <key>streemlining</key> + <string>streamlining</string> + <key>stregth</key> + <string>strength</string> + <key>strenghen</key> + <string>strengthen</string> + <key>strenghened</key> + <string>strengthened</string> + <key>strenghening</key> + <string>strengthening</string> + <key>strenght</key> + <string>strength</string> + <key>strenghten</key> + <string>strengthen</string> + <key>strenghtened</key> + <string>strengthened</string> + <key>strenghtening</key> + <string>strengthening</string> + <key>strengtened</key> + <string>strengthened</string> + <key>strenous</key> + <string>strenuous</string> + <key>strictist</key> + <string>strictest</string> + <key>strikely</key> + <string>strikingly</string> + <key>strnad</key> + <string>strand</string> + <key>stroy</key> + <string>story</string> + <key>structual</key> + <string>structural</string> + <key>stubborness</key> + <string>stubbornness</string> + <key>stucture</key> + <string>structure</string> + <key>stuctured</key> + <string>structured</string> + <key>studdy</key> + <string>study</string> + <key>studing</key> + <string>studying</string> + <key>stuggling</key> + <string>struggling</string> + <key>sturcture</key> + <string>structure</string> + <key>subcatagories</key> + <string>subcategories</string> + <key>subcatagory</key> + <string>subcategory</string> + <key>subconsiously</key> + <string>subconsciously</string> + <key>subjudgation</key> + <string>subjugation</string> + <key>submachne</key> + <string>submachine</string> + <key>subpecies</key> + <string>subspecies</string> + <key>subsidary</key> + <string>subsidiary</string> + <key>subsiduary</key> + <string>subsidiary</string> + <key>subsquent</key> + <string>subsequent</string> + <key>subsquently</key> + <string>subsequently</string> + <key>substace</key> + <string>substance</string> + <key>substancial</key> + <string>substantial</string> + <key>substatial</key> + <string>substantial</string> + <key>substituded</key> + <string>substituted</string> + <key>substract</key> + <string>subtract</string> + <key>substracted</key> + <string>subtracted</string> + <key>substracting</key> + <string>subtracting</string> + <key>substraction</key> + <string>subtraction</string> + <key>substracts</key> + <string>subtracts</string> + <key>subtances</key> + <string>substances</string> + <key>subterranian</key> + <string>subterranean</string> + <key>suburburban</key> + <string>suburban</string> + <key>succceeded</key> + <string>succeeded</string> + <key>succcesses</key> + <string>successes</string> + <key>succedded</key> + <string>succeeded</string> + <key>succeded</key> + <string>succeeded</string> + <key>succeds</key> + <string>succeeds</string> + <key>succesful</key> + <string>successful</string> + <key>succesfully</key> + <string>successfully</string> + <key>succesfuly</key> + <string>successfully</string> + <key>succesion</key> + <string>succession</string> + <key>succesive</key> + <string>successive</string> + <key>successfull</key> + <string>successful</string> + <key>successully</key> + <string>successfully</string> + <key>succsess</key> + <string>success</string> + <key>succsessfull</key> + <string>successful</string> + <key>suceed</key> + <string>succeed</string> + <key>suceeded</key> + <string>succeeded</string> + <key>suceeding</key> + <string>succeeding</string> + <key>suceeds</key> + <string>succeeds</string> + <key>sucesful</key> + <string>successful</string> + <key>sucesfully</key> + <string>successfully</string> + <key>sucesfuly</key> + <string>successfully</string> + <key>sucesion</key> + <string>succession</string> + <key>sucess</key> + <string>success</string> + <key>sucesses</key> + <string>successes</string> + <key>sucessful</key> + <string>successful</string> + <key>sucessfull</key> + <string>successful</string> + <key>sucessfully</key> + <string>successfully</string> + <key>sucessfuly</key> + <string>successfully</string> + <key>sucession</key> + <string>succession</string> + <key>sucessive</key> + <string>successive</string> + <key>sucessor</key> + <string>successor</string> + <key>sucessot</key> + <string>successor</string> + <key>sucide</key> + <string>suicide</string> + <key>sucidial</key> + <string>suicidal</string> + <key>sufferage</key> + <string>suffrage</string> + <key>sufferred</key> + <string>suffered</string> + <key>sufferring</key> + <string>suffering</string> + <key>sufficent</key> + <string>sufficient</string> + <key>sufficently</key> + <string>sufficiently</string> + <key>sumary</key> + <string>summary</string> + <key>sunglases</key> + <string>sunglasses</string> + <key>suop</key> + <string>soup</string> + <key>superceeded</key> + <string>superseded</string> + <key>superintendant</key> + <string>superintendent</string> + <key>suphisticated</key> + <string>sophisticated</string> + <key>suplimented</key> + <string>supplemented</string> + <key>supose</key> + <string>suppose</string> + <key>suposed</key> + <string>supposed</string> + <key>suposedly</key> + <string>supposedly</string> + <key>suposes</key> + <string>supposes</string> + <key>suposing</key> + <string>supposing</string> + <key>supplamented</key> + <string>supplemented</string> + <key>suppliementing</key> + <string>supplementing</string> + <key>suppoed</key> + <string>supposed</string> + <key>supposingly</key> + <string>supposedly</string> + <key>suppy</key> + <string>supply</string> + <key>supress</key> + <string>suppress</string> + <key>supressed</key> + <string>suppressed</string> + <key>supresses</key> + <string>suppresses</string> + <key>supressing</key> + <string>suppressing</string> + <key>suprise</key> + <string>surprise</string> + <key>suprised</key> + <string>surprised</string> + <key>suprising</key> + <string>surprising</string> + <key>suprisingly</key> + <string>surprisingly</string> + <key>suprize</key> + <string>surprise</string> + <key>suprized</key> + <string>surprised</string> + <key>suprizing</key> + <string>surprising</string> + <key>suprizingly</key> + <string>surprisingly</string> + <key>surfce</key> + <string>surface</string> + <key>surley</key> + <string>surely</string> + <key>suround</key> + <string>surround</string> + <key>surounded</key> + <string>surrounded</string> + <key>surounding</key> + <string>surrounding</string> + <key>suroundings</key> + <string>surroundings</string> + <key>surounds</key> + <string>surrounds</string> + <key>surplanted</key> + <string>supplanted</string> + <key>surpress</key> + <string>suppress</string> + <key>surpressed</key> + <string>suppressed</string> + <key>surprize</key> + <string>surprise</string> + <key>surprized</key> + <string>surprised</string> + <key>surprizing</key> + <string>surprising</string> + <key>surprizingly</key> + <string>surprisingly</string> + <key>surrended</key> + <string>surrendered</string> + <key>surrepetitious</key> + <string>surreptitious</string> + <key>surrepetitiously</key> + <string>surreptitiously</string> + <key>surreptious</key> + <string>surreptitious</string> + <key>surreptiously</key> + <string>surreptitiously</string> + <key>surronded</key> + <string>surrounded</string> + <key>surrouded</key> + <string>surrounded</string> + <key>surrouding</key> + <string>surrounding</string> + <key>surrundering</key> + <string>surrendering</string> + <key>surveilence</key> + <string>surveillance</string> + <key>surveill</key> + <string>surveil</string> + <key>surveyer</key> + <string>surveyor</string> + <key>surviver</key> + <string>survivor</string> + <key>survivers</key> + <string>survivors</string> + <key>survivied</key> + <string>survived</string> + <key>suseptable</key> + <string>susceptible</string> + <key>suseptible</key> + <string>susceptible</string> + <key>suspention</key> + <string>suspension</string> + <key>swaer</key> + <string>swear</string> + <key>swaers</key> + <string>swears</string> + <key>swepth</key> + <string>swept</string> + <key>swiming</key> + <string>swimming</string> + <key>syas</key> + <string>says</string> + <key>symetrical</key> + <string>symmetrical</string> + <key>symetrically</key> + <string>symmetrically</string> + <key>symetry</key> + <string>symmetry</string> + <key>symettric</key> + <string>symmetric</string> + <key>symmetral</key> + <string>symmetric</string> + <key>symmetricaly</key> + <string>symmetrically</string> + <key>synagouge</key> + <string>synagogue</string> + <key>syncronization</key> + <string>synchronization</string> + <key>synonomous</key> + <string>synonymous</string> + <key>synonymns</key> + <string>synonyms</string> + <key>synphony</key> + <string>symphony</string> + <key>syphyllis</key> + <string>syphilis</string> + <key>sypmtoms</key> + <string>symptoms</string> + <key>syrap</key> + <string>syrup</string> + <key>sysmatically</key> + <string>systematically</string> + <key>sytem</key> + <string>system</string> + <key>sytle</key> + <string>style</string> + <key>tabacco</key> + <string>tobacco</string> + <key>tahn</key> + <string>than</string> + <key>taht</key> + <string>that</string> + <key>talekd</key> + <string>talked</string> + <key>targetted</key> + <string>targeted</string> + <key>targetting</key> + <string>targeting</string> + <key>tast</key> + <string>taste</string> + <key>tath</key> + <string>that</string> + <key>tattooes</key> + <string>tattoos</string> + <key>taxanomic</key> + <string>taxonomic</string> + <key>taxanomy</key> + <string>taxonomy</string> + <key>teached</key> + <string>taught</string> + <key>techician</key> + <string>technician</string> + <key>techicians</key> + <string>technicians</string> + <key>techiniques</key> + <string>techniques</string> + <key>technitian</key> + <string>technician</string> + <key>technnology</key> + <string>technology</string> + <key>technolgy</key> + <string>technology</string> + <key>teh</key> + <string>the</string> + <key>tehy</key> + <string>they</string> + <key>telelevision</key> + <string>television</string> + <key>televsion</key> + <string>television</string> + <key>telphony</key> + <string>telephony</string> + <key>temerature</key> + <string>temperature</string> + <key>tempalte</key> + <string>template</string> + <key>tempaltes</key> + <string>templates</string> + <key>temparate</key> + <string>temperate</string> + <key>temperarily</key> + <string>temporarily</string> + <key>temperment</key> + <string>temperament</string> + <key>tempertaure</key> + <string>temperature</string> + <key>temperture</key> + <string>temperature</string> + <key>temprary</key> + <string>temporary</string> + <key>tenacle</key> + <string>tentacle</string> + <key>tenacles</key> + <string>tentacles</string> + <key>tendacy</key> + <string>tendency</string> + <key>tendancies</key> + <string>tendencies</string> + <key>tendancy</key> + <string>tendency</string> + <key>tennisplayer</key> + <string>tennis player</string> + <key>tepmorarily</key> + <string>temporarily</string> + <key>terrestial</key> + <string>terrestrial</string> + <key>terriories</key> + <string>territories</string> + <key>terriory</key> + <string>territory</string> + <key>territorist</key> + <string>terrorist</string> + <key>territoy</key> + <string>territory</string> + <key>terroist</key> + <string>terrorist</string> + <key>testiclular</key> + <string>testicular</string> + <key>tghe</key> + <string>the</string> + <key>thast</key> + <string>that's</string> + <key>theather</key> + <string>theater</string> + <key>theese</key> + <string>these</string> + <key>theif</key> + <string>thief</string> + <key>theives</key> + <string>thieves</string> + <key>themselfs</key> + <string>themselves</string> + <key>themslves</key> + <string>themselves</string> + <key>ther</key> + <string>there</string> + <key>therafter</key> + <string>thereafter</string> + <key>therby</key> + <string>thereby</string> + <key>theri</key> + <string>their</string> + <key>theyre</key> + <string>they're</string> + <key>thgat</key> + <string>that</string> + <key>thge</key> + <string>the</string> + <key>thier</key> + <string>their</string> + <key>thign</key> + <string>thing</string> + <key>thigns</key> + <string>things</string> + <key>thigsn</key> + <string>things</string> + <key>thikn</key> + <string>think</string> + <key>thikning</key> + <string>thinking</string> + <key>thikns</key> + <string>thinks</string> + <key>thiunk</key> + <string>think</string> + <key>thn</key> + <string>then</string> + <key>thna</key> + <string>than</string> + <key>thne</key> + <string>then</string> + <key>thnig</key> + <string>thing</string> + <key>thnigs</key> + <string>things</string> + <key>thoughout</key> + <string>throughout</string> + <key>threatend</key> + <string>threatened</string> + <key>threatning</key> + <string>threatening</string> + <key>threee</key> + <string>three</string> + <key>threshhold</key> + <string>threshold</string> + <key>thrid</key> + <string>third</string> + <key>throrough</key> + <string>thorough</string> + <key>throughly</key> + <string>thoroughly</string> + <key>throught</key> + <string>throat</string> + <key>througout</key> + <string>throughout</string> + <key>thru</key> + <string>through</string> + <key>thsi</key> + <string>this</string> + <key>thsoe</key> + <string>those</string> + <key>thta</key> + <string>that</string> + <key>thyat</key> + <string>that</string> + <key>tiem</key> + <string>time</string> + <key>tihkn</key> + <string>think</string> + <key>tihs</key> + <string>this</string> + <key>timne</key> + <string>time</string> + <key>tiome</key> + <string>time</string> + <key>tje</key> + <string>the</string> + <key>tjhe</key> + <string>the</string> + <key>tjpanishad</key> + <string>upanishad</string> + <key>tkae</key> + <string>take</string> + <key>tkaes</key> + <string>takes</string> + <key>tkaing</key> + <string>taking</string> + <key>tlaking</key> + <string>talking</string> + <key>tobbaco</key> + <string>tobacco</string> + <key>todays</key> + <string>today's</string> + <key>todya</key> + <string>today</string> + <key>toghether</key> + <string>together</string> + <key>toke</key> + <string>took</string> + <key>tolerence</key> + <string>tolerance</string> + <key>tomatos</key> + <string>tomatoes</string> + <key>tommorow</key> + <string>tomorrow</string> + <key>tommorrow</key> + <string>tomorrow</string> + <key>tongiht</key> + <string>tonight</string> + <key>toriodal</key> + <string>toroidal</string> + <key>tormenters</key> + <string>tormentors</string> + <key>tornadoe</key> + <string>tornado</string> + <key>torpeados</key> + <string>torpedoes</string> + <key>torpedos</key> + <string>torpedoes</string> + <key>tothe</key> + <string>to the</string> + <key>toubles</key> + <string>troubles</string> + <key>tounge</key> + <string>tongue</string> + <key>tourch</key> + <string>torch</string> + <key>towords</key> + <string>towards</string> + <key>towrad</key> + <string>toward</string> + <key>tradionally</key> + <string>traditionally</string> + <key>traditionaly</key> + <string>traditionally</string> + <key>traditionnal</key> + <string>traditional</string> + <key>traditition</key> + <string>tradition</string> + <key>tradtionally</key> + <string>traditionally</string> + <key>trafficed</key> + <string>trafficked</string> + <key>trafficing</key> + <string>trafficking</string> + <key>trafic</key> + <string>traffic</string> + <key>trancendent</key> + <string>transcendent</string> + <key>trancending</key> + <string>transcending</string> + <key>tranform</key> + <string>transform</string> + <key>tranformed</key> + <string>transformed</string> + <key>transcendance</key> + <string>transcendence</string> + <key>transcendant</key> + <string>transcendent</string> + <key>transcendentational</key> + <string>transcendental</string> + <key>transcripting</key> + <string>transcribing</string> + <key>transending</key> + <string>transcending</string> + <key>transesxuals</key> + <string>transsexuals</string> + <key>transfered</key> + <string>transferred</string> + <key>transfering</key> + <string>transferring</string> + <key>transformaton</key> + <string>transformation</string> + <key>transistion</key> + <string>transition</string> + <key>translater</key> + <string>translator</string> + <key>translaters</key> + <string>translators</string> + <key>transmissable</key> + <string>transmissible</string> + <key>transporation</key> + <string>transportation</string> + <key>tremelo</key> + <string>tremolo</string> + <key>tremelos</key> + <string>tremolos</string> + <key>triguered</key> + <string>triggered</string> + <key>triology</key> + <string>trilogy</string> + <key>troling</key> + <string>trolling</string> + <key>troup</key> + <string>troupe</string> + <key>troups</key> + <string>troops</string> + <key>truely</key> + <string>truly</string> + <key>trustworthyness</key> + <string>trustworthiness</string> + <key>turnk</key> + <string>trunk</string> + <key>tust</key> + <string>trust</string> + <key>twelth</key> + <string>twelfth</string> + <key>twon</key> + <string>town</string> + <key>twpo</key> + <string>two</string> + <key>tyhat</key> + <string>that</string> + <key>tyhe</key> + <string>they</string> + <key>typcial</key> + <string>typical</string> + <key>typicaly</key> + <string>typically</string> + <key>tyranies</key> + <string>tyrannies</string> + <key>tyrany</key> + <string>tyranny</string> + <key>tyrranies</key> + <string>tyrannies</string> + <key>tyrrany</key> + <string>tyranny</string> + <key>ubiquitious</key> + <string>ubiquitous</string> + <key>ublisher</key> + <string>publisher</string> + <key>uise</key> + <string>use</string> + <key>ultimely</key> + <string>ultimately</string> + <key>unacompanied</key> + <string>unaccompanied</string> + <key>unahppy</key> + <string>unhappy</string> + <key>unanymous</key> + <string>unanimous</string> + <key>unathorised</key> + <string>unauthorised</string> + <key>unavailible</key> + <string>unavailable</string> + <key>unballance</key> + <string>unbalance</string> + <key>unbeknowst</key> + <string>unbeknownst</string> + <key>unbeleivable</key> + <string>unbelievable</string> + <key>uncertainity</key> + <string>uncertainty</string> + <key>unchallengable</key> + <string>unchallengeable</string> + <key>unchangable</key> + <string>unchangeable</string> + <key>uncompetive</key> + <string>uncompetitive</string> + <key>unconcious</key> + <string>unconscious</string> + <key>unconciousness</key> + <string>unconsciousness</string> + <key>unconfortability</key> + <string>discomfort</string> + <key>uncontitutional</key> + <string>unconstitutional</string> + <key>unconvential</key> + <string>unconventional</string> + <key>undecideable</key> + <string>undecidable</string> + <key>understoon</key> + <string>understood</string> + <key>undesireable</key> + <string>undesirable</string> + <key>undetecable</key> + <string>undetectable</string> + <key>undoubtely</key> + <string>undoubtedly</string> + <key>undreground</key> + <string>underground</string> + <key>uneccesary</key> + <string>unnecessary</string> + <key>unecessary</key> + <string>unnecessary</string> + <key>unequalities</key> + <string>inequalities</string> + <key>unforetunately</key> + <string>unfortunately</string> + <key>unforgetable</key> + <string>unforgettable</string> + <key>unforgiveable</key> + <string>unforgivable</string> + <key>unfortunatley</key> + <string>unfortunately</string> + <key>unfortunatly</key> + <string>unfortunately</string> + <key>unfourtunately</key> + <string>unfortunately</string> + <key>unihabited</key> + <string>uninhabited</string> + <key>unilateraly</key> + <string>unilaterally</string> + <key>unilatreal</key> + <string>unilateral</string> + <key>unilatreally</key> + <string>unilaterally</string> + <key>uninterruped</key> + <string>uninterrupted</string> + <key>uninterupted</key> + <string>uninterrupted</string> + <key>univeral</key> + <string>universal</string> + <key>univeristies</key> + <string>universities</string> + <key>univeristy</key> + <string>university</string> + <key>univerity</key> + <string>university</string> + <key>universtiy</key> + <string>university</string> + <key>univesities</key> + <string>universities</string> + <key>univesity</key> + <string>university</string> + <key>unkown</key> + <string>unknown</string> + <key>unlikey</key> + <string>unlikely</string> + <key>unmanouverable</key> + <string>unmaneuverable</string> + <key>unmistakeably</key> + <string>unmistakably</string> + <key>unneccesarily</key> + <string>unnecessarily</string> + <key>unneccesary</key> + <string>unnecessary</string> + <key>unneccessarily</key> + <string>unnecessarily</string> + <key>unneccessary</key> + <string>unnecessary</string> + <key>unnecesarily</key> + <string>unnecessarily</string> + <key>unnecesary</key> + <string>unnecessary</string> + <key>unoffical</key> + <string>unofficial</string> + <key>unoperational</key> + <string>nonoperational</string> + <key>unoticeable</key> + <string>unnoticeable</string> + <key>unplease</key> + <string>displease</string> + <key>unplesant</key> + <string>unpleasant</string> + <key>unprecendented</key> + <string>unprecedented</string> + <key>unprecidented</key> + <string>unprecedented</string> + <key>unrepentent</key> + <string>unrepentant</string> + <key>unrepetant</key> + <string>unrepentant</string> + <key>unrepetent</key> + <string>unrepentant</string> + <key>unsed</key> + <string>unused</string> + <key>unsubstanciated</key> + <string>unsubstantiated</string> + <key>unsuccesful</key> + <string>unsuccessful</string> + <key>unsuccesfully</key> + <string>unsuccessfully</string> + <key>unsuccessfull</key> + <string>unsuccessful</string> + <key>unsucesful</key> + <string>unsuccessful</string> + <key>unsucesfuly</key> + <string>unsuccessfully</string> + <key>unsucessful</key> + <string>unsuccessful</string> + <key>unsucessfull</key> + <string>unsuccessful</string> + <key>unsucessfully</key> + <string>unsuccessfully</string> + <key>unsuprised</key> + <string>unsurprised</string> + <key>unsuprising</key> + <string>unsurprising</string> + <key>unsuprisingly</key> + <string>unsurprisingly</string> + <key>unsuprized</key> + <string>unsurprised</string> + <key>unsuprizing</key> + <string>unsurprising</string> + <key>unsuprizingly</key> + <string>unsurprisingly</string> + <key>unsurprized</key> + <string>unsurprised</string> + <key>unsurprizing</key> + <string>unsurprising</string> + <key>unsurprizingly</key> + <string>unsurprisingly</string> + <key>untill</key> + <string>until</string> + <key>untranslateable</key> + <string>untranslatable</string> + <key>unuseable</key> + <string>unusable</string> + <key>unusuable</key> + <string>unusable</string> + <key>unviersity</key> + <string>university</string> + <key>unwarrented</key> + <string>unwarranted</string> + <key>unweildly</key> + <string>unwieldy</string> + <key>unwieldly</key> + <string>unwieldy</string> + <key>upcomming</key> + <string>upcoming</string> + <key>upgradded</key> + <string>upgraded</string> + <key>upto</key> + <string>up to</string> + <key>usally</key> + <string>usually</string> + <key>useage</key> + <string>usage</string> + <key>usefull</key> + <string>useful</string> + <key>usefuly</key> + <string>usefully</string> + <key>useing</key> + <string>using</string> + <key>usualy</key> + <string>usually</string> + <key>ususally</key> + <string>usually</string> + <key>vaccum</key> + <string>vacuum</string> + <key>vaccume</key> + <string>vacuum</string> + <key>vacinity</key> + <string>vicinity</string> + <key>vaguaries</key> + <string>vagaries</string> + <key>vaieties</key> + <string>varieties</string> + <key>vailidty</key> + <string>validity</string> + <key>valetta</key> + <string>valletta</string> + <key>valuble</key> + <string>valuable</string> + <key>valueable</key> + <string>valuable</string> + <key>varations</key> + <string>variations</string> + <key>varient</key> + <string>variant</string> + <key>variey</key> + <string>variety</string> + <key>varing</key> + <string>varying</string> + <key>varities</key> + <string>varieties</string> + <key>varity</key> + <string>variety</string> + <key>vasall</key> + <string>vassal</string> + <key>vasalls</key> + <string>vassals</string> + <key>vegatarian</key> + <string>vegetarian</string> + <key>vegitable</key> + <string>vegetable</string> + <key>vegitables</key> + <string>vegetables</string> + <key>vegtable</key> + <string>vegetable</string> + <key>vehicule</key> + <string>vehicle</string> + <key>vell</key> + <string>well</string> + <key>venemous</key> + <string>venomous</string> + <key>vengance</key> + <string>vengeance</string> + <key>vengence</key> + <string>vengeance</string> + <key>verfication</key> + <string>verification</string> + <key>verison</key> + <string>version</string> + <key>verisons</key> + <string>versions</string> + <key>vermillion</key> + <string>vermilion</string> + <key>versitilaty</key> + <string>versatility</string> + <key>versitlity</key> + <string>versatility</string> + <key>vetween</key> + <string>between</string> + <key>veyr</key> + <string>very</string> + <key>vigeur</key> + <string>vigor</string> + <key>vigilence</key> + <string>vigilance</string> + <key>vigourous</key> + <string>vigorous</string> + <key>villian</key> + <string>villain</string> + <key>villification</key> + <string>vilification</string> + <key>villify</key> + <string>vilify</string> + <key>villin</key> + <string>villain</string> + <key>vincinity</key> + <string>vicinity</string> + <key>violentce</key> + <string>violence</string> + <key>virtualy</key> + <string>virtually</string> + <key>virutal</key> + <string>virtual</string> + <key>virutally</key> + <string>virtually</string> + <key>visable</key> + <string>visible</string> + <key>visably</key> + <string>visibly</string> + <key>visting</key> + <string>visiting</string> + <key>vistors</key> + <string>visitors</string> + <key>vitories</key> + <string>victories</string> + <key>volcanoe</key> + <string>volcano</string> + <key>voleyball</key> + <string>volleyball</string> + <key>volontary</key> + <string>voluntary</string> + <key>volonteer</key> + <string>volunteer</string> + <key>volonteered</key> + <string>volunteered</string> + <key>volonteering</key> + <string>volunteering</string> + <key>volonteers</key> + <string>volunteers</string> + <key>volounteer</key> + <string>volunteer</string> + <key>volounteered</key> + <string>volunteered</string> + <key>volounteering</key> + <string>volunteering</string> + <key>volounteers</key> + <string>volunteers</string> + <key>volumne</key> + <string>volume</string> + <key>vreity</key> + <string>variety</string> + <key>vrey</key> + <string>very</string> + <key>vriety</key> + <string>variety</string> + <key>vulnerablility</key> + <string>vulnerability</string> + <key>vyer</key> + <string>very</string> + <key>vyre</key> + <string>very</string> + <key>waht</key> + <string>what</string> + <key>wanna</key> + <string>want to</string> + <key>warantee</key> + <string>warranty</string> + <key>wardobe</key> + <string>wardrobe</string> + <key>warrent</key> + <string>warrant</string> + <key>warrriors</key> + <string>warriors</string> + <key>wasnt</key> + <string>wasn't</string> + <key>wass</key> + <string>was</string> + <key>watn</key> + <string>want</string> + <key>wayword</key> + <string>wayward</string> + <key>weaponary</key> + <string>weaponry</string> + <key>weas</key> + <string>was</string> + <key>wehn</key> + <string>when</string> + <key>weild</key> + <string>wield</string> + <key>weilded</key> + <string>wielded</string> + <key>wendsay</key> + <string>Wednesday</string> + <key>wensday</key> + <string>Wednesday</string> + <key>wereabouts</key> + <string>whereabouts</string> + <key>whant</key> + <string>want</string> + <key>whants</key> + <string>wants</string> + <key>whcih</key> + <string>which</string> + <key>wheras</key> + <string>whereas</string> + <key>wherease</key> + <string>whereas</string> + <key>whereever</key> + <string>wherever</string> + <key>whic</key> + <string>which</string> + <key>whihc</key> + <string>which</string> + <key>whith</key> + <string>with</string> + <key>whlch</key> + <string>which</string> + <key>whn</key> + <string>when</string> + <key>wholey</key> + <string>wholly</string> + <key>wholy</key> + <string>holy</string> + <key>whta</key> + <string>what</string> + <key>whther</key> + <string>whether</string> + <key>wich</key> + <string>which</string> + <key>widesread</key> + <string>widespread</string> + <key>wief</key> + <string>wife</string> + <key>wierd</key> + <string>weird</string> + <key>wiew</key> + <string>view</string> + <key>wih</key> + <string>with</string> + <key>wiht</key> + <string>with</string> + <key>wille</key> + <string>will</string> + <key>willingless</key> + <string>willingness</string> + <key>wirting</key> + <string>writing</string> + <key>withdrawl</key> + <string>withdrawal</string> + <key>witheld</key> + <string>withheld</string> + <key>withh</key> + <string>with</string> + <key>withing</key> + <string>within</string> + <key>withold</key> + <string>withhold</string> + <key>witht</key> + <string>with</string> + <key>witn</key> + <string>with</string> + <key>wiull</key> + <string>will</string> + <key>wnat</key> + <string>want</string> + <key>wnated</key> + <string>wanted</string> + <key>wnats</key> + <string>wants</string> + <key>wohle</key> + <string>whole</string> + <key>wokr</key> + <string>work</string> + <key>wokring</key> + <string>working</string> + <key>wonderfull</key> + <string>wonderful</string> + <key>wont</key> + <string>won't</string> + <key>wordlwide</key> + <string>worldwide</string> + <key>workststion</key> + <string>workstation</string> + <key>worls</key> + <string>world</string> + <key>worstened</key> + <string>worsened</string> + <key>woudl</key> + <string>would</string> + <key>wresters</key> + <string>wrestlers</string> + <key>wriet</key> + <string>write</string> + <key>writen</key> + <string>written</string> + <key>wroet</key> + <string>wrote</string> + <key>wrok</key> + <string>work</string> + <key>wroking</key> + <string>working</string> + <key>wtih</key> + <string>with</string> + <key>wupport</key> + <string>support</string> + <key>xenophoby</key> + <string>xenophobia</string> + <key>yaching</key> + <string>yachting</string> + <key>yaer</key> + <string>year</string> + <key>yaerly</key> + <string>yearly</string> + <key>yaers</key> + <string>years</string> + <key>yatch</key> + <string>yacht</string> + <key>yearm</key> + <string>year</string> + <key>yeasr</key> + <string>years</string> + <key>yeild</key> + <string>yield</string> + <key>yeilding</key> + <string>yielding</string> + <key>yera</key> + <string>year</string> + <key>yeras</key> + <string>years</string> + <key>yersa</key> + <string>years</string> + <key>yotube</key> + <string>YouTube</string> + <key>youre</key> + <string>you're</string> + <key>youseff</key> + <string>yousef</string> + <key>youself</key> + <string>yourself</string> + <key>ytou</key> + <string>you</string> + <key>yuo</key> + <string>you</string> + <key>zeebra</key> + <string>zebra</string> + </map> + </map> + </array> +</llsd> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 1928e53699..5e50bd6e01 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -335,6 +335,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>AutoReplace</key> + <map> + <key>Comment</key> + <string>Replaces keywords with a configured word or phrase</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>AutoAcceptNewInventory</key> <map> <key>Comment</key> @@ -4293,6 +4304,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>InventoryInboxToggleState</key> + <map> + <key>Comment</key> + <string>Stores the open/closed state of inventory Received items panel</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>InventoryLinking</key> <map> <key>Comment</key> @@ -6356,17 +6378,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>NumpadControl</key> - <map> - <key>Comment</key> - <string>How numpad keys control your avatar. 0 = Like the normal arrow keys, 1 = Numpad moves avatar when numlock is off, 2 = Numpad moves avatar regardless of numlock (use this if you have no numlock)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>0</integer> - </map> <key>ObjectCacheEnabled</key> <map> <key>Comment</key> @@ -10887,7 +10898,8 @@ <string>F32</string> <key>Value</key> <real>0.1</real> - </map> <key>ToolTipFadeTime</key> + </map> + <key>ToolTipFadeTime</key> <map> <key>Comment</key> <string>Seconds over which tooltip fades away</string> @@ -12295,6 +12307,28 @@ <key>Value</key> <real>10.0</real> </map> + <key>SpellCheck</key> + <map> + <key>Comment</key> + <string>Enable spellchecking on line and text editors</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>SpellCheckDictionary</key> + <map> + <key>Comment</key> + <string>Current primary and secondary dictionaries used for spell checking</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>English (United States),Second Life Glossary</string> + </map> <key>UseNewWalkRun</key> <map> <key>Comment</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3367604753..a6776d4c8d 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -81,6 +81,7 @@ #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" +#include "llviewerregion.h" #include "llviewerstats.h" #include "llviewerwindow.h" #include "llvoavatarself.h" @@ -112,6 +113,105 @@ const F32 MAX_FIDGET_TIME = 20.f; // seconds // The agent instance. LLAgent gAgent; +class LLTeleportRequest +{ +public: + enum EStatus + { + kPending, + kStarted, + kFailed, + kRestartPending + }; + + LLTeleportRequest(); + virtual ~LLTeleportRequest(); + + EStatus getStatus() const {return mStatus;}; + void setStatus(EStatus pStatus) {mStatus = pStatus;}; + + virtual bool canRestartTeleport(); + + virtual void startTeleport() = 0; + virtual void restartTeleport(); + +protected: + +private: + EStatus mStatus; +}; + +class LLTeleportRequestViaLandmark : public LLTeleportRequest +{ +public: + LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId); + virtual ~LLTeleportRequestViaLandmark(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + virtual void restartTeleport(); + +protected: + inline const LLUUID &getLandmarkId() const {return mLandmarkId;}; + +private: + LLUUID mLandmarkId; +}; + +class LLTeleportRequestViaLure : public LLTeleportRequestViaLandmark +{ +public: + LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike); + virtual ~LLTeleportRequestViaLure(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + +protected: + inline BOOL isLureGodLike() const {return mIsLureGodLike;}; + +private: + BOOL mIsLureGodLike; +}; + +class LLTeleportRequestViaLocation : public LLTeleportRequest +{ +public: + LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal); + virtual ~LLTeleportRequestViaLocation(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + virtual void restartTeleport(); + +protected: + inline const LLVector3d &getPosGlobal() const {return mPosGlobal;}; + +private: + LLVector3d mPosGlobal; +}; + + +class LLTeleportRequestViaLocationLookAt : public LLTeleportRequestViaLocation +{ +public: + LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal); + virtual ~LLTeleportRequestViaLocationLookAt(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + virtual void restartTeleport(); + +protected: + +private: + +}; + //-------------------------------------------------------------------- // Statics // @@ -245,6 +345,17 @@ LLAgent::LLAgent() : mAgentAccess(new LLAgentAccess(gSavedSettings)), mCanEditParcel(false), mTeleportSourceSLURL(new LLSLURL), + mTeleportRequest(), + mTeleportFinishedSlot(), + mTeleportFailedSlot(), + mIsMaturityRatingChangingDuringTeleport(false), + mMaturityRatingChange(0U), + mIsDoSendMaturityPreferenceToServer(false), + mMaturityPreferenceRequestId(0U), + mMaturityPreferenceResponseId(0U), + mMaturityPreferenceNumRetries(0U), + mLastKnownRequestMaturity(SIM_ACCESS_MIN), + mLastKnownResponseMaturity(SIM_ACCESS_MIN), mTeleportState( TELEPORT_NONE ), mRegionp(NULL), @@ -330,9 +441,21 @@ void LLAgent::init() gSavedSettings.getControl("PreferredMaturity")->getValidateSignal()->connect(boost::bind(&LLAgent::validateMaturity, this, _2)); gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLAgent::handleMaturity, this, _2)); + mLastKnownResponseMaturity = static_cast<U8>(gSavedSettings.getU32("PreferredMaturity")); + mLastKnownRequestMaturity = mLastKnownResponseMaturity; + mIsDoSendMaturityPreferenceToServer = true; LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLAgent::parcelChangedCallback)); + if (!mTeleportFinishedSlot.connected()) + { + mTeleportFinishedSlot = LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback(boost::bind(&LLAgent::handleTeleportFinished, this)); + } + if (!mTeleportFailedSlot.connected()) + { + mTeleportFailedSlot = LLViewerParcelMgr::getInstance()->setTeleportFailedCallback(boost::bind(&LLAgent::handleTeleportFailed, this)); + } + mInitialized = TRUE; } @@ -342,6 +465,14 @@ void LLAgent::init() void LLAgent::cleanup() { mRegionp = NULL; + if (mTeleportFinishedSlot.connected()) + { + mTeleportFinishedSlot.disconnect(); + } + if (mTeleportFailedSlot.connected()) + { + mTeleportFailedSlot.disconnect(); + } } //----------------------------------------------------------------------------- @@ -2371,49 +2502,278 @@ bool LLAgent::isAdult() const return mAgentAccess->isAdult(); } -void LLAgent::setTeen(bool teen) -{ - mAgentAccess->setTeen(teen); -} - //static int LLAgent::convertTextToMaturity(char text) { return LLAgentAccess::convertTextToMaturity(text); } -bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity) +class LLMaturityPreferencesResponder : public LLHTTPClient::Responder { - if (!getRegion()) - return false; +public: + LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity); + virtual ~LLMaturityPreferencesResponder(); + + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string& pReason); + +protected: + +private: + U8 parseMaturityFromServerResponse(const LLSD &pContent); + + LLAgent *mAgent; + U8 mPreferredMaturity; + U8 mPreviousMaturity; +}; + +LLMaturityPreferencesResponder::LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity) + : LLHTTPClient::Responder(), + mAgent(pAgent), + mPreferredMaturity(pPreferredMaturity), + mPreviousMaturity(pPreviousMaturity) +{ +} + +LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder() +{ +} + +void LLMaturityPreferencesResponder::result(const LLSD &pContent) +{ + U8 actualMaturity = parseMaturityFromServerResponse(pContent); + + if (actualMaturity != mPreferredMaturity) + { + llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', the server responded with '" + << LLViewerRegion::accessToString(actualMaturity) << "' [value:" << static_cast<U32>(actualMaturity) << ", llsd:" + << pContent << "]" << llendl; + } + mAgent->handlePreferredMaturityResult(actualMaturity); +} + +void LLMaturityPreferencesResponder::error(U32 pStatus, const std::string& pReason) +{ + llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', we got an error because '" + << pReason << "' [status:" << pStatus << "]" << llendl; + mAgent->handlePreferredMaturityError(); +} + +U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) +{ + // stinson 05/24/2012 Pathfinding regions have re-defined the response behavior. In the old server code, + // if you attempted to change the preferred maturity to the same value, the response content would be an + // undefined LLSD block. In the new server code with pathfinding, the response content should always be + // defined. Thus, the check for isUndefined() can be replaced with an assert after pathfinding is merged + // into server trunk and fully deployed. + U8 maturity = SIM_ACCESS_MIN; + if (pContent.isUndefined()) + { + maturity = mPreferredMaturity; + } + else + { + llassert(!pContent.isUndefined()); + llassert(pContent.isMap()); - // Update agent access preference on the server - std::string url = getRegion()->getCapability("UpdateAgentInformation"); - if (!url.empty()) + if (!pContent.isUndefined() && pContent.isMap()) + { + // stinson 05/24/2012 Pathfinding regions have re-defined the response syntax. The if statement catches + // the new syntax, and the else statement catches the old syntax. After pathfinding is merged into + // server trunk and fully deployed, we can remove the else statement. + if (pContent.has("access_prefs")) + { + llassert(pContent.has("access_prefs")); + llassert(pContent.get("access_prefs").isMap()); + llassert(pContent.get("access_prefs").has("max")); + llassert(pContent.get("access_prefs").get("max").isString()); + if (pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max") && + pContent.get("access_prefs").get("max").isString()) + { + LLSD::String actualPreference = pContent.get("access_prefs").get("max").asString(); + LLStringUtil::trim(actualPreference); + maturity = LLViewerRegion::shortStringToAccess(actualPreference); + } + } + else if (pContent.has("max")) + { + llassert(pContent.get("max").isString()); + if (pContent.get("max").isString()) + { + LLSD::String actualPreference = pContent.get("max").asString(); + LLStringUtil::trim(actualPreference); + maturity = LLViewerRegion::shortStringToAccess(actualPreference); + } + } + } + } + + return maturity; +} + +void LLAgent::handlePreferredMaturityResult(U8 pServerMaturity) +{ + // Update the number of responses received + ++mMaturityPreferenceResponseId; + llassert(mMaturityPreferenceResponseId <= mMaturityPreferenceRequestId); + + // Update the last known server maturity response + mLastKnownResponseMaturity = pServerMaturity; + + // Ignore all responses if we know there are more unanswered requests that are expected + if (mMaturityPreferenceResponseId == mMaturityPreferenceRequestId) { - // Set new access preference - LLSD access_prefs = LLSD::emptyMap(); - if (preferredMaturity == SIM_ACCESS_PG) + // If we received a response that matches the last known request, then we are good + if (mLastKnownRequestMaturity == mLastKnownResponseMaturity) { - access_prefs["max"] = "PG"; + mMaturityPreferenceNumRetries = 0; + reportPreferredMaturitySuccess(); + llassert(static_cast<U8>(gSavedSettings.getU32("PreferredMaturity")) == mLastKnownResponseMaturity); } - else if (preferredMaturity == SIM_ACCESS_MATURE) + // Else, the viewer is out of sync with the server, so let's try to re-sync with the + // server by re-sending our last known request. Cap the re-tries at 3 just to be safe. + else if (++mMaturityPreferenceNumRetries <= 3) { - access_prefs["max"] = "M"; + llinfos << "Retrying attempt #" << mMaturityPreferenceNumRetries << " to set viewer preferred maturity to '" + << LLViewerRegion::accessToString(mLastKnownRequestMaturity) << "'" << llendl; + sendMaturityPreferenceToServer(mLastKnownRequestMaturity); } - if (preferredMaturity == SIM_ACCESS_ADULT) + // Else, the viewer is style out of sync with the server after 3 retries, so inform the user + else { - access_prefs["max"] = "A"; + mMaturityPreferenceNumRetries = 0; + reportPreferredMaturityError(); + } + } +} + +void LLAgent::handlePreferredMaturityError() +{ + // Update the number of responses received + ++mMaturityPreferenceResponseId; + llassert(mMaturityPreferenceResponseId <= mMaturityPreferenceRequestId); + + // Ignore all responses if we know there are more unanswered requests that are expected + if (mMaturityPreferenceResponseId == mMaturityPreferenceRequestId) + { + mMaturityPreferenceNumRetries = 0; + + // If we received a response that matches the last known request, then we are synced with + // the server, but not quite sure why we are + if (mLastKnownRequestMaturity == mLastKnownResponseMaturity) + { + llwarns << "Got an error but maturity preference '" << LLViewerRegion::accessToString(mLastKnownRequestMaturity) + << "' seems to be in sync with the server" << llendl; + reportPreferredMaturitySuccess(); + } + // Else, the more likely case is that the last request does not match the last response, + // so inform the user + else + { + reportPreferredMaturityError(); + } + } +} + +void LLAgent::reportPreferredMaturitySuccess() +{ + // If there is a pending teleport request waiting for the maturity preference to be synced with + // the server, let's start the pending request + if (hasPendingTeleportRequest()) + { + startTeleportRequest(); + } +} + +void LLAgent::reportPreferredMaturityError() +{ + // If there is a pending teleport request waiting for the maturity preference to be synced with + // the server, we were unable to successfully sync with the server on maturity preference, so let's + // just raise the screen. + mIsMaturityRatingChangingDuringTeleport = false; + if (hasPendingTeleportRequest()) + { + setTeleportState(LLAgent::TELEPORT_NONE); + } + + // Get the last known maturity request from the user activity + std::string preferredMaturity = LLViewerRegion::accessToString(mLastKnownRequestMaturity); + LLStringUtil::toLower(preferredMaturity); + + // Get the last known maturity response from the server + std::string actualMaturity = LLViewerRegion::accessToString(mLastKnownResponseMaturity); + LLStringUtil::toLower(actualMaturity); + + // Notify the user + LLSD args = LLSD::emptyMap(); + args["PREFERRED_MATURITY"] = preferredMaturity; + args["ACTUAL_MATURITY"] = actualMaturity; + LLNotificationsUtil::add("MaturityChangeError", args); + + // Check the saved settings to ensure that we are consistent. If we are not consistent, update + // the viewer, but do not send anything to server + U8 localMaturity = static_cast<U8>(gSavedSettings.getU32("PreferredMaturity")); + if (localMaturity != mLastKnownResponseMaturity) + { + bool tmpIsDoSendMaturityPreferenceToServer = mIsDoSendMaturityPreferenceToServer; + mIsDoSendMaturityPreferenceToServer = false; + llinfos << "Setting viewer preferred maturity to '" << LLViewerRegion::accessToString(mLastKnownResponseMaturity) << "'" << llendl; + gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(mLastKnownResponseMaturity)); + mIsDoSendMaturityPreferenceToServer = tmpIsDoSendMaturityPreferenceToServer; + } +} + +bool LLAgent::isMaturityPreferenceSyncedWithServer() const +{ + return (mMaturityPreferenceRequestId == mMaturityPreferenceResponseId); +} + +void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) +{ + // Only send maturity preference to the server if enabled + if (mIsDoSendMaturityPreferenceToServer) + { + // Increment the number of requests. The handlers manage a separate count of responses. + ++mMaturityPreferenceRequestId; + + // Update the last know maturity request + mLastKnownRequestMaturity = pPreferredMaturity; + + // Create a response handler + LLHTTPClient::ResponderPtr responderPtr = LLHTTPClient::ResponderPtr(new LLMaturityPreferencesResponder(this, pPreferredMaturity, mLastKnownResponseMaturity)); + + // If we don't have a region, report it as an error + if (getRegion() == NULL) + { + responderPtr->error(0U, "region is not defined"); + } + else + { + // Find the capability to send maturity preference + std::string url = getRegion()->getCapability("UpdateAgentInformation"); + + // If the capability is not defined, report it as an error + if (url.empty()) + { + responderPtr->error(0U, "capability 'UpdateAgentInformation' is not defined for region"); + } + else + { + // Set new access preference + LLSD access_prefs = LLSD::emptyMap(); + access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity); + + LLSD body = LLSD::emptyMap(); + body["access_prefs"] = access_prefs; + llinfos << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) + << "' via capability to: " << url << llendl; + LLSD headers; + LLHTTPClient::post(url, body, responderPtr, headers, 30.0f); + } } - - LLSD body = LLSD::emptyMap(); - body["access_prefs"] = access_prefs; - llinfos << "Sending access prefs update to " << (access_prefs["max"].asString()) << " via capability to: " - << url << llendl; - LLHTTPClient::post(url, body, new LLHTTPClient::Responder()); // Ignore response - return true; } - return false; } BOOL LLAgent::getAdminOverride() const @@ -2436,11 +2796,6 @@ void LLAgent::setGodLevel(U8 god_level) mAgentAccess->setGodLevel(god_level); } -void LLAgent::setAOTransition() -{ - mAgentAccess->setTransition(); -} - const LLAgentAccess& LLAgent::getAgentAccess() { return *mAgentAccess; @@ -2451,9 +2806,9 @@ bool LLAgent::validateMaturity(const LLSD& newvalue) return mAgentAccess->canSetMaturity(newvalue.asInteger()); } -void LLAgent::handleMaturity(const LLSD& newvalue) +void LLAgent::handleMaturity(const LLSD &pNewValue) { - sendMaturityPreferenceToServer(newvalue.asInteger()); + sendMaturityPreferenceToServer(static_cast<U8>(pNewValue.asInteger())); } //---------------------------------------------------------------------------- @@ -3388,7 +3743,7 @@ void LLAgent::clearVisualParams(void *data) // protected bool LLAgent::teleportCore(bool is_local) { - if(TELEPORT_NONE != mTeleportState) + if ((TELEPORT_NONE != mTeleportState) && (mTeleportState != TELEPORT_PENDING)) { llwarns << "Attempt to teleport when already teleporting." << llendl; return false; @@ -3466,6 +3821,102 @@ bool LLAgent::teleportCore(bool is_local) return true; } +bool LLAgent::hasRestartableFailedTeleportRequest() +{ + return ((mTeleportRequest != NULL) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed) && + mTeleportRequest->canRestartTeleport()); +} + +void LLAgent::restartFailedTeleportRequest() +{ + if (hasRestartableFailedTeleportRequest()) + { + mTeleportRequest->setStatus(LLTeleportRequest::kRestartPending); + startTeleportRequest(); + } +} + +void LLAgent::clearTeleportRequest() +{ + mTeleportRequest.reset(); +} + +void LLAgent::setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange) +{ + mIsMaturityRatingChangingDuringTeleport = true; + mMaturityRatingChange = pMaturityRatingChange; +} + +bool LLAgent::hasPendingTeleportRequest() +{ + return ((mTeleportRequest != NULL) && + ((mTeleportRequest->getStatus() == LLTeleportRequest::kPending) || + (mTeleportRequest->getStatus() == LLTeleportRequest::kRestartPending))); +} + +void LLAgent::startTeleportRequest() +{ + if (hasPendingTeleportRequest()) + { + if (!isMaturityPreferenceSyncedWithServer()) + { + gTeleportDisplay = TRUE; + setTeleportState(TELEPORT_PENDING); + } + else + { + switch (mTeleportRequest->getStatus()) + { + case LLTeleportRequest::kPending : + mTeleportRequest->setStatus(LLTeleportRequest::kStarted); + mTeleportRequest->startTeleport(); + break; + case LLTeleportRequest::kRestartPending : + llassert(mTeleportRequest->canRestartTeleport()); + mTeleportRequest->setStatus(LLTeleportRequest::kStarted); + mTeleportRequest->restartTeleport(); + break; + default : + llassert(0); + break; + } + } + } +} + +void LLAgent::handleTeleportFinished() +{ + clearTeleportRequest(); + if (mIsMaturityRatingChangingDuringTeleport) + { + // notify user that the maturity preference has been changed + std::string maturityRating = LLViewerRegion::accessToString(mMaturityRatingChange); + LLStringUtil::toLower(maturityRating); + LLSD args; + args["RATING"] = maturityRating; + LLNotificationsUtil::add("PreferredMaturityChanged", args); + mIsMaturityRatingChangingDuringTeleport = false; + } +} + +void LLAgent::handleTeleportFailed() +{ + if (mTeleportRequest != NULL) + { + mTeleportRequest->setStatus(LLTeleportRequest::kFailed); + } + if (mIsMaturityRatingChangingDuringTeleport) + { + // notify user that the maturity preference has been changed + std::string maturityRating = LLViewerRegion::accessToString(mMaturityRatingChange); + LLStringUtil::toLower(maturityRating); + LLSD args; + args["RATING"] = maturityRating; + LLNotificationsUtil::add("PreferredMaturityChanged", args); + mIsMaturityRatingChangingDuringTeleport = false; + } +} + void LLAgent::teleportRequest( const U64& region_handle, const LLVector3& pos_local, @@ -3498,6 +3949,12 @@ void LLAgent::teleportRequest( // Landmark ID = LLUUID::null means teleport home void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) { + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLandmark(landmark_asset_id)); + startTeleportRequest(); +} + +void LLAgent::doTeleportViaLandmark(const LLUUID& landmark_asset_id) +{ LLViewerRegion *regionp = getRegion(); if(regionp && teleportCore()) { @@ -3513,6 +3970,12 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike) { + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLure(lure_id, godlike)); + startTeleportRequest(); +} + +void LLAgent::doTeleportViaLure(const LLUUID& lure_id, BOOL godlike) +{ LLViewerRegion* regionp = getRegion(); if(regionp && teleportCore()) { @@ -3544,24 +4007,33 @@ void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike) // James Cook, July 28, 2005 void LLAgent::teleportCancel() { - LLViewerRegion* regionp = getRegion(); - if(regionp) + if (!hasPendingTeleportRequest()) { - // send the message - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("TeleportCancel"); - msg->nextBlockFast(_PREHASH_Info); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - sendReliableMessage(); - } - gTeleportDisplay = FALSE; + LLViewerRegion* regionp = getRegion(); + if(regionp) + { + // send the message + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("TeleportCancel"); + msg->nextBlockFast(_PREHASH_Info); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + sendReliableMessage(); + } + } + clearTeleportRequest(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } void LLAgent::teleportViaLocation(const LLVector3d& pos_global) { + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocation(pos_global)); + startTeleportRequest(); +} + +void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global) +{ LLViewerRegion* regionp = getRegion(); U64 handle = to_region_handle(pos_global); LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); @@ -3604,6 +4076,12 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) // Teleport to global position, but keep facing in the same direction void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) { + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocationLookAt(pos_global)); + startTeleportRequest(); +} + +void LLAgent::doTeleportViaLocationLookAt(const LLVector3d& pos_global) +{ mbTeleportKeepsLookAt = true; gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction U64 region_handle = to_region_handle(pos_global); @@ -4045,5 +4523,149 @@ LLAgentQueryManager::~LLAgentQueryManager() { } -// EOF +//----------------------------------------------------------------------------- +// LLTeleportRequest +//----------------------------------------------------------------------------- + +LLTeleportRequest::LLTeleportRequest() + : mStatus(kPending) +{ +} + +LLTeleportRequest::~LLTeleportRequest() +{ +} +bool LLTeleportRequest::canRestartTeleport() +{ + return false; +} + +void LLTeleportRequest::restartTeleport() +{ + llassert(0); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLandmark +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLandmark::LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId) + : LLTeleportRequest(), + mLandmarkId(pLandmarkId) +{ +} + +LLTeleportRequestViaLandmark::~LLTeleportRequestViaLandmark() +{ +} + +bool LLTeleportRequestViaLandmark::canRestartTeleport() +{ + return true; +} + +void LLTeleportRequestViaLandmark::startTeleport() +{ + gAgent.doTeleportViaLandmark(getLandmarkId()); +} + +void LLTeleportRequestViaLandmark::restartTeleport() +{ + gAgent.doTeleportViaLandmark(getLandmarkId()); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLure +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLure::LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike) + : LLTeleportRequestViaLandmark(pLureId), + mIsLureGodLike(pIsLureGodLike) +{ +} + +LLTeleportRequestViaLure::~LLTeleportRequestViaLure() +{ +} + +bool LLTeleportRequestViaLure::canRestartTeleport() +{ + // stinson 05/17/2012 : cannot restart a teleport via lure because of server-side restrictions + // The current scenario is as follows: + // 1. User A initializes a request for User B to teleport via lure + // 2. User B accepts the teleport via lure request + // 3. The server sees the init request from User A and the accept request from User B and matches them up + // 4. The server then removes the paired requests up from the "queue" + // 5. The server then fails User B's teleport for reason of maturity level (for example) + // 6. User B's viewer prompts user to increase their maturity level profile value. + // 7. User B confirms and accepts increase in maturity level + // 8. User B's viewer then attempts to teleport via lure again + // 9. This request will time-out on the viewer-side because User A's initial request has been removed from the "queue" in step 4 + + return false; +} + +void LLTeleportRequestViaLure::startTeleport() +{ + gAgent.doTeleportViaLure(getLandmarkId(), isLureGodLike()); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLocation +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLocation::LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal) + : LLTeleportRequest(), + mPosGlobal(pPosGlobal) +{ +} + +LLTeleportRequestViaLocation::~LLTeleportRequestViaLocation() +{ +} + +bool LLTeleportRequestViaLocation::canRestartTeleport() +{ + return true; +} + +void LLTeleportRequestViaLocation::startTeleport() +{ + gAgent.doTeleportViaLocation(getPosGlobal()); +} + +void LLTeleportRequestViaLocation::restartTeleport() +{ + gAgent.doTeleportViaLocation(getPosGlobal()); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLocationLookAt +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLocationLookAt::LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal) + : LLTeleportRequestViaLocation(pPosGlobal) +{ +} + +LLTeleportRequestViaLocationLookAt::~LLTeleportRequestViaLocationLookAt() +{ +} + +bool LLTeleportRequestViaLocationLookAt::canRestartTeleport() +{ + return true; +} + +void LLTeleportRequestViaLocationLookAt::startTeleport() +{ + gAgent.doTeleportViaLocationLookAt(getPosGlobal()); +} + +void LLTeleportRequestViaLocationLookAt::restartTeleport() +{ + gAgent.doTeleportViaLocationLookAt(getPosGlobal()); +} + +// EOF diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 740770bbdf..a505d5bbae 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -35,6 +35,8 @@ #include "llcoordframe.h" // for mFrameAgent #include "llvoavatardefines.h" +#include <boost/function.hpp> +#include <boost/shared_ptr.hpp> #include <boost/signals2.hpp> extern const BOOL ANIMATE; @@ -56,6 +58,9 @@ class LLAgentAccess; class LLSLURL; class LLPauseRequestHandle; class LLUIColor; +class LLTeleportRequest; + +typedef boost::shared_ptr<LLTeleportRequest> LLTeleportRequestPtr; //-------------------------------------------------------------------- // Types @@ -539,7 +544,8 @@ public: TELEPORT_MOVING = 3, // Viewer has received destination location from source simulator TELEPORT_START_ARRIVAL = 4, // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator TELEPORT_ARRIVING = 5, // Make the user wait while content "pre-caches" - TELEPORT_LOCAL = 6 // Teleporting in-sim without showing the progress screen + TELEPORT_LOCAL = 6, // Teleporting in-sim without showing the progress screen + TELEPORT_PENDING = 7 }; public: @@ -556,9 +562,6 @@ private: // Teleport Actions //-------------------------------------------------------------------- public: - void teleportRequest(const U64& region_handle, - const LLVector3& pos_local, // Go to a named location home - bool look_at_from_camera = false); void teleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark void teleportHome() { teleportViaLandmark(LLUUID::null); } // Go home void teleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location @@ -572,6 +575,44 @@ protected: //-------------------------------------------------------------------- // Teleport State //-------------------------------------------------------------------- + +public: + bool hasRestartableFailedTeleportRequest(); + void restartFailedTeleportRequest(); + void clearTeleportRequest(); + void setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange); + +private: + friend class LLTeleportRequest; + friend class LLTeleportRequestViaLandmark; + friend class LLTeleportRequestViaLure; + friend class LLTeleportRequestViaLocation; + friend class LLTeleportRequestViaLocationLookAt; + + LLTeleportRequestPtr mTeleportRequest; + boost::signals2::connection mTeleportFinishedSlot; + boost::signals2::connection mTeleportFailedSlot; + + bool mIsMaturityRatingChangingDuringTeleport; + U8 mMaturityRatingChange; + + bool hasPendingTeleportRequest(); + void startTeleportRequest(); + + void teleportRequest(const U64& region_handle, + const LLVector3& pos_local, // Go to a named location home + bool look_at_from_camera = false); + void doTeleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark + void doTeleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location + void doTeleportViaLocation(const LLVector3d& pos_global); // To a global location - this will probably need to be deprecated + void doTeleportViaLocationLookAt(const LLVector3d& pos_global);// To a global location, preserving camera rotation + + void handleTeleportFinished(); + void handleTeleportFailed(); + + //-------------------------------------------------------------------- + // Teleport State + //-------------------------------------------------------------------- public: ETeleportState getTeleportState() const { return mTeleportState; } void setTeleportState(ETeleportState state); @@ -614,8 +655,6 @@ public: const LLAgentAccess& getAgentAccess(); BOOL canManageEstate() const; BOOL getAdminOverride() const; - // ! BACKWARDS COMPATIBILITY ! This function can go away after the AO transition (see llstartup.cpp). - void setAOTransition(); private: LLAgentAccess * mAgentAccess; @@ -650,13 +689,28 @@ public: bool isTeen() const; bool isMature() const; bool isAdult() const; - void setTeen(bool teen); void setMaturity(char text); - static int convertTextToMaturity(char text); - bool sendMaturityPreferenceToServer(int preferredMaturity); // ! "U8" instead of "int"? + static int convertTextToMaturity(char text); + +private: + bool mIsDoSendMaturityPreferenceToServer; + unsigned int mMaturityPreferenceRequestId; + unsigned int mMaturityPreferenceResponseId; + unsigned int mMaturityPreferenceNumRetries; + U8 mLastKnownRequestMaturity; + U8 mLastKnownResponseMaturity; + + bool isMaturityPreferenceSyncedWithServer() const; + void sendMaturityPreferenceToServer(U8 pPreferredMaturity); + + friend class LLMaturityPreferencesResponder; + void handlePreferredMaturityResult(U8 pServerMaturity); + void handlePreferredMaturityError(); + void reportPreferredMaturitySuccess(); + void reportPreferredMaturityError(); // Maturity callbacks for PreferredMaturity control variable - void handleMaturity(const LLSD& newvalue); + void handleMaturity(const LLSD &pNewValue); bool validateMaturity(const LLSD& newvalue); diff --git a/indra/newview/llagentaccess.cpp b/indra/newview/llagentaccess.cpp index 08a33ab04a..c4ee321e04 100644 --- a/indra/newview/llagentaccess.cpp +++ b/indra/newview/llagentaccess.cpp @@ -33,8 +33,7 @@ LLAgentAccess::LLAgentAccess(LLControlGroup& savedSettings) : mSavedSettings(savedSettings), mAccess(SIM_ACCESS_PG), mAdminOverride(false), - mGodLevel(GOD_NOT), - mAOTransition(false) + mGodLevel(GOD_NOT) { } @@ -133,18 +132,6 @@ bool LLAgentAccess::isAdult() const return mAccess >= SIM_ACCESS_ADULT; } -void LLAgentAccess::setTeen(bool teen) -{ - if (teen) - { - mAccess = SIM_ACCESS_PG; - } - else - { - mAccess = SIM_ACCESS_MATURE; - } -} - //static int LLAgentAccess::convertTextToMaturity(char text) { @@ -182,16 +169,6 @@ void LLAgentAccess::setMaturity(char text) mSavedSettings.setU32("PreferredMaturity", preferred_access); } -void LLAgentAccess::setTransition() -{ - mAOTransition = true; -} - -bool LLAgentAccess::isInTransition() const -{ - return mAOTransition; -} - bool LLAgentAccess::canSetMaturity(S32 maturity) { if (isGodlike()) // Gods can always set their Maturity level diff --git a/indra/newview/llagentaccess.h b/indra/newview/llagentaccess.h index 2e98e4eea1..4e851b0aa0 100644 --- a/indra/newview/llagentaccess.h +++ b/indra/newview/llagentaccess.h @@ -59,13 +59,10 @@ public: bool isMature() const; bool isAdult() const; - void setTeen(bool teen); void setMaturity(char text); static int convertTextToMaturity(char text); - void setTransition(); // sets the transition bit, which defaults to false - bool isInTransition() const; bool canSetMaturity(S32 maturity); private: @@ -73,13 +70,6 @@ private: U8 mGodLevel; bool mAdminOverride; - // this should be deleted after the 60-day AO transition. - // It should be safe to remove it in Viewer 2009 - // It's set by a special short-term flag in login.cgi - // called ao_transition. When that's gone, this can go, along with - // all of the code that depends on it. - bool mAOTransition; - LLControlGroup& mSavedSettings; }; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index faadfb4b87..6d67e098a6 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -229,12 +229,13 @@ LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() { - LL_INFOS("Avatar") << self_av_string() << "done update appearance on destroy" << LL_ENDL; - - selfStopPhase("update_appearance_on_destroy"); - if (!LLApp::isExiting()) { + // speculative fix for MAINT-1150 + LL_INFOS("Avatar") << self_av_string() << "done update appearance on destroy" << LL_ENDL; + + selfStopPhase("update_appearance_on_destroy"); + LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder); } } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 062551a3e8..024c25538c 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -95,6 +95,7 @@ #include "llupdaterservice.h" #include "llcallfloater.h" #include "llfloatertexturefetchdebugger.h" +#include "llspellcheck.h" // Linden library includes #include "llavatarnamecache.h" @@ -118,6 +119,7 @@ // Third party library includes #include <boost/bind.hpp> #include <boost/foreach.hpp> +#include <boost/algorithm/string.hpp> @@ -626,6 +628,7 @@ LLAppViewer::LLAppViewer() : mPurgeOnExit(false), mSecondInstance(false), mSavedFinalSnapshot(false), + mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded. mForceGraphicsDetail(false), mQuitRequested(false), mLogoutRequestSent(false), @@ -1803,6 +1806,13 @@ bool LLAppViewer::cleanup() { llinfos << "Not saving per-account settings; don't know the account name yet." << llendl; } + // Only save per account settings if the previous login succeeded, otherwise + // we might end up with a cleared out settings file in case a previous login + // failed after loading per account settings. + else if (!mSavePerAccountSettings) + { + llinfos << "Not saving per-account settings; last login was not successful." << llendl; + } else { gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); @@ -2557,6 +2567,19 @@ bool LLAppViewer::initConfiguration() //gDirUtilp->setSkinFolder("default"); } + if (gSavedSettings.getBOOL("SpellCheck")) + { + std::list<std::string> dict_list; + std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary"); + boost::split(dict_list, dict_setting, boost::is_any_of(std::string(","))); + if (!dict_list.empty()) + { + LLSpellChecker::setUseSpellCheck(dict_list.front()); + dict_list.pop_front(); + LLSpellChecker::instance().setSecondaryDictionaries(dict_list); + } + } + mYieldTime = gSavedSettings.getS32("YieldTime"); // Read skin/branding settings if specified. @@ -5016,6 +5039,10 @@ void LLAppViewer::handleLoginComplete() mOnLoginCompleted(); writeDebugInfo(); + + // we logged in successfully, so save settings on logout + llinfos << "Login successful, per account settings will be saved on log out." << llendl; + mSavePerAccountSettings=true; } void LLAppViewer::launchUpdater() diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index f7d019ccba..ae3c795d1e 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -247,6 +247,7 @@ private: bool mPurgeOnExit; bool mSavedFinalSnapshot; + bool mSavePerAccountSettings; // only save per account settings if login succeeded bool mForceGraphicsDetail; diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index bad60a9757..53c77fa22e 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -130,6 +130,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, // This results in a 2-3x improvement in opening a new Inventory window (which uses a large numebr of allocations) // Note: This won't work when running from the debugger unless the _NO_DEBUG_HEAP environment variable is set to 1 + // Enable to get mem debugging within visual studio. + //_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); _CrtSetDbgFlag(0); // default, just making explicit ULONG ulEnableLFH = 2; diff --git a/indra/newview/llautoreplace.cpp b/indra/newview/llautoreplace.cpp new file mode 100644 index 0000000000..0f1ce2bcd0 --- /dev/null +++ b/indra/newview/llautoreplace.cpp @@ -0,0 +1,771 @@ +/** + * @file llautoreplace.cpp + * @brief Auto Replace Manager + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llautoreplace.h" +#include "llsdserialize.h" +#include "llboost.h" +#include "llcontrol.h" +#include "llviewercontrol.h" +#include "llnotificationsutil.h" + +LLAutoReplace* LLAutoReplace::sInstance; + +const char* LLAutoReplace::SETTINGS_FILE_NAME = "autoreplace.xml"; + +LLAutoReplace::LLAutoReplace() +{ +} + +LLAutoReplace::~LLAutoReplace() +{ + sInstance = NULL; +} + +void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) +{ + static LLCachedControl<bool> perform_autoreplace(gSavedSettings, "AutoReplace"); + if(perform_autoreplace) + { + S32 wordEnd = cursorPos-1; + LLWString text = inputText.getWString(); + + bool atSpace = (text[wordEnd] == ' '); + bool haveWord = (LLWStringUtil::isPartOfWord(text[wordEnd])); + + if (atSpace || haveWord) + { + if (atSpace && wordEnd > 0) + { + // find out if this space immediately follows a word + wordEnd--; + haveWord = (LLWStringUtil::isPartOfWord(text[wordEnd])); + } + if (haveWord) + { + // wordEnd points to the end of a word, now find the start of the word + std::string word; + S32 wordStart = wordEnd; + for ( S32 backOne = wordStart - 1; + backOne >= 0 && LLWStringUtil::isPartOfWord(text[backOne]); + backOne-- + ) + { + wordStart--; // walk wordStart back to the beginning of the word + } + LL_DEBUGS("AutoReplace")<<"wordStart: "<<wordStart<<" wordEnd: "<<wordEnd<<LL_ENDL; + std::string strText = std::string(text.begin(), text.end()); + std::string lastWord = strText.substr(wordStart, wordEnd-wordStart+1); + std::string replacementWord( mSettings.replaceWord( lastWord ) ); + + if ( replacementWord != lastWord ) + { + // The last word is one for which we have a replacement + if (atSpace) + { + // replace the last word in the input + LLWString strNew = utf8str_to_wstring(replacementWord); + LLWString strOld = utf8str_to_wstring(lastWord); + int size_change = strNew.size() - strOld.size(); + + text.replace(wordStart,lastWord.length(),strNew); + inputText = wstring_to_utf8str(text); + cursorPos+=size_change; + } + } + } + } + } +} + +LLAutoReplace* LLAutoReplace::getInstance() +{ + if(!sInstance) + { + sInstance = new LLAutoReplace(); + sInstance->loadFromSettings(); + } + return sInstance; +} + +std::string LLAutoReplace::getUserSettingsFileName() +{ + std::string path=gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); + + if (!path.empty()) + { + path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, SETTINGS_FILE_NAME); + } + return path; +} + +std::string LLAutoReplace::getAppSettingsFileName() +{ + std::string path=gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""); + + if (!path.empty()) + { + path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, SETTINGS_FILE_NAME); + } + else + { + LL_ERRS("AutoReplace") << "Failed to get app settings directory name" << LL_ENDL; + } + return path; +} + +LLAutoReplaceSettings LLAutoReplace::getSettings() +{ + return mSettings; +} + +void LLAutoReplace::setSettings(const LLAutoReplaceSettings& newSettings) +{ + mSettings.set(newSettings); + /// Make the newSettings active and write them to user storage + saveToUserSettings(); +} + +void LLAutoReplace::loadFromSettings() +{ + std::string filename=getUserSettingsFileName(); + if (filename.empty()) + { + LL_INFOS("AutoReplace") << "no valid user settings directory." << LL_ENDL; + } + if(gDirUtilp->fileExists(filename)) + { + LLSD userSettings; + llifstream file; + file.open(filename.c_str()); + if (file.is_open()) + { + LLSDSerialize::fromXML(userSettings, file); + } + file.close(); + if ( mSettings.setFromLLSD(userSettings) ) + { + LL_INFOS("AutoReplace") << "settings loaded from '" << filename << "'" << LL_ENDL; + } + else + { + LL_WARNS("AutoReplace") << "invalid settings found in '" << filename << "'" << LL_ENDL; + } + } + else // no user settings found, try application settings + { + std::string defaultName = getAppSettingsFileName(); + LL_INFOS("AutoReplace") << " user settings file '" << filename << "' not found"<< LL_ENDL; + + bool gotSettings = false; + if(gDirUtilp->fileExists(defaultName)) + { + LLSD appDefault; + llifstream file; + file.open(defaultName.c_str()); + if (file.is_open()) + { + LLSDSerialize::fromXMLDocument(appDefault, file); + } + file.close(); + + if ( mSettings.setFromLLSD(appDefault) ) + { + LL_INFOS("AutoReplace") << "settings loaded from '" << defaultName.c_str() << "'" << LL_ENDL; + gotSettings = true; + } + else + { + LL_WARNS("AutoReplace") << "invalid settings found in '" << defaultName.c_str() << "'" << LL_ENDL; + } + } + + if ( ! gotSettings ) + { + if (mSettings.setFromLLSD(mSettings.getExampleLLSD())) + { + LL_WARNS("AutoReplace") << "no settings found; loaded example." << LL_ENDL; + } + else + { + LL_WARNS("AutoReplace") << "no settings found and example invalid!" << LL_ENDL; + } + } + } +} + +void LLAutoReplace::saveToUserSettings() +{ + std::string filename=getUserSettingsFileName(); + llofstream file; + file.open(filename.c_str()); + LLSDSerialize::toPrettyXML(mSettings.getAsLLSD(), file); + file.close(); + LL_INFOS("AutoReplace") << "settings saved to '" << filename << "'" << LL_ENDL; +} + +// ================================================================ +// LLAutoReplaceSettings +// ================================================================ + +const std::string LLAutoReplaceSettings::AUTOREPLACE_LIST_NAME = "name"; ///< key for looking up list names +const std::string LLAutoReplaceSettings::AUTOREPLACE_LIST_REPLACEMENTS = "replacements"; ///< key for looking up replacement map + +LLAutoReplaceSettings::LLAutoReplaceSettings() +{ +} + +LLAutoReplaceSettings::LLAutoReplaceSettings(const LLAutoReplaceSettings& settings) +{ + // copy all values through fundamental type intermediates for thread safety + mLists = LLSD::emptyArray(); + + for ( LLSD::array_const_iterator list = settings.mLists.beginArray(), listEnd = settings.mLists.endArray(); + list != listEnd; + list++ + ) + { + if ( (*list).isMap() ) // can fail due to LLSD-30: ignore it + { + LLSD listMap = LLSD::emptyMap(); + std::string listName = (*list)[AUTOREPLACE_LIST_NAME]; + listMap[AUTOREPLACE_LIST_NAME] = listName; + listMap[AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); + + for ( LLSD::map_const_iterator + entry = (*list)[AUTOREPLACE_LIST_REPLACEMENTS].beginMap(), + entriesEnd = (*list)[AUTOREPLACE_LIST_REPLACEMENTS].endMap(); + entry != entriesEnd; + entry++ + ) + { + std::string keyword = entry->first; + std::string replacement = entry->second.asString(); + listMap[AUTOREPLACE_LIST_REPLACEMENTS].insert(keyword, LLSD(replacement)); + } + + mLists.append(listMap); + } + } +} + +void LLAutoReplaceSettings::set(const LLAutoReplaceSettings& newSettings) +{ + mLists = newSettings.mLists; +} + +bool LLAutoReplaceSettings::setFromLLSD(const LLSD& settingsFromLLSD) +{ + bool settingsValid = true; + + if ( settingsFromLLSD.isArray() ) + { + for ( LLSD::array_const_iterator + list = settingsFromLLSD.beginArray(), + listEnd = settingsFromLLSD.endArray(); + settingsValid && list != listEnd; + list++ + ) + { + if ( (*list).isDefined() ) // can be undef due to LLSD-30: ignore it + { + settingsValid = listIsValid(*list); + } + } + } + else + { + settingsValid = false; + LL_WARNS("AutoReplace") << "settings are not an array" << LL_ENDL; + } + + if ( settingsValid ) + { + mLists = settingsFromLLSD; + } + else + { + LL_WARNS("AutoReplace") << "invalid settings discarded; using hard coded example" << LL_ENDL; + } + + return settingsValid; +} + +bool LLAutoReplaceSettings::listNameMatches( const LLSD& list, const std::string name ) +{ + return list.isMap() + && list.has(AUTOREPLACE_LIST_NAME) + && list[AUTOREPLACE_LIST_NAME].asString() == name; +} + +const LLSD* LLAutoReplaceSettings::getListEntries(std::string listName) +{ + const LLSD* returnedEntries = NULL; + for( LLSD::array_const_iterator list = mLists.beginArray(), endList = mLists.endArray(); + returnedEntries == NULL && list != endList; + list++ + ) + { + const LLSD& thisList = *list; + if ( listNameMatches(thisList, listName) ) + { + returnedEntries = &thisList[AUTOREPLACE_LIST_REPLACEMENTS]; + } + } + return returnedEntries; +} + +std::string LLAutoReplaceSettings::replacementFor(std::string keyword, std::string listName) +{ + std::string replacement; + bool foundList = false; + for( LLSD::array_const_iterator list = mLists.beginArray(), endList = mLists.endArray(); + ! foundList && list != endList; + list++ + ) + { + const LLSD& thisList = *list; + if ( listNameMatches(thisList, listName) ) + { + foundList = true; // whether there is a replacement or not, we're done + if ( thisList.isMap() + && thisList.has(AUTOREPLACE_LIST_REPLACEMENTS) + && thisList[AUTOREPLACE_LIST_REPLACEMENTS].has(keyword) + ) + { + replacement = thisList[AUTOREPLACE_LIST_REPLACEMENTS][keyword].asString(); + LL_DEBUGS("AutoReplace")<<"'"<<keyword<<"' -> '"<<replacement<<"'"<<LL_ENDL; + } + } + if (!foundList) + { + LL_WARNS("AutoReplace")<<"failed to find list '"<<listName<<"'"<<LL_ENDL; + } + } + if (replacement.empty()) + { + LL_WARNS("AutoReplace")<<"failed to find '"<<keyword<<"'"<<LL_ENDL; + } + return replacement; +} + +LLSD LLAutoReplaceSettings::getListNames() +{ + LL_DEBUGS("AutoReplace")<<"====="<<LL_ENDL; + LLSD toReturn = LLSD::emptyArray(); + S32 counter=0; + for( LLSD::array_const_iterator list = mLists.beginArray(), endList = mLists.endArray(); + list != endList; + list++ + ) + { + const LLSD& thisList = *list; + if ( thisList.isMap() ) + { + if ( thisList.has(AUTOREPLACE_LIST_NAME) ) + { + std::string name = thisList[AUTOREPLACE_LIST_NAME].asString(); + LL_DEBUGS("AutoReplace")<<counter<<" '"<<name<<"'"<<LL_ENDL; + toReturn.append(LLSD(name)); + } + else + { + LL_ERRS("AutoReplace") <<counter<<" ! MISSING "<<AUTOREPLACE_LIST_NAME<< LL_ENDL; + } + } + else + { + LL_WARNS("AutoReplace")<<counter<<" ! not a map: "<<LLSD::typeString(thisList.type())<< LL_ENDL; + } + counter++; + } + LL_DEBUGS("AutoReplace")<<"^^^^^^"<<LL_ENDL; + return toReturn; +} + +bool LLAutoReplaceSettings::listIsValid(const LLSD& list) +{ + bool listValid = true; + if ( ! list.isMap() ) + { + listValid = false; + LL_WARNS("AutoReplace") << "list is not a map" << LL_ENDL; + } + else if ( ! list.has(AUTOREPLACE_LIST_NAME) + || ! list[AUTOREPLACE_LIST_NAME].isString() + || list[AUTOREPLACE_LIST_NAME].asString().empty() + ) + { + listValid = false; + LL_WARNS("AutoReplace") + << "list found without " << AUTOREPLACE_LIST_NAME + << " (or it is empty)" + << LL_ENDL; + } + else if ( ! list.has(AUTOREPLACE_LIST_REPLACEMENTS) || ! list[AUTOREPLACE_LIST_REPLACEMENTS].isMap() ) + { + listValid = false; + LL_WARNS("AutoReplace") << "list '" << list[AUTOREPLACE_LIST_NAME].asString() << "' without " << AUTOREPLACE_LIST_REPLACEMENTS << LL_ENDL; + } + else + { + for ( LLSD::map_const_iterator + entry = list[AUTOREPLACE_LIST_REPLACEMENTS].beginMap(), + entriesEnd = list[AUTOREPLACE_LIST_REPLACEMENTS].endMap(); + listValid && entry != entriesEnd; + entry++ + ) + { + if ( ! entry->second.isString() ) + { + listValid = false; + LL_WARNS("AutoReplace") + << "non-string replacement value found in list '" + << list[AUTOREPLACE_LIST_NAME].asString() << "'" + << LL_ENDL; + } + } + } + + return listValid; +} + +const LLSD* LLAutoReplaceSettings::exportList(std::string listName) +{ + const LLSD* exportedList = NULL; + for ( LLSD::array_const_iterator list = mLists.beginArray(), listEnd = mLists.endArray(); + exportedList == NULL && list != listEnd; + list++ + ) + { + if ( listNameMatches(*list, listName) ) + { + const LLSD& namedList = (*list); + exportedList = &namedList; + } + } + return exportedList; +} + +bool LLAutoReplaceSettings::listNameIsUnique(const LLSD& newList) +{ + bool nameIsUnique = true; + // this must always be called with a valid list, so it is safe to assume it has a name + std::string newListName = newList[AUTOREPLACE_LIST_NAME].asString(); + for ( LLSD::array_const_iterator list = mLists.beginArray(), listEnd = mLists.endArray(); + nameIsUnique && list != listEnd; + list++ + ) + { + if ( listNameMatches(*list, newListName) ) + { + LL_WARNS("AutoReplace")<<"duplicate list name '"<<newListName<<"'"<<LL_ENDL; + nameIsUnique = false; + } + } + return nameIsUnique; +} + +/* static */ +void LLAutoReplaceSettings::createEmptyList(LLSD& emptyList) +{ + emptyList = LLSD::emptyMap(); + emptyList[AUTOREPLACE_LIST_NAME] = "Empty"; + emptyList[AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); +} + +/* static */ +void LLAutoReplaceSettings::setListName(LLSD& list, const std::string& newName) +{ + list[AUTOREPLACE_LIST_NAME] = newName; +} + +/* static */ +std::string LLAutoReplaceSettings::getListName(LLSD& list) +{ + std::string name; + if ( list.isMap() && list.has(AUTOREPLACE_LIST_NAME) && list[AUTOREPLACE_LIST_NAME].isString() ) + { + name = list[AUTOREPLACE_LIST_NAME].asString(); + } + return name; +} + +LLAutoReplaceSettings::AddListResult LLAutoReplaceSettings::addList(const LLSD& newList) +{ + AddListResult result; + if ( listIsValid( newList ) ) + { + if ( listNameIsUnique( newList ) ) + { + mLists.append(newList); + result = AddListOk; + } + else + { + LL_WARNS("AutoReplace") << "attempt to add duplicate name" << LL_ENDL; + result = AddListDuplicateName; + } + } + else + { + LL_WARNS("AutoReplace") << "attempt to add invalid list" << LL_ENDL; + result = AddListInvalidList; + } + return result; +} + +bool LLAutoReplaceSettings::removeReplacementList(std::string listName) +{ + bool found = false; + for( S32 index = 0; !found && mLists[index].isDefined(); index++ ) + { + if( listNameMatches(mLists.get(index), listName) ) + { + LL_DEBUGS("AutoReplace")<<"list '"<<listName<<"'"<<LL_ENDL; + mLists.erase(index); + found = true; + } + } + return found; +} + +/// Move the named list up in the priority order +bool LLAutoReplaceSettings::increaseListPriority(std::string listName) +{ + LL_DEBUGS("AutoReplace")<<listName<<LL_ENDL; + bool found = false; + S32 search_index, previous_index; + LLSD targetList; + // The following is working around the fact that LLSD arrays containing maps also seem to have undefined entries... see LLSD-30 + previous_index = -1; + for ( search_index = 0, targetList = mLists[0]; + !found && search_index < mLists.size(); + search_index += 1, targetList = mLists[search_index] + ) + { + if ( targetList.isMap() ) + { + if ( listNameMatches( targetList, listName) ) + { + LL_DEBUGS("AutoReplace")<<"found at "<<search_index<<", previous is "<<previous_index<<LL_ENDL; + found = true; + if (previous_index >= 0) + { + LL_DEBUGS("AutoReplace") << "erase "<<search_index<<LL_ENDL; + mLists.erase(search_index); + LL_DEBUGS("AutoReplace") << "insert at "<<previous_index<<LL_ENDL; + mLists.insert(previous_index, targetList); + } + else + { + LL_WARNS("AutoReplace") << "attempted to move top list up" << LL_ENDL; + } + } + else + { + previous_index = search_index; + } + } + else + { + LL_DEBUGS("AutoReplace") << search_index<<" is "<<LLSD::typeString(targetList.type())<<LL_ENDL; + } + } + return found; +} + +/// Move the named list down in the priority order +bool LLAutoReplaceSettings::decreaseListPriority(std::string listName) +{ + LL_DEBUGS("AutoReplace")<<listName<<LL_ENDL; + S32 found_index = -1; + S32 search_index; + for ( search_index = 0; + found_index == -1 && search_index < mLists.size(); + search_index++ + ) + { + if ( listNameMatches( mLists[search_index], listName) ) + { + LL_DEBUGS("AutoReplace")<<"found at index "<<search_index<<LL_ENDL; + found_index = search_index; + } + } + if (found_index != -1) + { + S32 next_index; + for ( next_index = found_index+1; + next_index < mLists.size() && ! mLists[next_index].isMap(); + next_index++ + ) + { + // skipping over any undefined slots (see LLSD-30) + LL_WARNS("AutoReplace")<<next_index<<" ! not a map: "<<LLSD::typeString(mLists[next_index].type())<< LL_ENDL; + } + if ( next_index < mLists.size() ) + { + LLSD next_list = mLists[next_index]; + LL_DEBUGS("AutoReplace") << "erase "<<next_index<<LL_ENDL; + mLists.erase(next_index); + LL_DEBUGS("AutoReplace") << "insert at "<<found_index<<LL_ENDL; + mLists.insert(found_index, next_list); + } + else + { + LL_WARNS("AutoReplace") << "attempted to move bottom list down" << LL_ENDL; + } + } + else + { + LL_WARNS("AutoReplace") << "not found" << LL_ENDL; + } + return (found_index != -1); +} + + +std::string LLAutoReplaceSettings::replaceWord(const std::string currentWord) +{ + std::string returnedWord = currentWord; // in case no replacement is found + static LLCachedControl<bool> autoreplace_enabled(gSavedSettings, "AutoReplace"); + if ( autoreplace_enabled ) + { + LL_DEBUGS("AutoReplace")<<"checking '"<<currentWord<<"'"<< LL_ENDL; + //loop through lists in order + bool found = false; + for( LLSD::array_const_iterator list = mLists.beginArray(), endLists = mLists.endArray(); + ! found && list != endLists; + list++ + ) + { + const LLSD& checkList = *list; + const LLSD& replacements = checkList[AUTOREPLACE_LIST_REPLACEMENTS]; + + if ( replacements.has(currentWord) ) + { + found = true; + LL_DEBUGS("AutoReplace") + << " found in list '" << checkList[AUTOREPLACE_LIST_NAME].asString() + << " => '" << replacements[currentWord].asString() << "'" + << LL_ENDL; + returnedWord = replacements[currentWord].asString(); + } + } + } + return returnedWord; +} + +bool LLAutoReplaceSettings::addEntryToList(LLWString keyword, LLWString replacement, std::string listName) +{ + bool added = false; + + if ( ! keyword.empty() && ! replacement.empty() ) + { + bool isOneWord = true; + for (S32 character = 0; isOneWord && character < keyword.size(); character++ ) + { + if ( ! LLWStringUtil::isPartOfWord(keyword[character]) ) + { + LL_WARNS("AutoReplace") << "keyword '" << wstring_to_utf8str(keyword) << "' not a single word (len "<<keyword.size()<<" '"<<character<<"')" << LL_ENDL; + isOneWord = false; + } + } + + if ( isOneWord ) + { + bool listFound = false; + for( LLSD::array_iterator list = mLists.beginArray(), endLists = mLists.endArray(); + ! listFound && list != endLists; + list++ + ) + { + if ( listNameMatches(*list, listName) ) + { + listFound = true; + (*list)[AUTOREPLACE_LIST_REPLACEMENTS][wstring_to_utf8str(keyword)]=wstring_to_utf8str(replacement); + } + } + if (listFound) + { + added = true; + } + else + { + LL_WARNS("AutoReplace") << "list '" << listName << "' not found" << LL_ENDL; + } + } + } + + return added; +} + +bool LLAutoReplaceSettings::removeEntryFromList(std::string keyword, std::string listName) +{ + bool found = false; + for( LLSD::array_iterator list = mLists.beginArray(), endLists = mLists.endArray(); + ! found && list != endLists; + list++ + ) + { + if ( listNameMatches(*list, listName) ) + { + found = true; + (*list)[AUTOREPLACE_LIST_REPLACEMENTS].erase(keyword); + } + } + if (!found) + { + LL_WARNS("AutoReplace") << "list '" << listName << "' not found" << LL_ENDL; + } + return found; +} + +LLSD LLAutoReplaceSettings::getExampleLLSD() +{ + LL_DEBUGS("AutoReplace")<<LL_ENDL; + LLSD example = LLSD::emptyArray(); + + example[0] = LLSD::emptyMap(); + example[0][AUTOREPLACE_LIST_NAME] = "Example List 1"; + example[0][AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); + example[0][AUTOREPLACE_LIST_REPLACEMENTS]["keyword1"] = "replacement string 1"; + example[0][AUTOREPLACE_LIST_REPLACEMENTS]["keyword2"] = "replacement string 2"; + + example[1] = LLSD::emptyMap(); + example[1][AUTOREPLACE_LIST_NAME] = "Example List 2"; + example[1][AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); + example[1][AUTOREPLACE_LIST_REPLACEMENTS]["mistake1"] = "correction 1"; + example[1][AUTOREPLACE_LIST_REPLACEMENTS]["mistake2"] = "correction 2"; + + return example; +} + +const LLSD& LLAutoReplaceSettings::getAsLLSD() +{ + return mLists; +} + +LLAutoReplaceSettings::~LLAutoReplaceSettings() +{ +} diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h new file mode 100644 index 0000000000..30b1fd2c65 --- /dev/null +++ b/indra/newview/llautoreplace.h @@ -0,0 +1,228 @@ +/** + * @file llautoreplace.h + * @brief Auto Replace Manager + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef LLAUTOREPLACE_H +#define LLAUTOREPLACE_H + +#include "lllineeditor.h" + +class LLAutoReplace; + +/** The configuration data for the LLAutoReplace object + * + * This is a separate class so that the LLFloaterAutoReplaceSettings + * can have a copy of the configuration to manipulate before committing + * the changes back to the LLAutoReplace singleton that provides the + * autoreplace callback. + */ +class LLAutoReplaceSettings +{ + public: + LLAutoReplaceSettings(); + ~LLAutoReplaceSettings(); + + /// Constructor for creating a tempory copy of the current settings + LLAutoReplaceSettings(const LLAutoReplaceSettings& settings); + + /// Replace the current settings with new ones and save them to the user settings file + void set(const LLAutoReplaceSettings& newSettings); + + /// Load the current settings read from an LLSD file + bool setFromLLSD(const LLSD& settingsFromLLSD); + ///< @returns whether or not the settingsFromLLSD were valid + + // ================================================================ + ///@{ @name List Operations + // ================================================================ + + /// @returns the configured list names as an LLSD Array of strings + LLSD getListNames(); + + /// Status values returned from the addList method + typedef enum + { + AddListOk, + AddListDuplicateName, + AddListInvalidList, + } AddListResult; + + /// Inserts a new list at the end of the priority order + AddListResult addList(const LLSD& newList); + + /// Removes the named list, @returns false if not found + bool removeReplacementList(std::string listName); + + /// Move the named list up in the priority order + bool increaseListPriority(std::string listName); + ///< @returns false if the list is not found + + /// Move the named list down in the priority order + bool decreaseListPriority(std::string listName); + ///< @returns false if the list is not found + + /// Get a copy of just one list (for saving to an export file) + const LLSD* exportList(std::string listName); + /// @returns an LLSD map + + /// Checks for required elements, and that each has the correct type. + bool listIsValid(const LLSD& listSettings); + + /// Checks for required elements, and that each has the correct type. + bool listNameIs(const LLSD& listSettings); + + /// Checks to see if a new lists name conflicts with one in the settings + bool listNameIsUnique(const LLSD& newList); + /// @note must be called with LLSD that has passed listIsValid + + /// Initializes emptyList to an empty list named 'Empty' + static void createEmptyList(LLSD& emptyList); + + /// Resets the name of a list to a new value + static void setListName(LLSD& list, const std::string& newName); + + /// Gets the name of a list + static std::string getListName(LLSD& list); + + ///@} + // ================================================================ + ///@{ @name Replacement Entry Operations + // ================================================================ + + /// Get the replacements specified by a given list + const LLSD* getListEntries(std::string listName); + ///< @returns an LLSD Map of keyword -> replacement test pairs + + /// Get the replacement for the keyword from the specified list + std::string replacementFor(std::string keyword, std::string listName); + + /// Adds a keywword/replacement pair to the named list + bool addEntryToList(LLWString keyword, LLWString replacement, std::string listName); + + /// Removes the keywword and its replacement from the named list + bool removeEntryFromList(std::string keyword, std::string listName); + + /** + * Look for currentWord in the lists in order, returning any substitution found + * If no configured substitution is found, returns currentWord + */ + std::string replaceWord(const std::string currentWord /**< word to search for */ ); + + /// Provides a hard-coded example of settings + LLSD getExampleLLSD(); + + /// Get the actual settings as LLSD + const LLSD& getAsLLSD(); + ///< @note for use only in AutoReplace::saveToUserSettings + + private: + /// Efficiently and safely compare list names + bool listNameMatches( const LLSD& list, const std::string name ); + + /// The actual llsd data structure + LLSD mLists; + + static const std::string AUTOREPLACE_LIST_NAME; ///< key for looking up list names + static const std::string AUTOREPLACE_LIST_REPLACEMENTS; ///< key for looking up replacement map + + /**< + * LLSD structure of the lists + * - The configuration is an array (mLists), + * - Each entry in the array is a replacement list + * - Each replacement list is a map with three keys: + * @verbatim + * "name" String the name of the list + * "replacements" Map keyword -> replacement pairs + * + * <llsd> + * <array> + * <map> + * <key>name</key> <string>List 1</string> + * <key>data</key> + * <map> + * <key>keyword1</key> <string>replacement1</string> + * <key>keyword2</key> <string>replacement2</string> + * </map> + * </map> + * <map> + * <key>name</key> <string>List 2</string> + * <key>data</key> + * <map> + * <key>keyword1</key> <string>replacement1</string> + * <key>keyword2</key> <string>replacement2</string> + * </map> + * </map> + * </array> + * </llsd> + * @endverbatim + */ +}; + +/** Provides a facility to auto-replace text dynamically as it is entered. + * + * When the end of a word is detected (defined as any punctuation character, + * or any whitespace except newline or return), the preceding word is used + * as a lookup key in an ordered list of maps. If a match is found in any + * map, the keyword is replaced by the associated value from the map. + * + * See the autoreplaceCallback method for how to add autoreplace functionality + * to a text entry tool. + */ +class LLAutoReplace : public LLSingleton<LLAutoReplace> +{ + public: + LLAutoReplace(); + ~LLAutoReplace(); + + /// @return a pointer to the active instance + static LLAutoReplace* getInstance(); + + /// Callback that provides the hook for use in text entry methods + void autoreplaceCallback(LLUIString& inputText, S32& cursorPos); + + /// Get a copy of the current settings + LLAutoReplaceSettings getSettings(); + + /// Commit new settings after making changes + void setSettings(const LLAutoReplaceSettings& settings); + + private: + friend class LLSingleton<LLAutoReplace>; + static LLAutoReplace* sInstance; ///< the active settings instance + + LLAutoReplaceSettings mSettings; ///< configuration information + + /// Read settings from persistent storage + void loadFromSettings(); + + /// Make the newSettings active and write them to user storage + void saveToUserSettings(); + + /// Compute the user settings file name + std::string getUserSettingsFileName(); + + /// Compute the (read-ony) application settings file name + std::string getAppSettingsFileName(); + + /// basename for the settings files + static const char* SETTINGS_FILE_NAME; +}; + +#endif /* LLAUTOREPLACE_H */ diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index bc4b301ebb..960c64fa9e 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -59,6 +59,7 @@ class LLViewerTexture; const U32 SILHOUETTE_HIGHLIGHT = 0; // All data for new renderer goes into this class. +LL_ALIGN_PREFIX(16) class LLDrawable : public LLRefCount { public: @@ -75,6 +76,16 @@ public: static void initClass(); + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLDrawable() { init(); } MEM_TYPE_NEW(LLMemType::MTYPE_DRAWABLE); @@ -284,8 +295,8 @@ public: } EDrawableFlags; private: //aligned members - LLVector4a mExtents[2]; - LLVector4a mPositionGroup; + LL_ALIGN_16(LLVector4a mExtents[2]); + LL_ALIGN_16(LLVector4a mPositionGroup); public: LLXformMatrix mXform; @@ -327,7 +338,7 @@ private: static U32 sNumZombieDrawables; static LLDynamicArrayPtr<LLPointer<LLDrawable> > sDeadList; -}; +} LL_ALIGN_POSTFIX(16); inline LLFace* LLDrawable::getFace(const S32 i) const diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 313b310e1e..b4f6bf9383 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -411,6 +411,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) continue; } + if ((params.mVertexBuffer->getTypeMask() & mask) != mask) + { //FIXME! + llwarns << "Missing required components, skipping render batch." << llendl; + continue; + } + LLRenderPass::applyModelMatrix(params); diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index e18090545d..c51e7d1e1a 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -36,6 +36,16 @@ class LLViewerDynamicTexture : public LLViewerTexture { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + enum { LL_VIEWER_DYNAMIC_TEXTURE = LLViewerTexture::DYNAMIC_TEXTURE, @@ -85,7 +95,7 @@ protected: protected: BOOL mClamp; LLCoordGL mOrigin; - LLCamera mCamera; + LL_ALIGN_16(LLCamera mCamera); typedef std::set<LLViewerDynamicTexture*> instance_list_t; static instance_list_t sInstances[ LLViewerDynamicTexture::ORDER_COUNT ]; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index f5b217d539..4f3208474d 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -166,8 +166,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) //special value to indicate uninitialized position mIndicesIndex = 0xFFFFFFFF; - - mIndexInTex = 0; + mTexture = NULL; mTEOffset = -1; mTextureIndex = 255; @@ -1636,7 +1635,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (!do_xform) { LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); - LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); + S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, tc_size); } else { diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 3babc13c2e..efc3424858 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -59,6 +59,17 @@ class LLFace { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + + LLFace(const LLFace& rhs) { *this = rhs; diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 8986a694f9..4bf5b26b3b 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -59,6 +59,7 @@ LLFilePicker LLFilePicker::sInstance; #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0" #define MODEL_FILTER L"Model files (*.dae)\0*.dae\0" #define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0" +#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0" #endif // @@ -218,6 +219,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = SCRIPT_FILTER \ L"\0"; break; + case FFLOAD_DICTIONARY: + mOFN.lpstrFilter = DICTIONARY_FILTER \ + L"\0"; + break; default: res = FALSE; break; @@ -643,6 +648,16 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB result = false; } } + else if (filter == FFLOAD_DICTIONARY) + { + if (fileInfo.filetype != 'DIC ' && + fileInfo.filetype != 'XCU ' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dic"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && + fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("xcu"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))) + { + result = false; + } + } if (fileInfo.extension) { @@ -1235,6 +1250,12 @@ static std::string add_script_filter_to_gtkchooser(GtkWindow *picker) LLTrans::getString("script_files") + " (*.lsl)"); } +static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker) +{ + return add_simple_mime_filter_to_gtkchooser(picker, "text/plain", + LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)"); +} + BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) { BOOL rtn = FALSE; @@ -1371,6 +1392,9 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) case FFLOAD_SCRIPT: filtername = add_script_filter_to_gtkchooser(picker); break; + case FFLOAD_DICTIONARY: + filtername = add_dictionary_filter_to_gtkchooser(picker); + break; default:; break; } diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index a4d5d68ff5..55c665b9c7 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -85,6 +85,7 @@ public: FFLOAD_MODEL = 9, FFLOAD_COLLADA = 10, FFLOAD_SCRIPT = 11, + FFLOAD_DICTIONARY = 12 }; enum ESaveFilter diff --git a/indra/newview/llfloaterautoreplacesettings.cpp b/indra/newview/llfloaterautoreplacesettings.cpp new file mode 100644 index 0000000000..7d1bcba978 --- /dev/null +++ b/indra/newview/llfloaterautoreplacesettings.cpp @@ -0,0 +1,641 @@ +/** + * @file llfloaterautoreplacesettings.cpp + * @brief Auto Replace List floater + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterautoreplacesettings.h" + +#include "llagentdata.h" +#include "llcommandhandler.h" +#include "llfloater.h" +#include "lluictrlfactory.h" +#include "llagent.h" +#include "llpanel.h" +#include "llbutton.h" +#include "llcolorswatch.h" +#include "llcombobox.h" +#include "llview.h" +#include "llhttpclient.h" +#include "llbufferstream.h" +#include "llcheckboxctrl.h" +#include "llviewercontrol.h" + +#include "llui.h" +#include "llcontrol.h" +#include "llscrollingpanellist.h" +#include "llautoreplace.h" +#include "llfilepicker.h" +#include "llfile.h" +#include "llsdserialize.h" +#include "llsdutil.h" + +#include "llchat.h" +#include "llinventorymodel.h" +#include "llhost.h" +#include "llassetstorage.h" +#include "roles_constants.h" +#include "llviewertexteditor.h" +#include <boost/tokenizer.hpp> + +#include <iosfwd> +#include "llfloaterreg.h" +#include "llinspecttoast.h" +#include "llnotificationhandler.h" +#include "llnotificationmanager.h" +#include "llnotificationsutil.h" + + +LLFloaterAutoReplaceSettings::LLFloaterAutoReplaceSettings(const LLSD& key) + : LLFloater(key) + , mSelectedListName("") + , mListNames(NULL) + , mReplacementsList(NULL) + , mKeyword(NULL) + , mPreviousKeyword("") + , mReplacement(NULL) +{ +} + +void LLFloaterAutoReplaceSettings::onClose(bool app_quitting) +{ + cleanUp(); +} + +BOOL LLFloaterAutoReplaceSettings::postBuild(void) +{ + // get copies of the current settings that we will operate on + mEnabled = gSavedSettings.getBOOL("AutoReplace"); + LL_DEBUGS("AutoReplace") << ( mEnabled ? "enabled" : "disabled") << LL_ENDL; + + mSettings = LLAutoReplace::getInstance()->getSettings(); + + // global checkbox for whether or not autoreplace is active + LLUICtrl* enabledCheckbox = getChild<LLUICtrl>("autoreplace_enable"); + enabledCheckbox->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onAutoReplaceToggled, this)); + enabledCheckbox->setValue(LLSD(mEnabled)); + + // top row list creation and deletion + getChild<LLUICtrl>("autoreplace_import_list")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onImportList,this)); + getChild<LLUICtrl>("autoreplace_export_list")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onExportList,this)); + getChild<LLUICtrl>("autoreplace_new_list")->setCommitCallback( boost::bind(&LLFloaterAutoReplaceSettings::onNewList,this)); + getChild<LLUICtrl>("autoreplace_delete_list")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onDeleteList,this)); + + // the list of keyword->replacement lists + mListNames = getChild<LLScrollListCtrl>("autoreplace_list_name"); + mListNames->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSelectList, this)); + mListNames->setCommitOnSelectionChange(true); + + // list ordering + getChild<LLUICtrl>("autoreplace_list_up")->setCommitCallback( boost::bind(&LLFloaterAutoReplaceSettings::onListUp,this)); + getChild<LLUICtrl>("autoreplace_list_down")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onListDown,this)); + + // keyword->replacement entry add / delete + getChild<LLUICtrl>("autoreplace_add_entry")->setCommitCallback( boost::bind(&LLFloaterAutoReplaceSettings::onAddEntry,this)); + getChild<LLUICtrl>("autoreplace_delete_entry")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onDeleteEntry,this)); + + // entry edits + mKeyword = getChild<LLLineEditor>("autoreplace_keyword"); + mReplacement = getChild<LLLineEditor>("autoreplace_replacement"); + getChild<LLUICtrl>("autoreplace_save_entry")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSaveEntry, this)); + + // dialog termination ( Save Changes / Cancel ) + getChild<LLUICtrl>("autoreplace_save_changes")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSaveChanges, this)); + getChild<LLUICtrl>("autoreplace_cancel")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onCancel, this)); + + // the list of keyword->replacement pairs + mReplacementsList = getChild<LLScrollListCtrl>("autoreplace_list_replacements"); + mReplacementsList->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSelectEntry, this)); + mReplacementsList->setCommitOnSelectionChange(true); + + center(); + + mSelectedListName.clear(); + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); + + return true; +} + + +void LLFloaterAutoReplaceSettings::updateListNames() +{ + mListNames->deleteAllItems(); // start from scratch + + LLSD listNames = mSettings.getListNames(); // Array of Strings + + for ( LLSD::array_const_iterator entry = listNames.beginArray(), end = listNames.endArray(); + entry != end; + ++entry + ) + { + const std::string& listName = entry->asString(); + mListNames->addSimpleElement(listName); + } + + if (!mSelectedListName.empty()) + { + mListNames->setSelectedByValue( LLSD(mSelectedListName), true ); + } +} + +void LLFloaterAutoReplaceSettings::updateListNamesControls() +{ + if ( mSelectedListName.empty() ) + { + // There is no selected list + + // Disable all controls that operate on the selected list + getChild<LLButton>("autoreplace_export_list")->setEnabled(false); + getChild<LLButton>("autoreplace_delete_list")->setEnabled(false); + getChild<LLButton>("autoreplace_list_up")->setEnabled(false); + getChild<LLButton>("autoreplace_list_down")->setEnabled(false); + + mReplacementsList->deleteAllItems(); + } + else + { + // Enable the controls that operate on the selected list + getChild<LLButton>("autoreplace_export_list")->setEnabled(true); + getChild<LLButton>("autoreplace_delete_list")->setEnabled(true); + getChild<LLButton>("autoreplace_list_up")->setEnabled(!selectedListIsFirst()); + getChild<LLButton>("autoreplace_list_down")->setEnabled(!selectedListIsLast()); + } +} + +void LLFloaterAutoReplaceSettings::onSelectList() +{ + std::string previousSelectedListName = mSelectedListName; + // only one selection allowed + LLSD selected = mListNames->getSelectedValue(); + if (selected.isDefined()) + { + mSelectedListName = selected.asString(); + LL_DEBUGS("AutoReplace")<<"selected list '"<<mSelectedListName<<"'"<<LL_ENDL; + } + else + { + mSelectedListName.clear(); + LL_DEBUGS("AutoReplace")<<"unselected"<<LL_ENDL; + } + + updateListNamesControls(); + + if ( previousSelectedListName != mSelectedListName ) + { + updateReplacementsList(); + } +} + +void LLFloaterAutoReplaceSettings::onSelectEntry() +{ + LLSD selectedRow = mReplacementsList->getSelectedValue(); + if (selectedRow.isDefined()) + { + mPreviousKeyword = selectedRow.asString(); + LL_DEBUGS("AutoReplace")<<"selected entry '"<<mPreviousKeyword<<"'"<<LL_ENDL; + mKeyword->setValue(selectedRow); + std::string replacement = mSettings.replacementFor(mPreviousKeyword, mSelectedListName ); + mReplacement->setValue(replacement); + enableReplacementEntry(); + mReplacement->setFocus(true); + } + else + { + // no entry selection, so the entry panel should be off + disableReplacementEntry(); + LL_DEBUGS("AutoReplace")<<"no row selected"<<LL_ENDL; + } +} + +void LLFloaterAutoReplaceSettings::updateReplacementsList() +{ + // start from scratch, since this should only be called when the list changes + mReplacementsList->deleteAllItems(); + + if ( mSelectedListName.empty() ) + { + mReplacementsList->setEnabled(false); + getChild<LLButton>("autoreplace_add_entry")->setEnabled(false); + disableReplacementEntry(); + } + else + { + // Populate the keyword->replacement list from the selected list + const LLSD* mappings = mSettings.getListEntries(mSelectedListName); + for ( LLSD::map_const_iterator entry = mappings->beginMap(), end = mappings->endMap(); + entry != end; + entry++ + ) + { + LLSD row; + row["id"] = entry->first; + row["columns"][0]["column"] = "keyword"; + row["columns"][0]["value"] = entry->first; + row["columns"][1]["column"] = "replacement"; + row["columns"][1]["value"] = entry->second; + + mReplacementsList->addElement(row, ADD_BOTTOM); + } + + mReplacementsList->deselectAllItems(false /* don't call commit */); + mReplacementsList->setEnabled(true); + + getChild<LLButton>("autoreplace_add_entry")->setEnabled(true); + disableReplacementEntry(); + } +} + +void LLFloaterAutoReplaceSettings::enableReplacementEntry() +{ + LL_DEBUGS("AutoReplace")<<LL_ENDL; + mKeyword->setEnabled(true); + mReplacement->setEnabled(true); + getChild<LLButton>("autoreplace_save_entry")->setEnabled(true); + getChild<LLButton>("autoreplace_delete_entry")->setEnabled(true); +} + +void LLFloaterAutoReplaceSettings::disableReplacementEntry() +{ + LL_DEBUGS("AutoReplace")<<LL_ENDL; + mPreviousKeyword.clear(); + mKeyword->clear(); + mKeyword->setEnabled(false); + mReplacement->clear(); + mReplacement->setEnabled(false); + getChild<LLButton>("autoreplace_save_entry")->setEnabled(false); + getChild<LLButton>("autoreplace_delete_entry")->setEnabled(false); +} + +// called when the global settings checkbox is changed +void LLFloaterAutoReplaceSettings::onAutoReplaceToggled() +{ + // set our local copy of the flag, copied to the global preference in onOk + mEnabled = childGetValue("autoreplace_enable").asBoolean(); + LL_DEBUGS("AutoReplace")<< "autoreplace_enable " << ( mEnabled ? "on" : "off" ) << LL_ENDL; +} + +// called when the List Up button is pressed +void LLFloaterAutoReplaceSettings::onListUp() +{ + S32 selectedRow = mListNames->getFirstSelectedIndex(); + LLSD selectedName = mListNames->getSelectedValue().asString(); + + if ( mSettings.increaseListPriority(selectedName) ) + { + updateListNames(); + updateListNamesControls(); + } + else + { + LL_WARNS("AutoReplace") + << "invalid row ("<<selectedRow<<") selected '"<<selectedName<<"'" + <<LL_ENDL; + } +} + +// called when the List Down button is pressed +void LLFloaterAutoReplaceSettings::onListDown() +{ + S32 selectedRow = mListNames->getFirstSelectedIndex(); + std::string selectedName = mListNames->getSelectedValue().asString(); + + if ( mSettings.decreaseListPriority(selectedName) ) + { + updateListNames(); + updateListNamesControls(); + } + else + { + LL_WARNS("AutoReplace") + << "invalid row ("<<selectedRow<<") selected '"<<selectedName<<"'" + <<LL_ENDL; + } +} + +// called when the Delete Entry button is pressed +void LLFloaterAutoReplaceSettings::onDeleteEntry() +{ + LLSD selectedRow = mReplacementsList->getSelectedValue(); + if (selectedRow.isDefined()) + { + std::string keyword = selectedRow.asString(); + mReplacementsList->deleteSelectedItems(); // delete from the control + mSettings.removeEntryFromList(keyword, mSelectedListName); // delete from the local settings copy + disableReplacementEntry(); // no selection active, so turn off the buttons + } +} + +// called when the Import List button is pressed +void LLFloaterAutoReplaceSettings::onImportList() +{ + LLFilePicker& picker = LLFilePicker::instance(); + if( picker.getOpenFile( LLFilePicker::FFLOAD_XML) ) + { + llifstream file; + file.open(picker.getFirstFile().c_str()); + LLSD newList; + if (file.is_open()) + { + LLSDSerialize::fromXMLDocument(newList, file); + } + file.close(); + + switch ( mSettings.addList(newList) ) + { + case LLAutoReplaceSettings::AddListOk: + mSelectedListName = LLAutoReplaceSettings::getListName(newList); + + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); + break; + + case LLAutoReplaceSettings::AddListDuplicateName: + { + std::string newName = LLAutoReplaceSettings::getListName(newList); + LL_WARNS("AutoReplace")<<"name '"<<newName<<"' is in use; prompting for new name"<<LL_ENDL; + LLSD newPayload; + newPayload["list"] = newList; + LLSD args; + args["DUPNAME"] = newName; + + LLNotificationsUtil::add("RenameAutoReplaceList", args, newPayload, + boost::bind(&LLFloaterAutoReplaceSettings::callbackListNameConflict, this, _1, _2)); + } + break; + + case LLAutoReplaceSettings::AddListInvalidList: + LLNotificationsUtil::add("InvalidAutoReplaceList"); + LL_WARNS("AutoReplace") << "imported list was invalid" << LL_ENDL; + + mSelectedListName.clear(); + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); + break; + + default: + LL_ERRS("AutoReplace") << "invalid AddListResult" << LL_ENDL; + + } + + } + else + { + LL_DEBUGS("AutoReplace") << "file selection failed for import list" << LL_ENDL; + } +} + +void LLFloaterAutoReplaceSettings::onNewList() +{ + LLSD payload; + LLSD emptyList; + LLAutoReplaceSettings::createEmptyList(emptyList); + payload["list"] = emptyList; + LLSD args; + + LLNotificationsUtil::add("AddAutoReplaceList", args, payload, + boost::bind(&LLFloaterAutoReplaceSettings::callbackNewListName, this, _1, _2)); +} + +bool LLFloaterAutoReplaceSettings::callbackNewListName(const LLSD& notification, const LLSD& response) +{ + LL_DEBUGS("AutoReplace")<<"called"<<LL_ENDL; + + LLSD newList = notification["payload"]["list"]; + + if ( response.has("listname") && response["listname"].isString() ) + { + std::string newName = response["listname"].asString(); + LLAutoReplaceSettings::setListName(newList, newName); + + switch ( mSettings.addList(newList) ) + { + case LLAutoReplaceSettings::AddListOk: + LL_INFOS("AutoReplace") << "added new list '"<<newName<<"'"<<LL_ENDL; + mSelectedListName = newName; + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); + break; + + case LLAutoReplaceSettings::AddListDuplicateName: + { + LL_WARNS("AutoReplace")<<"name '"<<newName<<"' is in use; prompting for new name"<<LL_ENDL; + LLSD newPayload; + newPayload["list"] = notification["payload"]["list"]; + LLSD args; + args["DUPNAME"] = newName; + + LLNotificationsUtil::add("RenameAutoReplaceList", args, newPayload, + boost::bind(&LLFloaterAutoReplaceSettings::callbackListNameConflict, this, _1, _2)); + } + break; + + case LLAutoReplaceSettings::AddListInvalidList: + LLNotificationsUtil::add("InvalidAutoReplaceList"); + + mSelectedListName.clear(); + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); + break; + + default: + LL_ERRS("AutoReplace") << "invalid AddListResult" << LL_ENDL; + } + } + else + { + LL_ERRS("AutoReplace") << "adding notification response" << LL_ENDL; + } + return false; +} + +// callback for the RenameAutoReplaceList notification +bool LLFloaterAutoReplaceSettings::callbackListNameConflict(const LLSD& notification, const LLSD& response) +{ + LLSD newList = notification["payload"]["list"]; + + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch ( option ) + { + case 0: + // Replace current list + LL_INFOS("AutoReplace")<<"option 'replace current list' selected"<<LL_ENDL; + + break; + + case 1: + // Use New Name + LL_INFOS("AutoReplace")<<"option 'use new name' selected"<<LL_ENDL; + callbackNewListName(notification, response); + break; + + default: + LL_ERRS("AutoReplace")<<"invalid selected option "<<option<<LL_ENDL; + } + + return false; +} + +void LLFloaterAutoReplaceSettings::onDeleteList() +{ + std::string listName= mListNames->getFirstSelected()->getColumn(0)->getValue().asString(); + mSettings.removeReplacementList(listName); // remove from the copy of settings + mReplacementsList->deleteSelectedItems(); // remove from the scrolling list + + mSelectedListName.clear(); + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); +} + +void LLFloaterAutoReplaceSettings::onExportList() +{ + std::string listName=mListNames->getFirstSelected()->getColumn(0)->getValue().asString(); + const LLSD* list = mSettings.exportList(listName); + std::string listFileName = listName + ".xml"; + LLFilePicker& picker = LLFilePicker::instance(); + if( picker.getSaveFile( LLFilePicker::FFSAVE_XML, listFileName) ) + { + llofstream file; + file.open(picker.getFirstFile().c_str()); + LLSDSerialize::toPrettyXML(*list, file); + file.close(); + } +} + +void LLFloaterAutoReplaceSettings::onAddEntry() +{ + mPreviousKeyword.clear(); + mReplacementsList->deselectAllItems(false /* don't call commit */); + mKeyword->clear(); + mReplacement->clear(); + enableReplacementEntry(); + mKeyword->setFocus(true); +} + +void LLFloaterAutoReplaceSettings::onSaveEntry() +{ + LL_DEBUGS("AutoReplace")<<"called"<<LL_ENDL; + + if ( ! mPreviousKeyword.empty() ) + { + // delete any existing value for the key that was editted + LL_INFOS("AutoReplace") + << "list '" << mSelectedListName << "' " + << "removed '" << mPreviousKeyword + << "'" << LL_ENDL; + mSettings.removeEntryFromList( mPreviousKeyword, mSelectedListName ); + } + + LLWString keyword = mKeyword->getWText(); + LLWString replacement = mReplacement->getWText(); + if ( mSettings.addEntryToList(keyword, replacement, mSelectedListName) ) + { + // insert the new keyword->replacement pair + LL_INFOS("AutoReplace") + << "list '" << mSelectedListName << "' " + << "added '" << wstring_to_utf8str(keyword) + << "' -> '" << wstring_to_utf8str(replacement) + << "'" << LL_ENDL; + + updateReplacementsList(); + } + else + { + LLNotificationsUtil::add("InvalidAutoReplaceEntry"); + LL_WARNS("AutoReplace")<<"invalid entry " + << "keyword '" << wstring_to_utf8str(keyword) + << "' replacement '" << wstring_to_utf8str(replacement) + << "'" << LL_ENDL; + } +} + +void LLFloaterAutoReplaceSettings::onCancel() +{ + cleanUp(); + closeFloater(false /* not quitting */); +} + +void LLFloaterAutoReplaceSettings::onSaveChanges() +{ + // put our local copy of the settings into the active copy + LLAutoReplace::getInstance()->setSettings( mSettings ); + // save our local copy of the global feature enable/disable value + gSavedSettings.setBOOL("AutoReplace", mEnabled); + cleanUp(); + closeFloater(false /* not quitting */); +} + +void LLFloaterAutoReplaceSettings::cleanUp() +{ + +} + +bool LLFloaterAutoReplaceSettings::selectedListIsFirst() +{ + bool isFirst = false; + + if (!mSelectedListName.empty()) + { + LLSD lists = mSettings.getListNames(); // an Array of Strings + LLSD first = lists.get(0); + if ( first.isString() && first.asString() == mSelectedListName ) + { + isFirst = true; + } + } + return isFirst; +} + +bool LLFloaterAutoReplaceSettings::selectedListIsLast() +{ + bool isLast = false; + + if (!mSelectedListName.empty()) + { + LLSD last; + LLSD lists = mSettings.getListNames(); // an Array of Strings + for ( LLSD::array_const_iterator list = lists.beginArray(), listEnd = lists.endArray(); + list != listEnd; + list++ + ) + { + last = *list; + } + if ( last.isString() && last.asString() == mSelectedListName ) + { + isLast = true; + } + } + return isLast; +} + +/* TBD +mOldText = getChild<LLLineEditor>("autoreplace_old_text"); +mNewText = getChild<LLLineEditor>("autoreplace_new_text"); +*/ diff --git a/indra/newview/llfloaterautoreplacesettings.h b/indra/newview/llfloaterautoreplacesettings.h new file mode 100644 index 0000000000..629aea3e3c --- /dev/null +++ b/indra/newview/llfloaterautoreplacesettings.h @@ -0,0 +1,117 @@ +/** + * @file llfloaterautoreplacesettings.h + * @brief Auto Replace List floater + * @copyright Copyright (c) 2011 LordGregGreg Back + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERAUTOREPLACESETTINGS_H +#define LLFLOATERAUTOREPLACESETTINGS_H + +#include "llfloater.h" +#include "llmediactrl.h" +#include "llscrolllistctrl.h" +#include "lllineeditor.h" + +#include "llviewerinventory.h" +#include <boost/bind.hpp> +#include "llautoreplace.h" + +class LLFloaterAutoReplaceSettings : public LLFloater +{ +public: + LLFloaterAutoReplaceSettings(const LLSD& key); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_quitting); + + void setData(void * data); + +private: + + /** @{ @name Local Copies of Settings + * These are populated in the postBuild method with the values + * current when the floater is instantiated, and then either + * discarded when Cancel is pressed, or copied back to the active + * settings if Ok is pressed. + */ + bool mEnabled; ///< the global preference for AutoReplace + LLAutoReplaceSettings mSettings; ///< settings being modified + /** @} */ + + /// convenience variable - the name of the currently selected list (if any) + std::string mSelectedListName; + /// the scrolling list of list names (one column, no headings, order manually controlled) + LLScrollListCtrl* mListNames; + /// the scroling list of keyword->replacement pairs + LLScrollListCtrl* mReplacementsList; + + /// the keyword for the entry editing pane + LLLineEditor* mKeyword; + /// saved keyword value + std::string mPreviousKeyword; + /// the replacement for the entry editing pane + LLLineEditor* mReplacement; + + /// callback for when the feature enable/disable checkbox changes + void onAutoReplaceToggled(); + /// callback for when an entry in the list of list names is selected + void onSelectList(); + + void onImportList(); + void onExportList(); + void onNewList(); + void onDeleteList(); + + void onListUp(); + void onListDown(); + + void onSelectEntry(); + void onAddEntry(); + void onDeleteEntry(); + void onSaveEntry(); + + void onSaveChanges(); + void onCancel(); + + /// updates the contents of the mListNames + void updateListNames(); + /// updates the controls associated with mListNames (depends on whether a name is selected or not) + void updateListNamesControls(); + /// updates the contents of the mReplacementsList + void updateReplacementsList(); + /// enables the components that should only be active when a keyword is selected + void enableReplacementEntry(); + /// disables the components that should only be active when a keyword is selected + void disableReplacementEntry(); + + /// called from the AddAutoReplaceList notification dialog + bool callbackNewListName(const LLSD& notification, const LLSD& response); + /// called from the RenameAutoReplaceList notification dialog + bool callbackListNameConflict(const LLSD& notification, const LLSD& response); + + bool selectedListIsFirst(); + bool selectedListIsLast(); + + void cleanUp(); +}; + +#endif // LLFLOATERAUTOREPLACESETTINGS_H diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index cc7c9a5bda..df8ecb6fd9 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1865,23 +1865,8 @@ BOOL LLPanelLandOptions::postBuild() childSetCommitCallback("ShowDirectoryCheck", onCommitAny, this); - if (gAgent.getAgentAccess().isInTransition()) - { - // during the AO transition, this combo has an Adult item. - // Post-transition, it goes away. We can remove this conditional - // after the transition and just use the "else" clause. - mCategoryCombo = getChild<LLComboBox>( "land category with adult"); - childSetCommitCallback("land category with adult", onCommitAny, this); - } - else - { - // this is the code that should be preserved post-transition - // you could also change the XML to set visibility and enabled true. - mCategoryCombo = getChild<LLComboBox>( "land category"); - childSetCommitCallback("land category", onCommitAny, this); - } - mCategoryCombo->setVisible(true); - mCategoryCombo->setEnabled(true); + mCategoryCombo = getChild<LLComboBox>( "land category"); + childSetCommitCallback("land category", onCommitAny, this); mMatureCtrl = getChild<LLCheckBoxCtrl>( "MatureCheck"); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 40d2157e28..35341ef0ea 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -4774,7 +4774,8 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) if (vf.mTexCoords) { vb->getTexCoord0Strider(tc_strider); - LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); + S32 tex_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, tex_size); } if (vf.mNormals) @@ -5047,15 +5048,7 @@ BOOL LLModelPreview::render() LLRect preview_rect; - LLFloaterModelWizard* floater_wizard = dynamic_cast<LLFloaterModelWizard*>(mFMP); - if (floater_wizard) - { - preview_rect = floater_wizard->getPreviewRect(); - } - else - { - preview_rect = mFMP->getChildView("preview_panel")->getRect(); - } + preview_rect = mFMP->getChildView("preview_panel")->getRect(); F32 aspect = (F32) preview_rect.getWidth()/preview_rect.getHeight(); @@ -5599,7 +5592,6 @@ void LLModelPreview::setPreviewLOD(S32 lod) combo_box->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order mFMP->childSetText("lod_file_" + lod_name[mPreviewLOD], mLODFile[mPreviewLOD]); - // the wizard has three lod drop downs LLComboBox* combo_box2 = mFMP->getChild<LLComboBox>("preview_lod_combo2"); combo_box2->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 981f9b0f72..ab319c30d5 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -30,12 +30,12 @@ #include "llfloaternamedesc.h" #include "lldynamictexture.h" -#include "llfloatermodelwizard.h" #include "llquaternion.h" #include "llmeshrepository.h" #include "llmodel.h" #include "llthread.h" #include "llviewermenufile.h" +#include "llfloatermodeluploadbase.h" class LLComboBox; class LLJoint; @@ -389,9 +389,7 @@ private: protected: friend class LLModelLoader; friend class LLFloaterModelPreview; - friend class LLFloaterModelWizard; friend class LLFloaterModelPreview::DecompRequest; - friend class LLFloaterModelWizard::DecompRequest; friend class LLPhysicsDecomp; LLFloater* mFMP; diff --git a/indra/newview/llfloatermodelwizard.cpp b/indra/newview/llfloatermodelwizard.cpp deleted file mode 100644 index b517b78e5a..0000000000 --- a/indra/newview/llfloatermodelwizard.cpp +++ /dev/null @@ -1,795 +0,0 @@ -/** - * @file llfloatermodelwizard.cpp - * @author Leyla Farazha - * @brief Implementation of the LLFloaterModelWizard class. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - - -#include "llviewerprecompiledheaders.h" - -#include "llbutton.h" -#include "lldrawable.h" -#include "llcheckboxctrl.h" -#include "llcombobox.h" -#include "llfloater.h" -#include "llfloatermodelwizard.h" -#include "llfloatermodelpreview.h" -#include "llfloaterreg.h" -#include "llsliderctrl.h" -#include "lltoolmgr.h" -#include "llviewerwindow.h" - -LLFloaterModelWizard* LLFloaterModelWizard::sInstance = NULL; - -static const std::string stateNames[]={ - "choose_file", - "optimize", - "physics", - "review", - "upload"}; - -static void swap_controls(LLUICtrl* first_ctrl, LLUICtrl* second_ctrl, bool first_ctr_visible); - -LLFloaterModelWizard::LLFloaterModelWizard(const LLSD& key) - : LLFloaterModelUploadBase(key) - ,mRecalculateGeometryBtn(NULL) - ,mRecalculatePhysicsBtn(NULL) - ,mRecalculatingPhysicsBtn(NULL) - ,mCalculateWeightsBtn(NULL) - ,mCalculatingWeightsBtn(NULL) - ,mChooseFilePreviewPanel(NULL) - ,mOptimizePreviewPanel(NULL) - ,mPhysicsPreviewPanel(NULL) -{ - mLastEnabledState = CHOOSE_FILE; - sInstance = this; - - mCommitCallbackRegistrar.add("Wizard.Choose", boost::bind(&LLFloaterModelWizard::setState, this, CHOOSE_FILE)); - mCommitCallbackRegistrar.add("Wizard.Optimize", boost::bind(&LLFloaterModelWizard::setState, this, OPTIMIZE)); - mCommitCallbackRegistrar.add("Wizard.Physics", boost::bind(&LLFloaterModelWizard::setState, this, PHYSICS)); - mCommitCallbackRegistrar.add("Wizard.Review", boost::bind(&LLFloaterModelWizard::setState, this, REVIEW)); - mCommitCallbackRegistrar.add("Wizard.Upload", boost::bind(&LLFloaterModelWizard::setState, this, UPLOAD)); -} -LLFloaterModelWizard::~LLFloaterModelWizard() -{ - sInstance = NULL; -} -void LLFloaterModelWizard::setState(int state) -{ - - mState = state; - - for(size_t t=0; t<LL_ARRAY_SIZE(stateNames); ++t) - { - LLView *view = getChildView(stateNames[t]+"_panel"); - if (view) - { - view->setVisible(state == (int) t ? TRUE : FALSE); - } - } - - LLView* current_preview_panel = NULL; - - if (state == CHOOSE_FILE) - { - mModelPreview->mViewOption["show_physics"] = false; - - current_preview_panel = mChooseFilePreviewPanel; - - getChildView("close")->setVisible(false); - getChildView("back")->setVisible(true); - getChildView("back")->setEnabled(false); - getChildView("next")->setVisible(true); - getChildView("upload")->setVisible(false); - getChildView("cancel")->setVisible(true); - mCalculateWeightsBtn->setVisible(false); - mCalculatingWeightsBtn->setVisible(false); - } - - if (state == OPTIMIZE) - { - if (mLastEnabledState < state) - { - mModelPreview->genLODs(-1); - } - - mModelPreview->mViewOption["show_physics"] = false; - - current_preview_panel = mOptimizePreviewPanel; - - getChildView("back")->setVisible(true); - getChildView("back")->setEnabled(true); - getChildView("close")->setVisible(false); - getChildView("next")->setVisible(true); - getChildView("upload")->setVisible(false); - getChildView("cancel")->setVisible(true); - mCalculateWeightsBtn->setVisible(false); - mCalculatingWeightsBtn->setVisible(false); - } - - if (state == PHYSICS) - { - if (mLastEnabledState < state) - { - mModelPreview->setPhysicsFromLOD(1); - - // Trigger the recalculate physics when first entering - // the Physics step. - onClickRecalculatePhysics(); - } - - mModelPreview->mViewOption["show_physics"] = true; - - current_preview_panel = mPhysicsPreviewPanel; - - getChildView("next")->setVisible(false); - getChildView("upload")->setVisible(false); - getChildView("close")->setVisible(false); - getChildView("back")->setVisible(true); - getChildView("back")->setEnabled(true); - getChildView("cancel")->setVisible(true); - mCalculateWeightsBtn->setVisible(true); - mCalculatingWeightsBtn->setVisible(false); - } - - if (state == REVIEW) - { - - mModelPreview->mViewOption["show_physics"] = false; - - getChildView("close")->setVisible(false); - getChildView("next")->setVisible(false); - getChildView("back")->setVisible(true); - getChildView("back")->setEnabled(true); - getChildView("upload")->setVisible(true); - getChildView("cancel")->setVisible(true); - mCalculateWeightsBtn->setVisible(false); - mCalculatingWeightsBtn->setVisible(false); - } - - if (state == UPLOAD) - { - getChildView("close")->setVisible(true); - getChildView("next")->setVisible(false); - getChildView("back")->setVisible(false); - getChildView("upload")->setVisible(false); - getChildView("cancel")->setVisible(false); - mCalculateWeightsBtn->setVisible(false); - mCalculatingWeightsBtn->setVisible(false); - } - - if (current_preview_panel) - { - LLRect rect; - current_preview_panel->localRectToOtherView(current_preview_panel->getLocalRect(), &rect, this); - - // Reduce the preview rect by 1 px to fit the borders - rect.stretch(-1); - - if (rect != mPreviewRect) - { - mPreviewRect = rect; - mModelPreview->refresh(); - } - } - updateButtons(); -} - - - -void LLFloaterModelWizard::updateButtons() -{ - if (mLastEnabledState < mState) - { - mLastEnabledState = mState; - } - - for(size_t i=0; i<LL_ARRAY_SIZE(stateNames); ++i) - { - LLButton *button = getChild<LLButton>(stateNames[i]+"_btn"); - - if (i == mState) - { - button->setEnabled(TRUE); - button->setToggleState(TRUE); - } - else if (i <= mLastEnabledState) - { - button->setEnabled(TRUE); - button->setToggleState(FALSE); - } - else - { - button->setEnabled(FALSE); - } - } -} - -void LLFloaterModelWizard::onClickSwitchToAdvanced() -{ - LLFloaterModelPreview* floater_preview = LLFloaterReg::getTypedInstance<LLFloaterModelPreview>("upload_model"); - if (!floater_preview) - { - llwarns << "FLoater model preview not found." << llendl; - return; - } - - // Open floater model preview - floater_preview->openFloater(); - - // Close the wizard - closeFloater(); - - std::string filename = getChild<LLUICtrl>("lod_file")->getValue().asString(); - if (!filename.empty()) - { - // Re-load the model to the floater model preview if it has been loaded - // into the wizard. - floater_preview->loadModel(3, filename); - } -} - -void LLFloaterModelWizard::onClickRecalculateGeometry() -{ - S32 val = getChild<LLUICtrl>("accuracy_slider")->getValue().asInteger(); - - mModelPreview->genLODs(-1, NUM_LOD - val); - - mModelPreview->refresh(); -} - -void LLFloaterModelWizard::onClickRecalculatePhysics() -{ - // Hide the "Recalculate physics" button and show the "Recalculating..." - // button instead. - swap_controls(mRecalculatePhysicsBtn, mRecalculatingPhysicsBtn, false); - - executePhysicsStage("Decompose"); -} - -void LLFloaterModelWizard::onClickCalculateUploadFee() -{ - swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, false); - - mModelPreview->rebuildUploadData(); - - mUploadModelUrl.clear(); - - gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale, - true, false, false, mUploadModelUrl, false, getWholeModelFeeObserverHandle()); -} - -void LLFloaterModelWizard::loadModel() -{ - mModelPreview->mLoading = TRUE; - - (new LLMeshFilePicker(mModelPreview, 3))->getFile(); -} - -void LLFloaterModelWizard::onClickCancel() -{ - closeFloater(); -} - -void LLFloaterModelWizard::onClickBack() -{ - setState(llmax((int) CHOOSE_FILE, mState-1)); -} - -void LLFloaterModelWizard::onClickNext() -{ - setState(llmin((int) UPLOAD, mState+1)); -} - -bool LLFloaterModelWizard::onEnableNext() -{ - return true; -} - -bool LLFloaterModelWizard::onEnableBack() -{ - return true; -} - - -//----------------------------------------------------------------------------- -// handleMouseDown() -//----------------------------------------------------------------------------- -BOOL LLFloaterModelWizard::handleMouseDown(S32 x, S32 y, MASK mask) -{ - if (mPreviewRect.pointInRect(x, y)) - { - bringToFront( x, y ); - gFocusMgr.setMouseCapture(this); - gViewerWindow->hideCursor(); - mLastMouseX = x; - mLastMouseY = y; - return TRUE; - } - - return LLFloater::handleMouseDown(x, y, mask); -} - -//----------------------------------------------------------------------------- -// handleMouseUp() -//----------------------------------------------------------------------------- -BOOL LLFloaterModelWizard::handleMouseUp(S32 x, S32 y, MASK mask) -{ - gFocusMgr.setMouseCapture(FALSE); - gViewerWindow->showCursor(); - return LLFloater::handleMouseUp(x, y, mask); -} - -//----------------------------------------------------------------------------- -// handleHover() -//----------------------------------------------------------------------------- -BOOL LLFloaterModelWizard::handleHover (S32 x, S32 y, MASK mask) -{ - MASK local_mask = mask & ~MASK_ALT; - - if (mModelPreview && hasMouseCapture()) - { - if (local_mask == MASK_PAN) - { - // pan here - mModelPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); - } - else if (local_mask == MASK_ORBIT) - { - F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; - F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f; - - mModelPreview->rotate(yaw_radians, pitch_radians); - } - else - { - - F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; - F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f; - - mModelPreview->rotate(yaw_radians, 0.f); - mModelPreview->zoom(zoom_amt); - } - - - mModelPreview->refresh(); - - LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY); - } - - if (!mPreviewRect.pointInRect(x, y) || !mModelPreview) - { - return LLFloater::handleHover(x, y, mask); - } - else if (local_mask == MASK_ORBIT) - { - gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA); - } - else if (local_mask == MASK_PAN) - { - gViewerWindow->setCursor(UI_CURSOR_TOOLPAN); - } - else - { - gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN); - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// handleScrollWheel() -//----------------------------------------------------------------------------- -BOOL LLFloaterModelWizard::handleScrollWheel(S32 x, S32 y, S32 clicks) -{ - if (mPreviewRect.pointInRect(x, y) && mModelPreview) - { - mModelPreview->zoom((F32)clicks * -0.2f); - mModelPreview->refresh(); - } - - return TRUE; -} - - -void LLFloaterModelWizard::initDecompControls() -{ - LLSD key; - - static const LLCDStageData* stage = NULL; - static S32 stage_count = 0; - - if (!stage && LLConvexDecomposition::getInstance() != NULL) - { - stage_count = LLConvexDecomposition::getInstance()->getStages(&stage); - } - - static const LLCDParam* param = NULL; - static S32 param_count = 0; - if (!param && LLConvexDecomposition::getInstance() != NULL) - { - param_count = LLConvexDecomposition::getInstance()->getParameters(¶m); - } - - for (S32 j = stage_count-1; j >= 0; --j) - { - gMeshRepo.mDecompThread->mStageID[stage[j].mName] = j; - // protected against stub by stage_count being 0 for stub above - LLConvexDecomposition::getInstance()->registerCallback(j, LLPhysicsDecomp::llcdCallback); - - for (S32 i = 0; i < param_count; ++i) - { - if (param[i].mStage != j) - { - continue; - } - - std::string name(param[i].mName ? param[i].mName : ""); - std::string description(param[i].mDescription ? param[i].mDescription : ""); - - if (param[i].mType == LLCDParam::LLCD_FLOAT) - { - mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mFloat); - } - else if (param[i].mType == LLCDParam::LLCD_INTEGER) - { - mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue); - } - else if (param[i].mType == LLCDParam::LLCD_BOOLEAN) - { - mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mBool); - } - else if (param[i].mType == LLCDParam::LLCD_ENUM) - { - mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue); - } - } - } - - mDecompParams["Simplify Method"] = 0; // set it to retain % -} - -/*virtual*/ -void LLFloaterModelWizard::onPermissionsReceived(const LLSD& result) -{ - std::string upload_status = result["mesh_upload_status"].asString(); - // BAP HACK: handle "" for case that MeshUploadFlag cap is broken. - mHasUploadPerm = (("" == upload_status) || ("valid" == upload_status)); - - getChildView("warning_label")->setVisible(!mHasUploadPerm); - getChildView("warning_text")->setVisible(!mHasUploadPerm); -} - -/*virtual*/ -void LLFloaterModelWizard::setPermissonsErrorStatus(U32 status, const std::string& reason) -{ - llwarns << "LLFloaterModelWizard::setPermissonsErrorStatus(" << status << " : " << reason << ")" << llendl; -} - -/*virtual*/ -void LLFloaterModelWizard::onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) -{ - swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, true); - - // Enable the "Upload" buton if we have calculated the upload fee - // and have the permission to upload. - getChildView("upload")->setEnabled(mHasUploadPerm); - - mUploadModelUrl = upload_url; - - S32 fee = result["upload_price"].asInteger(); - childSetTextArg("review_fee", "[FEE]", llformat("%d", fee)); - childSetTextArg("charged_fee", "[FEE]", llformat("%d", fee)); - - setState(REVIEW); -} - -/*virtual*/ -void LLFloaterModelWizard::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) -{ - swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, true); - - // Disable the "Review" step if it has been previously enabled. - modelChangedCallback(); - - llwarns << "LLFloaterModelWizard::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << llendl; - - setState(PHYSICS); -} - -/*virtual*/ -void LLFloaterModelWizard::onModelUploadSuccess() -{ - // success! - setState(UPLOAD); -} - -/*virtual*/ -void LLFloaterModelWizard::onModelUploadFailure() -{ - // Failure. Make the user recalculate fees - setState(PHYSICS); - // Disable the "Review" step if it has been previously enabled. - if (mLastEnabledState > PHYSICS) - { - mLastEnabledState = PHYSICS; - } - - updateButtons(); -} - -//static -void LLFloaterModelWizard::executePhysicsStage(std::string stage_name) -{ - if (sInstance) - { - // Invert the slider value so that "performance" end is giving the least detailed physics, - // and the "accuracy" end is giving the most detailed physics - F64 physics_accuracy = 1 - sInstance->getChild<LLSliderCtrl>("physics_slider")->getValue().asReal(); - - sInstance->mDecompParams["Retain%"] = physics_accuracy; - - if (!sInstance->mCurRequest.empty()) - { - llinfos << "Decomposition request still pending." << llendl; - return; - } - - if (sInstance->mModelPreview) - { - for (S32 i = 0; i < sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS].size(); ++i) - { - LLModel* mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][i]; - DecompRequest* request = new DecompRequest(stage_name, mdl); - if(request->isValid()) - { - sInstance->mCurRequest.insert(request); - gMeshRepo.mDecompThread->submitRequest(request); - } - } - } - } -} - -LLFloaterModelWizard::DecompRequest::DecompRequest(const std::string& stage, LLModel* mdl) -{ - mStage = stage; - mContinue = 1; - mModel = mdl; - mDecompID = &mdl->mDecompID; - mParams = sInstance->mDecompParams; - - //copy out positions and indices - assignData(mdl) ; -} - - -S32 LLFloaterModelWizard::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2) -{ - setStatusMessage(llformat("%s: %d/%d", status, p1, p2)); - - return mContinue; -} - -void LLFloaterModelWizard::DecompRequest::completed() -{ //called from the main thread - mModel->setConvexHullDecomposition(mHull); - - if (sInstance) - { - if (sInstance->mModelPreview) - { - sInstance->mModelPreview->mDirty = true; - LLFloaterModelWizard::sInstance->mModelPreview->refresh(); - } - - sInstance->mCurRequest.erase(this); - } - - if (mStage == "Decompose") - { - executePhysicsStage("Simplify"); - } - else - { - // Decomp request is complete so we can enable the "Recalculate physics" button again. - swap_controls(sInstance->mRecalculatePhysicsBtn, sInstance->mRecalculatingPhysicsBtn, true); - } -} - - -BOOL LLFloaterModelWizard::postBuild() -{ - childSetValue("import_scale", (F32) 0.67335826); - - getChild<LLUICtrl>("browse")->setCommitCallback(boost::bind(&LLFloaterModelWizard::loadModel, this)); - //getChild<LLUICtrl>("lod_file")->setCommitCallback(boost::bind(&LLFloaterModelWizard::loadModel, this)); - getChild<LLUICtrl>("cancel")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCancel, this)); - getChild<LLUICtrl>("close")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCancel, this)); - getChild<LLUICtrl>("back")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickBack, this)); - getChild<LLUICtrl>("next")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickNext, this)); - getChild<LLUICtrl>("preview_lod_combo")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPreviewLODCommit, this, _1)); - getChild<LLUICtrl>("preview_lod_combo2")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPreviewLODCommit, this, _1)); - getChild<LLUICtrl>("upload")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onUpload, this)); - getChild<LLUICtrl>("switch_to_advanced")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickSwitchToAdvanced, this)); - - mRecalculateGeometryBtn = getChild<LLButton>("recalculate_geometry_btn"); - mRecalculateGeometryBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickRecalculateGeometry, this)); - - mRecalculatePhysicsBtn = getChild<LLButton>("recalculate_physics_btn"); - mRecalculatePhysicsBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickRecalculatePhysics, this)); - - mRecalculatingPhysicsBtn = getChild<LLButton>("recalculating_physics_btn"); - - mCalculateWeightsBtn = getChild<LLButton>("calculate"); - mCalculateWeightsBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCalculateUploadFee, this)); - - mCalculatingWeightsBtn = getChild<LLButton>("calculating"); - - mChooseFilePreviewPanel = getChild<LLView>("choose_file_preview_panel"); - mOptimizePreviewPanel = getChild<LLView>("optimize_preview_panel"); - mPhysicsPreviewPanel = getChild<LLView>("physics_preview_panel"); - - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - - enable_registrar.add("Next.OnEnable", boost::bind(&LLFloaterModelWizard::onEnableNext, this)); - enable_registrar.add("Back.OnEnable", boost::bind(&LLFloaterModelWizard::onEnableBack, this)); - - mModelPreview = new LLModelPreview(512, 512, this); - mModelPreview->setPreviewTarget(16.f); - mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelWizard::setDetails, this, _1, _2, _3, _4, _5)); - mModelPreview->setModelLoadedCallback(boost::bind(&LLFloaterModelWizard::modelLoadedCallback, this)); - mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelWizard::modelChangedCallback, this)); - mModelPreview->mViewOption["show_textures"] = true; - - center(); - - setState(CHOOSE_FILE); - - childSetTextArg("import_dimensions", "[X]", LLStringUtil::null); - childSetTextArg("import_dimensions", "[Y]", LLStringUtil::null); - childSetTextArg("import_dimensions", "[Z]", LLStringUtil::null); - - initDecompControls(); - - requestAgentUploadPermissions(); - - return TRUE; -} - - -void LLFloaterModelWizard::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost) -{ - // iterate through all the panels, setting the dimensions - for(size_t t=0; t<LL_ARRAY_SIZE(stateNames); ++t) - { - LLPanel *panel = getChild<LLPanel>(stateNames[t]+"_panel"); - if (panel) - { - panel->childSetText("dimension_x", llformat("%.1f", x)); - panel->childSetText("dimension_y", llformat("%.1f", y)); - panel->childSetText("dimension_z", llformat("%.1f", z)); - } - } - - childSetTextArg("review_prim_equiv", "[EQUIV]", llformat("%d", mModelPreview->mResourceCost)); -} - -void LLFloaterModelWizard::modelLoadedCallback() -{ - mLastEnabledState = CHOOSE_FILE; - updateButtons(); -} - -void LLFloaterModelWizard::modelChangedCallback() -{ - // Don't allow to proceed to the "Review" step if the model has changed - // but the new upload fee hasn't been calculated yet. - if (mLastEnabledState > PHYSICS) - { - mLastEnabledState = PHYSICS; - } - - getChildView("upload")->setEnabled(false); - - updateButtons(); -} - -void LLFloaterModelWizard::onUpload() -{ - mModelPreview->rebuildUploadData(); - - gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale, - true, false, false, mUploadModelUrl, true, - LLHandle<LLWholeModelFeeObserver>(), getWholeModelUploadObserverHandle()); -} - -void LLFloaterModelWizard::onPreviewLODCommit(LLUICtrl* ctrl) -{ - if (!mModelPreview) - { - return; - } - - S32 which_mode = 0; - - LLComboBox* combo = (LLComboBox*) ctrl; - - which_mode = (NUM_LOD-1)-combo->getFirstSelectedIndex(); // combo box list of lods is in reverse order - - mModelPreview->setPreviewLOD(which_mode); -} - -void LLFloaterModelWizard::refresh() -{ - if (mState == CHOOSE_FILE) - { - bool model_loaded = false; - - if (mModelPreview && mModelPreview->getLoadState() == LLModelLoader::DONE) - { - model_loaded = true; - } - - getChildView("next")->setEnabled(model_loaded); - } -} - -void LLFloaterModelWizard::draw() -{ - refresh(); - - LLFloater::draw(); - - if (mModelPreview && mState < REVIEW) - { - mModelPreview->update(); - - gGL.color3f(1.f, 1.f, 1.f); - - gGL.getTexUnit(0)->bind(mModelPreview); - - gGL.begin( LLRender::QUADS ); - { - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mBottom); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mBottom); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mTop); - } - gGL.end(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } -} - -// static -void swap_controls(LLUICtrl* first_ctrl, LLUICtrl* second_ctrl, bool first_ctr_visible) -{ - first_ctrl->setVisible(first_ctr_visible); - second_ctrl->setVisible(!first_ctr_visible); -} diff --git a/indra/newview/llfloatermodelwizard.h b/indra/newview/llfloatermodelwizard.h deleted file mode 100644 index db9b605777..0000000000 --- a/indra/newview/llfloatermodelwizard.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file llfloatermodelwizard.h - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LLFLOATERMODELWIZARD_H -#define LLFLOATERMODELWIZARD_H - - -#include "llmeshrepository.h" -#include "llmodel.h" -#include "llthread.h" -#include "llfloatermodeluploadbase.h" - - -class LLModelPreview; - - -class LLFloaterModelWizard : public LLFloaterModelUploadBase -{ -public: - - class DecompRequest : public LLPhysicsDecomp::Request - { - public: - S32 mContinue; - LLPointer<LLModel> mModel; - - DecompRequest(const std::string& stage, LLModel* mdl); - virtual S32 statusCallback(const char* status, S32 p1, S32 p2); - virtual void completed(); - - }; - - static LLFloaterModelWizard* sInstance; - - LLFloaterModelWizard(const LLSD& key); - virtual ~LLFloaterModelWizard(); - /*virtual*/ BOOL postBuild(); - void draw(); - void refresh(); - - BOOL handleMouseDown(S32 x, S32 y, MASK mask); - BOOL handleMouseUp(S32 x, S32 y, MASK mask); - BOOL handleHover(S32 x, S32 y, MASK mask); - BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - - void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost); - void modelLoadedCallback(); - void modelChangedCallback(); - void initDecompControls(); - - // shows warning message if agent has no permissions to upload model - /*virtual*/ void onPermissionsReceived(const LLSD& result); - - // called when error occurs during permissions request - /*virtual*/ void setPermissonsErrorStatus(U32 status, const std::string& reason); - - /*virtual*/ void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url); - - /*virtual*/ void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason); - - /*virtual*/ void onModelUploadSuccess(); - - /*virtual*/ void onModelUploadFailure(); - - const LLRect& getPreviewRect() const { return mPreviewRect; } - - LLPhysicsDecomp::decomp_params mDecompParams; - std::set<LLPointer<DecompRequest> > mCurRequest; - std::string mStatusMessage; - static void executePhysicsStage(std::string stage_name); - -private: - enum EWizardState - { - CHOOSE_FILE = 0, - OPTIMIZE, - PHYSICS, - REVIEW, - UPLOAD - }; - - void setState(int state); - void updateButtons(); - void onClickSwitchToAdvanced(); - void onClickRecalculateGeometry(); - void onClickRecalculatePhysics(); - void onClickCalculateUploadFee(); - void onClickCancel(); - void onClickBack(); - void onClickNext(); - bool onEnableNext(); - bool onEnableBack(); - void loadModel(); - void onPreviewLODCommit(LLUICtrl*); - void onUpload(); - - LLModelPreview* mModelPreview; - LLRect mPreviewRect; - int mState; - - S32 mLastMouseX; - S32 mLastMouseY; - - U32 mLastEnabledState; - - LLButton* mRecalculateGeometryBtn; - LLButton* mRecalculatePhysicsBtn; - LLButton* mRecalculatingPhysicsBtn; - LLButton* mCalculateWeightsBtn; - LLButton* mCalculatingWeightsBtn; - - LLView* mChooseFilePreviewPanel; - LLView* mOptimizePreviewPanel; - LLView* mPhysicsPreviewPanel; -}; - - -#endif diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 173b0e538c..5edd920c70 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -35,7 +35,7 @@ #include "llfloaterpreference.h" #include "message.h" - +#include "llfloaterautoreplacesettings.h" #include "llagent.h" #include "llavatarconstants.h" #include "llcheckboxctrl.h" @@ -346,7 +346,9 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.BlockList", boost::bind(&LLFloaterPreference::onClickBlockList, this)); mCommitCallbackRegistrar.add("Pref.Proxy", boost::bind(&LLFloaterPreference::onClickProxySettings, this)); mCommitCallbackRegistrar.add("Pref.TranslationSettings", boost::bind(&LLFloaterPreference::onClickTranslationSettings, this)); - + mCommitCallbackRegistrar.add("Pref.AutoReplace", boost::bind(&LLFloaterPreference::onClickAutoReplace, this)); + mCommitCallbackRegistrar.add("Pref.SpellChecker", boost::bind(&LLFloaterPreference::onClickSpellChecker, this)); + sSkin = gSavedSettings.getString("SkinCurrent"); mCommitCallbackRegistrar.add("Pref.ClickActionChange", boost::bind(&LLFloaterPreference::onClickActionChange, this)); @@ -354,7 +356,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2)); - + LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); } @@ -435,6 +437,8 @@ BOOL LLFloaterPreference::postBuild() gSavedSettings.getControl("ChatBubbleOpacity")->getSignal()->connect(boost::bind(&LLFloaterPreference::onNameTagOpacityChange, this, _2)); + gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeMaturity, this)); + LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab"))) tabcontainer->selectFirstTab(); @@ -604,6 +608,9 @@ void LLFloaterPreference::cancel() // hide translation settings floater LLFloaterReg::hideInstance("prefs_translation"); + // hide translation settings floater + LLFloaterReg::hideInstance("prefs_autoreplace"); + // cancel hardware menu LLFloaterHardwareSettings* hardware_settings = LLFloaterReg::getTypedInstance<LLFloaterHardwareSettings>("prefs_hardware_settings"); if (hardware_settings) @@ -931,7 +938,6 @@ void LLFloaterPreference::refreshSkin(void* data) self->getChild<LLRadioGroup>("skin_selection", true)->setValue(sSkin); } - void LLFloaterPreference::buildPopupLists() { LLScrollListCtrl& disabled_popups = @@ -1515,6 +1521,16 @@ void LLFloaterPreference::onClickTranslationSettings() LLFloaterReg::showInstance("prefs_translation"); } +void LLFloaterPreference::onClickAutoReplace() +{ + LLFloaterReg::showInstance("prefs_autoreplace"); +} + +void LLFloaterPreference::onClickSpellChecker() +{ + LLFloaterReg::showInstance("prefs_spellchecker"); +} + void LLFloaterPreference::onClickActionChange() { mClickActionDirty = true; diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index ec5994e917..b71f7c647b 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -157,6 +157,8 @@ public: void onClickBlockList(); void onClickProxySettings(); void onClickTranslationSettings(); + void onClickAutoReplace(); + void onClickSpellChecker(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp new file mode 100644 index 0000000000..5ecdd11918 --- /dev/null +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -0,0 +1,491 @@ +/** + * @file llfloaterspellchecksettings.h + * @brief Spell checker settings floater + * +* $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llcombobox.h" +#include "llfilepicker.h" +#include "llfloaterreg.h" +#include "llfloaterspellchecksettings.h" +#include "llscrolllistctrl.h" +#include "llsdserialize.h" +#include "llspellcheck.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llnotificationsutil.h" + +#include <boost/algorithm/string.hpp> + +///---------------------------------------------------------------------------- +/// Class LLFloaterSpellCheckerSettings +///---------------------------------------------------------------------------- +LLFloaterSpellCheckerSettings::LLFloaterSpellCheckerSettings(const LLSD& key) + : LLFloater(key) +{ +} + +void LLFloaterSpellCheckerSettings::draw() +{ + LLFloater::draw(); + + std::vector<LLScrollListItem*> sel_items = getChild<LLScrollListCtrl>("spellcheck_available_list")->getAllSelected(); + bool enable_remove = !sel_items.empty(); + for (std::vector<LLScrollListItem*>::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) + { + enable_remove &= LLSpellChecker::canRemoveDictionary((*sel_it)->getValue().asString()); + } + getChild<LLUICtrl>("spellcheck_remove_btn")->setEnabled(enable_remove); +} + +BOOL LLFloaterSpellCheckerSettings::postBuild(void) +{ + gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaries, this, false)); + LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLFloaterSpellCheckerSettings::onSpellCheckSettingsChange, this)); + getChild<LLUICtrl>("spellcheck_remove_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnRemove, this)); + getChild<LLUICtrl>("spellcheck_import_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnImport, this)); + getChild<LLUICtrl>("spellcheck_main_combo")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaries, this, false)); + getChild<LLUICtrl>("spellcheck_moveleft_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_active_list", "spellcheck_available_list")); + getChild<LLUICtrl>("spellcheck_moveright_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_available_list", "spellcheck_active_list")); + center(); + return true; +} + +void LLFloaterSpellCheckerSettings::onBtnImport() +{ + LLFloaterReg::showInstance("prefs_spellchecker_import"); +} + +void LLFloaterSpellCheckerSettings::onBtnMove(const std::string& from, const std::string& to) +{ + LLScrollListCtrl* from_ctrl = findChild<LLScrollListCtrl>(from); + LLScrollListCtrl* to_ctrl = findChild<LLScrollListCtrl>(to); + + LLSD row; + row["columns"][0]["column"] = "name"; + + std::vector<LLScrollListItem*> sel_items = from_ctrl->getAllSelected(); + std::vector<LLScrollListItem*>::const_iterator sel_it; + for ( sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) + { + row["value"] = (*sel_it)->getValue(); + row["columns"][0]["value"] = (*sel_it)->getColumn(0)->getValue(); + to_ctrl->addElement(row); + to_ctrl->setSelectedByValue( (*sel_it)->getValue(), true ); + } + from_ctrl->deleteSelectedItems(); +} + +void LLFloaterSpellCheckerSettings::onClose(bool app_quitting) +{ + if (app_quitting) + { + // don't save anything + return; + } + LLFloaterReg::hideInstance("prefs_spellchecker_import"); + + std::list<std::string> list_dict; + + LLComboBox* dict_combo = findChild<LLComboBox>("spellcheck_main_combo"); + const std::string dict_name = dict_combo->getSelectedItemLabel(); + if (!dict_name.empty()) + { + list_dict.push_back(dict_name); + + LLScrollListCtrl* list_ctrl = findChild<LLScrollListCtrl>("spellcheck_active_list"); + std::vector<LLScrollListItem*> list_items = list_ctrl->getAllData(); + for (std::vector<LLScrollListItem*>::const_iterator item_it = list_items.begin(); item_it != list_items.end(); ++item_it) + { + const std::string language = (*item_it)->getValue().asString(); + if (LLSpellChecker::hasDictionary(language, true)) + { + list_dict.push_back(language); + } + } + } + gSavedSettings.setString("SpellCheckDictionary", boost::join(list_dict, ",")); +} + +void LLFloaterSpellCheckerSettings::onOpen(const LLSD& key) +{ + refreshDictionaries(true); +} + +void LLFloaterSpellCheckerSettings::onBtnRemove() +{ + std::vector<LLScrollListItem*> sel_items = getChild<LLScrollListCtrl>("spellcheck_available_list")->getAllSelected(); + for (std::vector<LLScrollListItem*>::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) + { + LLSpellChecker::instance().removeDictionary((*sel_it)->getValue().asString()); + } +} + +void LLFloaterSpellCheckerSettings::onSpellCheckSettingsChange() +{ + refreshDictionaries(true); +} + +void LLFloaterSpellCheckerSettings::refreshDictionaries(bool from_settings) +{ + bool enabled = gSavedSettings.getBOOL("SpellCheck"); + getChild<LLUICtrl>("spellcheck_moveleft_btn")->setEnabled(enabled); + getChild<LLUICtrl>("spellcheck_moveright_btn")->setEnabled(enabled); + + // Populate the dictionary combobox + LLComboBox* dict_combo = findChild<LLComboBox>("spellcheck_main_combo"); + std::string dict_cur = dict_combo->getSelectedItemLabel(); + if ((dict_cur.empty() || from_settings) && (LLSpellChecker::getUseSpellCheck())) + { + dict_cur = LLSpellChecker::instance().getPrimaryDictionary(); + } + dict_combo->clearRows(); + + const LLSD& dict_map = LLSpellChecker::getDictionaryMap(); + if (dict_map.size()) + { + for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it) + { + const LLSD& dict = *dict_it; + if ( (dict["installed"].asBoolean()) && (dict["is_primary"].asBoolean()) && (dict.has("language")) ) + { + dict_combo->add(dict["language"].asString()); + } + } + if (!dict_combo->selectByValue(dict_cur)) + { + dict_combo->clear(); + } + } + dict_combo->sortByName(); + dict_combo->setEnabled(enabled); + + // Populate the available and active dictionary list + LLScrollListCtrl* avail_ctrl = findChild<LLScrollListCtrl>("spellcheck_available_list"); + LLScrollListCtrl* active_ctrl = findChild<LLScrollListCtrl>("spellcheck_active_list"); + + LLSpellChecker::dict_list_t active_list; + if ( ((!avail_ctrl->getItemCount()) && (!active_ctrl->getItemCount())) || (from_settings) ) + { + if (LLSpellChecker::getUseSpellCheck()) + { + active_list = LLSpellChecker::instance().getSecondaryDictionaries(); + } + } + else + { + std::vector<LLScrollListItem*> active_items = active_ctrl->getAllData(); + for (std::vector<LLScrollListItem*>::const_iterator item_it = active_items.begin(); item_it != active_items.end(); ++item_it) + { + std::string dict = (*item_it)->getValue().asString(); + if (dict_cur != dict) + { + active_list.push_back(dict); + } + } + } + + LLSD row; + row["columns"][0]["column"] = "name"; + + active_ctrl->clearRows(); + active_ctrl->setEnabled(enabled); + for (LLSpellChecker::dict_list_t::const_iterator it = active_list.begin(); it != active_list.end(); ++it) + { + const std::string language = *it; + const LLSD dict = LLSpellChecker::getDictionaryData(language); + row["value"] = language; + row["columns"][0]["value"] = (!dict["user_installed"].asBoolean()) ? language : language + " " + LLTrans::getString("UserDictionary"); + active_ctrl->addElement(row); + } + active_ctrl->sortByColumnIndex(0, true); + active_list.push_back(dict_cur); + + avail_ctrl->clearRows(); + avail_ctrl->setEnabled(enabled); + for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it) + { + const LLSD& dict = *dict_it; + const std::string language = dict["language"].asString(); + if ( (dict["installed"].asBoolean()) && (active_list.end() == std::find(active_list.begin(), active_list.end(), language)) ) + { + row["value"] = language; + row["columns"][0]["value"] = (!dict["user_installed"].asBoolean()) ? language : language + " " + LLTrans::getString("UserDictionary"); + avail_ctrl->addElement(row); + } + } + avail_ctrl->sortByColumnIndex(0, true); +} + +///---------------------------------------------------------------------------- +/// Class LLFloaterSpellCheckerImport +///---------------------------------------------------------------------------- +LLFloaterSpellCheckerImport::LLFloaterSpellCheckerImport(const LLSD& key) + : LLFloater(key) +{ +} + +BOOL LLFloaterSpellCheckerImport::postBuild(void) +{ + getChild<LLUICtrl>("dictionary_path_browse")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnBrowse, this)); + getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnOK, this)); + getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnCancel, this)); + center(); + return true; +} + +void LLFloaterSpellCheckerImport::onBtnBrowse() +{ + LLFilePicker& file_picker = LLFilePicker::instance(); + if (!file_picker.getOpenFile(LLFilePicker::FFLOAD_DICTIONARY)) + { + return; + } + + std::string filepath = file_picker.getFirstFile(); + + const std::string extension = gDirUtilp->getExtension(filepath); + if ("xcu" == extension) + { + filepath = parseXcuFile(filepath); + if (filepath.empty()) + { + return; + } + } + + getChild<LLUICtrl>("dictionary_path")->setValue(filepath); + + mDictionaryDir = gDirUtilp->getDirName(filepath); + mDictionaryBasename = gDirUtilp->getBaseFileName(filepath, true); + getChild<LLUICtrl>("dictionary_name")->setValue(mDictionaryBasename); +} + +void LLFloaterSpellCheckerImport::onBtnCancel() +{ + closeFloater(false); +} + +void LLFloaterSpellCheckerImport::onBtnOK() +{ + const std::string dict_dic = mDictionaryDir + gDirUtilp->getDirDelimiter() + mDictionaryBasename + ".dic"; + const std::string dict_aff = mDictionaryDir + gDirUtilp->getDirDelimiter() + mDictionaryBasename + ".aff"; + std::string dict_language = getChild<LLUICtrl>("dictionary_language")->getValue().asString(); + LLStringUtil::trim(dict_language); + + bool imported = false; + if ( dict_language.empty() + || mDictionaryDir.empty() + || mDictionaryBasename.empty() + || ! gDirUtilp->fileExists(dict_dic) + ) + { + LLNotificationsUtil::add("SpellingDictImportRequired"); + } + else + { + std::string settings_dic = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".dic"; + if ( copyFile( dict_dic, settings_dic ) ) + { + if (gDirUtilp->fileExists(dict_aff)) + { + std::string settings_aff = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".aff"; + if (copyFile( dict_aff, settings_aff )) + { + imported = true; + } + else + { + LLSD args = LLSD::emptyMap(); + args["FROM_NAME"] = dict_aff; + args["TO_NAME"] = settings_aff; + LLNotificationsUtil::add("SpellingDictImportFailed", args); + } + } + else + { + LLSD args = LLSD::emptyMap(); + args["DIC_NAME"] = dict_dic; + LLNotificationsUtil::add("SpellingDictIsSecondary", args); + + imported = true; + } + } + else + { + LLSD args = LLSD::emptyMap(); + args["FROM_NAME"] = dict_dic; + args["TO_NAME"] = settings_dic; + LLNotificationsUtil::add("SpellingDictImportFailed", args); + } + } + + if ( imported ) + { + LLSD custom_dict_info; + custom_dict_info["is_primary"] = (bool)gDirUtilp->fileExists(dict_aff); + custom_dict_info["name"] = mDictionaryBasename; + custom_dict_info["language"] = dict_language; + + LLSD custom_dict_map; + llifstream custom_file_in(LLSpellChecker::getDictionaryUserPath() + "user_dictionaries.xml"); + if (custom_file_in.is_open()) + { + LLSDSerialize::fromXMLDocument(custom_dict_map, custom_file_in); + custom_file_in.close(); + } + + LLSD::array_iterator it = custom_dict_map.beginArray(); + for (; it != custom_dict_map.endArray(); ++it) + { + LLSD& dict_info = *it; + if (dict_info["name"].asString() == mDictionaryBasename) + { + dict_info = custom_dict_info; + break; + } + } + if (custom_dict_map.endArray() == it) + { + custom_dict_map.append(custom_dict_info); + } + + llofstream custom_file_out(LLSpellChecker::getDictionaryUserPath() + "user_dictionaries.xml", std::ios::trunc); + if (custom_file_out.is_open()) + { + LLSDSerialize::toPrettyXML(custom_dict_map, custom_file_out); + custom_file_out.close(); + } + + LLSpellChecker::refreshDictionaryMap(); + } + + closeFloater(false); +} + +bool LLFloaterSpellCheckerImport::copyFile(const std::string from, const std::string to) +{ + bool copied = false; + LLFILE* in = LLFile::fopen(from, "rb"); /* Flawfinder: ignore */ + if (in) + { + LLFILE* out = LLFile::fopen(to, "wb"); /* Flawfinder: ignore */ + if (out) + { + char buf[16384]; /* Flawfinder: ignore */ + size_t readbytes; + bool write_ok = true; + while(write_ok && (readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */ + { + if (fwrite(buf, 1, readbytes, out) != readbytes) + { + LL_WARNS("SpellCheck") << "Short write" << LL_ENDL; + write_ok = false; + } + } + if ( write_ok ) + { + copied = true; + } + fclose(out); + } + } + fclose(in); + return copied; +} + +std::string LLFloaterSpellCheckerImport::parseXcuFile(const std::string& file_path) const +{ + LLXMLNodePtr xml_root; + if ( (!LLUICtrlFactory::getLayeredXMLNode(file_path, xml_root)) || (xml_root.isNull()) ) + { + return LLStringUtil::null; + } + + // Bury down to the "Dictionaries" parent node + LLXMLNode* dict_node = NULL; + for (LLXMLNode* outer_node = xml_root->getFirstChild(); outer_node && !dict_node; outer_node = outer_node->getNextSibling()) + { + std::string temp; + if ( (outer_node->getAttributeString("oor:name", temp)) && ("ServiceManager" == temp) ) + { + for (LLXMLNode* inner_node = outer_node->getFirstChild(); inner_node && !dict_node; inner_node = inner_node->getNextSibling()) + { + if ( (inner_node->getAttributeString("oor:name", temp)) && ("Dictionaries" == temp) ) + { + dict_node = inner_node; + break; + } + } + } + } + + if (dict_node) + { + // Iterate over all child nodes until we find one that has a <value>DICT_SPELL</value> node + for (LLXMLNode* outer_node = dict_node->getFirstChild(); outer_node; outer_node = outer_node->getNextSibling()) + { + std::string temp; + LLXMLNodePtr location_node, format_node; + for (LLXMLNode* inner_node = outer_node->getFirstChild(); inner_node; inner_node = inner_node->getNextSibling()) + { + if (inner_node->getAttributeString("oor:name", temp)) + { + if ("Locations" == temp) + { + inner_node->getChild("value", location_node, false); + } + else if ("Format" == temp) + { + inner_node->getChild("value", format_node, false); + } + } + } + if ( (format_node.isNull()) || ("DICT_SPELL" != format_node->getValue()) || (location_node.isNull()) ) + { + continue; + } + + // Found a list of file locations, return the .dic (if present) + std::list<std::string> location_list; + boost::split(location_list, location_node->getValue(), boost::is_any_of(std::string(" "))); + for (std::list<std::string>::iterator it = location_list.begin(); it != location_list.end(); ++it) + { + std::string& location = *it; + if ("\\" != gDirUtilp->getDirDelimiter()) + LLStringUtil::replaceString(location, "\\", gDirUtilp->getDirDelimiter()); + else + LLStringUtil::replaceString(location, "/", gDirUtilp->getDirDelimiter()); + LLStringUtil::replaceString(location, "%origin%", gDirUtilp->getDirName(file_path)); + if ("dic" == gDirUtilp->getExtension(location)) + { + return location; + } + } + } + } + + return LLStringUtil::null; +} diff --git a/indra/newview/llfloaterspellchecksettings.h b/indra/newview/llfloaterspellchecksettings.h new file mode 100644 index 0000000000..eded3a9133 --- /dev/null +++ b/indra/newview/llfloaterspellchecksettings.h @@ -0,0 +1,68 @@ +/** + * @file llfloaterspellchecksettings.h + * @brief Spell checker settings floater + * +* $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERSPELLCHECKERSETTINGS_H +#define LLFLOATERSPELLCHECKERSETTINGS_H + +#include "llfloater.h" + +class LLFloaterSpellCheckerSettings : public LLFloater +{ +public: + LLFloaterSpellCheckerSettings(const LLSD& key); + + /*virtual*/ void draw(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); + +protected: + void onBtnImport(); + void onBtnMove(const std::string& from, const std::string& to); + void onBtnRemove(); + void onSpellCheckSettingsChange(); + void refreshDictionaries(bool from_settings); +}; + +class LLFloaterSpellCheckerImport : public LLFloater +{ +public: + LLFloaterSpellCheckerImport(const LLSD& key); + + /*virtual*/ BOOL postBuild(); + +protected: + void onBtnBrowse(); + void onBtnCancel(); + void onBtnOK(); + bool copyFile(const std::string from, const std::string to); + std::string parseXcuFile(const std::string& file_path) const; + + std::string mDictionaryDir; + std::string mDictionaryBasename; +}; + +#endif // LLFLOATERSPELLCHECKERSETTINGS_H diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 0965b7b533..7d047ec67e 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -562,7 +562,6 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) { width = scroll_rect.getWidth(); } - LLView::reshape(width, height, called_from_parent); mReshapeSignal(mSelectedItems, FALSE); } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f67464078b..63eedcdfea 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -56,7 +56,7 @@ #include "llrootview.h" #include "llspeakers.h" #include "llviewerchat.h" - +#include "llautoreplace.h" LLIMFloater::LLIMFloater(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id), @@ -255,6 +255,8 @@ BOOL LLIMFloater::postBuild() mInputEditor->setMaxTextLength(1023); // enable line history support for instant message bar mInputEditor->setEnableLineHistory(TRUE); + // *TODO Establish LineEditor with autoreplace callback + mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); LLFontGL* font = LLViewerChat::getChatFont(); mInputEditor->setFont(font); diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 93dd82957f..51df868faa 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -336,13 +336,19 @@ namespace LLMarketplaceImport // Interface class // +static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 1.0f; //static void LLMarketplaceInventoryImporter::update() { if (instanceExists()) { - LLMarketplaceInventoryImporter::instance().updateImport(); + static LLTimer update_timer; + if (update_timer.hasExpired()) + { + LLMarketplaceInventoryImporter::instance().updateImport(); + update_timer.setTimerExpirySec(MARKET_IMPORTER_UPDATE_FREQUENCY); + } } } diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 00ff81724c..f8f0f7d243 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -52,6 +52,7 @@ #include "lltranslate.h" #include "llresizehandle.h" +#include "llautoreplace.h" S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; @@ -89,6 +90,7 @@ BOOL LLNearbyChatBar::postBuild() { mChatBox = getChild<LLLineEditor>("chat_box"); + mChatBox->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); mChatBox->setCommitCallback(boost::bind(&LLNearbyChatBar::onChatBoxCommit, this)); mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 7c6287967a..16c51138a9 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -128,6 +128,8 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), SERVER_OBJECT_MESSAGE("ServerObjectMessage"), TELEPORT_OFFERED("TeleportOffered"), + TELEPORT_OFFERED_MATURITY_EXCEEDED("TeleportOffered_MaturityExceeded"), + TELEPORT_OFFERED_MATURITY_BLOCKED("TeleportOffered_MaturityBlocked"), TELEPORT_OFFER_SENT("TeleportOfferSent"), IM_SYSTEM_MESSAGE_TIP("IMSystemMessageTip"); @@ -149,6 +151,8 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) || INVENTORY_DECLINED == notification->getName() || USER_GIVE_ITEM == notification->getName() || TELEPORT_OFFERED == notification->getName() + || TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() + || TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName() || TELEPORT_OFFER_SENT == notification->getName() || IM_SYSTEM_MESSAGE_TIP == notification->getName(); } @@ -169,7 +173,9 @@ bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification) { return OFFER_FRIENDSHIP == notification->getName() || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); + || TELEPORT_OFFERED == notification->getName() + || TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() + || TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); } // static @@ -177,7 +183,9 @@ bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification) { return OFFER_FRIENDSHIP == notification->getName() || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); + || TELEPORT_OFFERED == notification->getName() + || TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() + || TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); } // static @@ -185,7 +193,9 @@ bool LLHandlerUtil::isNotificationReusable(const LLNotificationPtr& notification { return OFFER_FRIENDSHIP == notification->getName() || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); + || TELEPORT_OFFERED == notification->getName() + || TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() + || TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); } // static @@ -212,7 +222,9 @@ bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) if(OFFER_FRIENDSHIP == notification->getName() || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName()) + || TELEPORT_OFFERED == notification->getName() + || TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() + || TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName()) { // When ANY offer arrives, show toast, unless IM window is already open - EXT-5904 return ! isIMFloaterOpened(notification); diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index c01adc3c35..a50d9074f7 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -176,7 +176,7 @@ void LLPanelNearByMedia::handleMediaAutoPlayChanged(const LLSD& newvalue) { // update mParcelAudioAutoStart if AUTO_PLAY_MEDIA_SETTING changes mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) && - gSavedSettings.getBOOL("MediaTentativeAutoPlay"); + gSavedSettings.getBOOL("MediaTentativeAutoPlay"); } /*virtual*/ diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index 3baa1eccc8..70f3b5335e 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -129,22 +129,22 @@ void LLPolyMeshSharedData::freeMeshData() { mNumVertices = 0; - delete [] mBaseCoords; + ll_aligned_free_16(mBaseCoords); mBaseCoords = NULL; - delete [] mBaseNormals; + ll_aligned_free_16(mBaseNormals); mBaseNormals = NULL; - delete [] mBaseBinormals; + ll_aligned_free_16(mBaseBinormals); mBaseBinormals = NULL; - delete [] mTexCoords; + ll_aligned_free_16(mTexCoords); mTexCoords = NULL; - delete [] mDetailTexCoords; + ll_aligned_free_16(mDetailTexCoords); mDetailTexCoords = NULL; - delete [] mWeights; + ll_aligned_free_16(mWeights); mWeights = NULL; } @@ -229,17 +229,18 @@ U32 LLPolyMeshSharedData::getNumKB() BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) { U32 i; - mBaseCoords = new LLVector4a[ numVertices ]; - mBaseNormals = new LLVector4a[ numVertices ]; - mBaseBinormals = new LLVector4a[ numVertices ]; - mTexCoords = new LLVector2[ numVertices ]; - mDetailTexCoords = new LLVector2[ numVertices ]; - mWeights = new F32[ numVertices ]; + mBaseCoords = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mBaseNormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mBaseBinormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mWeights = (F32*) ll_aligned_malloc_16(numVertices*sizeof(F32)); for (i = 0; i < numVertices; i++) { mBaseCoords[i].clear(); mBaseNormals[i].clear(); mBaseBinormals[i].clear(); + mTexCoords[i].clear(); mWeights[i] = 0.f; } mNumVertices = numVertices; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index bd335576ba..86de80b47d 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -530,6 +530,7 @@ void LLSpatialGroup::setVisible() void LLSpatialGroup::validate() { + ll_assert_aligned(this,64); #if LL_OCTREE_PARANOIA_CHECK sg_assert(!isState(DIRTY)); @@ -1199,6 +1200,8 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mCurUpdatingSlotp(NULL), mCurUpdatingTexture (NULL) { + ll_assert_aligned(this,16); + sNodeCount++; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -4196,6 +4199,7 @@ public: { llerrs << "Face texture index incorrect." << llendl; } + } } } } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index e82c50b92b..f050df2b39 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -68,6 +68,16 @@ protected: ~LLDrawInfo(); public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLDrawInfo(const LLDrawInfo& rhs) { @@ -106,7 +116,7 @@ public: F32 mPartSize; F32 mVSize; LLSpatialGroup* mGroup; - LLFace* mFace; //associated face + LL_ALIGN_16(LLFace* mFace); //associated face F32 mDistance; U32 mDrawMode; @@ -181,7 +191,7 @@ public: }; }; -LL_ALIGN_PREFIX(64) +LL_ALIGN_PREFIX(16) class LLSpatialGroup : public LLOctreeListener<LLDrawable> { friend class LLSpatialPartition; @@ -193,6 +203,16 @@ public: *this = rhs; } + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + const LLSpatialGroup& operator=(const LLSpatialGroup& rhs) { llerrs << "Illegal operation!" << llendl; @@ -375,12 +395,12 @@ public: V4_COUNT = 10 } eV4Index; - LLVector4a mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects) - LLVector4a mExtents[2]; // extents (min, max) of this node and all its children - LLVector4a mObjectExtents[2]; // extents (min, max) of objects in this node - LLVector4a mObjectBounds[2]; // bounding box (center, size) of objects in this node - LLVector4a mViewAngle; - LLVector4a mLastUpdateViewAngle; + LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) + LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children + LL_ALIGN_16(LLVector4a mObjectExtents[2]); // extents (min, max) of objects in this node + LL_ALIGN_16(LLVector4a mObjectBounds[2]); // bounding box (center, size) of objects in this node + LL_ALIGN_16(LLVector4a mViewAngle); + LL_ALIGN_16(LLVector4a mLastUpdateViewAngle); F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3() diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 6b0fc26db7..ee7a234bbe 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -740,6 +740,7 @@ bool idle_startup() { display_startup(); initialize_edit_menu(); + initialize_spellcheck_menu(); display_startup(); init_menus(); display_startup(); @@ -3215,17 +3216,6 @@ bool process_login_success_response() gSavedSettings.setU32("PreferredMaturity", preferredMaturity); } - // During the AO transition, this flag will be true. Then the flag will - // go away. After the AO transition, this code and all the code that - // uses it can be deleted. - text = response["ao_transition"].asString(); - if (!text.empty()) - { - if (text == "1") - { - gAgent.setAOTransition(); - } - } text = response["start_location"].asString(); if(!text.empty()) diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 6703ef4a41..ec36cf48c2 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -819,7 +819,10 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem mNoCopyTextureSelected = FALSE; if (itemp) { - mTextureSelectedCallback(itemp); + if (!mTextureSelectedCallback.empty()) + { + mTextureSelectedCallback(itemp); + } if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) { mNoCopyTextureSelected = TRUE; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 425bf7ee87..52d085dd2c 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -510,7 +510,7 @@ void LLGLTexMemBar::draw() F32 discard_bias = LLViewerTexture::sDesiredDiscardBias; F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ; F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ; - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); + S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f); F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024); F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024); diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index a473ee7ce0..d629f3abac 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -457,7 +457,7 @@ button_name_set_t getButtonDisableList(const std::string& notification_name, con { search_map = user_give_item_disable_map; } - else if("TeleportOffered" == notification_name) + else if(("TeleportOffered" == notification_name) || ("TeleportOffered_MaturityExceeded" == notification_name)) { search_map = teleport_offered_disable_map; } diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp index bf1f8808a7..cbd16e873d 100644 --- a/indra/newview/lltracker.cpp +++ b/indra/newview/lltracker.cpp @@ -251,7 +251,7 @@ void LLTracker::render3D() instance()->mBeaconText->setDoFade(FALSE); } - F32 dist = gFloaterWorldMap->getDistanceToDestination(instance()->mTrackedPositionGlobal, 0.0f); + F32 dist = gFloaterWorldMap->getDistanceToDestination(instance()->getTrackedPositionGlobal(), 0.0f); if (dist < DESTINATION_REACHED_RADIUS) { instance()->stopTrackingAvatar(); diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 2447f5dea8..8d8c401dac 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -41,6 +41,7 @@ #include "llstartup.h" #include "llviewerparcelmgr.h" #include "llparcel.h" +#include "llviewermessage.h" ///////////////////////////////////////////////////////// @@ -49,15 +50,22 @@ LLViewerAudio::LLViewerAudio() : mFadeState(FADE_IDLE), mFadeTime(), mIdleListnerActive(false), - mForcedTeleportFade(false) + mForcedTeleportFade(false), + mWasPlaying(false) { mTeleportFailedConnection = LLViewerParcelMgr::getInstance()-> setTeleportFailedCallback(boost::bind(&LLViewerAudio::onTeleportFailed, this)); + mTeleportFinishedConnection = LLViewerParcelMgr::getInstance()-> + setTeleportFinishedCallback(boost::bind(&LLViewerAudio::onTeleportFinished, this, _1, _2)); + mTeleportStartedConnection = LLViewerMessage::getInstance()-> + setTeleportStartedCallback(boost::bind(&LLViewerAudio::onTeleportStarted, this)); } LLViewerAudio::~LLViewerAudio() { mTeleportFailedConnection.disconnect(); + mTeleportFinishedConnection.disconnect(); + mTeleportStartedConnection.disconnect(); } void LLViewerAudio::registerIdleListener() @@ -67,7 +75,6 @@ void LLViewerAudio::registerIdleListener() mIdleListnerActive = true; doOnIdleRepeating(boost::bind(boost::bind(&LLViewerAudio::onIdleUpdate, this))); } - } void LLViewerAudio::startInternetStreamWithAutoFade(std::string streamURI) @@ -245,16 +252,54 @@ F32 LLViewerAudio::getFadeVolume() return fade_volume; } +void LLViewerAudio::onTeleportStarted() +{ + if (!LLViewerAudio::getInstance()->getForcedTeleportFade()) + { + // Even though the music was turned off it was starting up (with autoplay disabled) occasionally + // after a failed teleport or after an intra-parcel teleport. Also, the music sometimes was not + // restarting after a successful intra-parcel teleport. Setting mWasPlaying fixes these issues. + LLViewerAudio::getInstance()->setWasPlaying(!gAudiop->getInternetStreamURL().empty()); + LLViewerAudio::getInstance()->setForcedTeleportFade(true); + LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null); + LLViewerAudio::getInstance()->setNextStreamURI(LLStringUtil::null); + } +} + void LLViewerAudio::onTeleportFailed() { - if (gAudiop) + // Calling audio_update_volume makes sure that the music stream is properly set to be restored to + // its previous value + audio_update_volume(false); + + if (gAudiop && mWasPlaying) + { + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (parcel) + { + mNextStreamURI = parcel->getMusicURL(); + llinfos << "Teleport failed -- setting music stream to " << mNextStreamURI << llendl; + } + } + mWasPlaying = false; +} + +void LLViewerAudio::onTeleportFinished(const LLVector3d& pos, const bool& local) +{ + // Calling audio_update_volume makes sure that the music stream is properly set to be restored to + // its previous value + audio_update_volume(false); + + if (gAudiop && local && mWasPlaying) { LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if (parcel) { mNextStreamURI = parcel->getMusicURL(); + llinfos << "Intraparcel teleport -- setting music stream to " << mNextStreamURI << llendl; } } + mWasPlaying = false; } void init_audio() @@ -360,15 +405,9 @@ void audio_update_volume(bool force_update) // Streaming Music if (gAudiop) { - if (progress_view_visible && !LLViewerAudio::getInstance()->getForcedTeleportFade()) - { - LLViewerAudio::getInstance()->setForcedTeleportFade(true); - LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null); - LLViewerAudio::getInstance()->setNextStreamURI(LLStringUtil::null); - } - - if (!progress_view_visible && LLViewerAudio::getInstance()->getForcedTeleportFade() == true) + if (!progress_view_visible && LLViewerAudio::getInstance()->getForcedTeleportFade()) { + LLViewerAudio::getInstance()->setWasPlaying(!gAudiop->getInternetStreamURL().empty()); LLViewerAudio::getInstance()->setForcedTeleportFade(false); } diff --git a/indra/newview/llvieweraudio.h b/indra/newview/llvieweraudio.h index a3da9fc6b8..8c302c6549 100644 --- a/indra/newview/llvieweraudio.h +++ b/indra/newview/llvieweraudio.h @@ -66,6 +66,7 @@ public: bool getForcedTeleportFade() { return mForcedTeleportFade; }; void setForcedTeleportFade(bool fade) { mForcedTeleportFade = fade;} ; void setNextStreamURI(std::string stream) { mNextStreamURI = stream; } ; + void setWasPlaying(bool playing) { mWasPlaying = playing;} ; private: @@ -76,13 +77,17 @@ private: LLFrameTimer stream_fade_timer; bool mIdleListnerActive; bool mForcedTeleportFade; + bool mWasPlaying; boost::signals2::connection mTeleportFailedConnection; + boost::signals2::connection mTeleportFinishedConnection; + boost::signals2::connection mTeleportStartedConnection; void registerIdleListener(); void deregisterIdleListener() { mIdleListnerActive = false; }; void startFading(); void onTeleportFailed(); - + void onTeleportFinished(const LLVector3d& pos, const bool& local); + void onTeleportStarted(); }; #endif //LL_VIEWER_H diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 184033de42..b857c7fe89 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -51,9 +51,19 @@ const BOOL NOT_FOR_SELECTION = FALSE; extern template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInstance(); #endif +LL_ALIGN_PREFIX(16) class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera> { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } typedef enum { @@ -137,6 +147,7 @@ protected: S16 mZoomSubregion; public: -}; +} LL_ALIGN_POSTFIX(16); + #endif // LL_LLVIEWERCAMERA_H diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 0d361a2646..dec1615246 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -71,8 +71,12 @@ #include "llpaneloutfitsinventory.h" #include "llpanellogin.h" #include "llpaneltopinfobar.h" +#include "llspellcheck.h" #include "llupdaterservice.h" +// Third party library includes +#include <boost/algorithm/string.hpp> + #ifdef TOGGLE_HACKED_GODLIKE_VIEWER BOOL gHackGodmode = FALSE; #endif @@ -337,15 +341,6 @@ static bool handleUploadBakedTexOldChanged(const LLSD& newvalue) } -static bool handleNumpadControlChanged(const LLSD& newvalue) -{ - if (gKeyboard) - { - gKeyboard->setNumpadDistinct(static_cast<LLKeyboard::e_numpad_distinct>(newvalue.asInteger())); - } - return true; -} - static bool handleWLSkyDetailChanged(const LLSD&) { if (gSky.mVOWLSkyp.notNull()) @@ -501,6 +496,25 @@ bool handleForceShowGrid(const LLSD& newvalue) return true; } +bool handleSpellCheckChanged() +{ + if (gSavedSettings.getBOOL("SpellCheck")) + { + std::list<std::string> dict_list; + std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary"); + boost::split(dict_list, dict_setting, boost::is_any_of(std::string(","))); + if (!dict_list.empty()) + { + LLSpellChecker::setUseSpellCheck(dict_list.front()); + dict_list.pop_front(); + LLSpellChecker::instance().setSecondaryDictionaries(dict_list); + return true; + } + } + LLSpellChecker::setUseSpellCheck(LLStringUtil::null); + return true; +} + bool toggle_agent_pause(const LLSD& newvalue) { if ( newvalue.asBoolean() ) @@ -637,7 +651,6 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderUseStreamVBO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderPreferStreamDraw")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _2)); - gSavedSettings.getControl("NumpadControl")->getSignal()->connect(boost::bind(&handleNumpadControlChanged, _2)); gSavedSettings.getControl("JoystickAxis0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); gSavedSettings.getControl("JoystickAxis1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); gSavedSettings.getControl("JoystickAxis2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); @@ -706,6 +719,8 @@ void settings_setup_listeners() gSavedSettings.getControl("UpdaterServiceSetting")->getSignal()->connect(boost::bind(&toggle_updater_service_active, _2)); gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2)); gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2)); + gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); + gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); } #if TEST_CACHED_CONTROL diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 0ad2a6eb9b..fc5a2809b8 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -394,15 +394,24 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) const std::string& message = gAgent.getTeleportMessage(); switch( gAgent.getTeleportState() ) { + case LLAgent::TELEPORT_PENDING: + gTeleportDisplayTimer.reset(); + gViewerWindow->setShowProgress(TRUE); + gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); + gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["pending"]); + gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["pending"]); + break; + case LLAgent::TELEPORT_START: // Transition to REQUESTED. Viewer has sent some kind // of TeleportRequest to the source simulator gTeleportDisplayTimer.reset(); gViewerWindow->setShowProgress(TRUE); - gViewerWindow->setProgressPercent(0); + gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["requesting"]); + gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index d0e0d0d826..96303151f4 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -30,7 +30,7 @@ #include "llfloaterreg.h" #include "llviewerfloaterreg.h" - +#include "llfloaterautoreplacesettings.h" #include "llcompilequeue.h" #include "llcallfloater.h" #include "llfasttimerview.h" @@ -78,7 +78,6 @@ #include "llfloaterlandholdings.h" #include "llfloatermap.h" #include "llfloatermemleak.h" -#include "llfloatermodelwizard.h" #include "llfloaternamedesc.h" #include "llfloaternotificationsconsole.h" #include "llfloaterobjectweights.h" @@ -100,6 +99,7 @@ #include "llfloatersidepanelcontainer.h" #include "llfloatersnapshot.h" #include "llfloatersounddevices.h" +#include "llfloaterspellchecksettings.h" #include "llfloatertelehub.h" #include "llfloatertestinspectors.h" #include "llfloatertestlistview.h" @@ -254,7 +254,10 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>); LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHardwareSettings>); + LLFloaterReg::add("prefs_spellchecker_import", "floater_spellcheck_import.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerImport>); LLFloaterReg::add("prefs_translation", "floater_translation_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTranslationSettings>); + LLFloaterReg::add("prefs_spellchecker", "floater_spellcheck.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerSettings>); + LLFloaterReg::add("prefs_autoreplace", "floater_autoreplace.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAutoReplaceSettings>); LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerms>); LLFloaterReg::add("picks", "floater_picks.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>); @@ -304,7 +307,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload"); LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload"); LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelPreview>, "upload"); - LLFloaterReg::add("upload_model_wizard", "floater_model_wizard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelWizard>); LLFloaterReg::add("upload_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptPreview>, "upload"); LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload"); diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index f029ae5302..5d1aa870a3 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -729,8 +729,10 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w F32* vw = (F32*) vertex_weightsp.get(); F32* cw = (F32*) clothing_weightsp.get(); - LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), num_verts*2*sizeof(F32)); - LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), num_verts*sizeof(F32)); + S32 tc_size = (num_verts*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), tc_size); + S32 vw_size = (num_verts*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), vw_size); LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4*sizeof(F32)); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 34e916fec0..97ddfb48d2 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -86,6 +86,7 @@ #include "llrootview.h" #include "llsceneview.h" #include "llselectmgr.h" +#include "llspellcheckmenuhandler.h" #include "llstatusbar.h" #include "lltextureview.h" #include "lltoolcomp.h" @@ -300,7 +301,6 @@ BOOL enable_buy_land(void*); void handle_test_male(void *); void handle_test_female(void *); -void handle_toggle_pg(void*); void handle_dump_attachments(void *); void handle_dump_avatar_local_textures(void*); void handle_debug_avatar_textures(void*); @@ -1643,23 +1643,6 @@ class LLAdvancedTestFemale : public view_listener_t } }; - - -/////////////// -// TOGGLE PG // -/////////////// - - -class LLAdvancedTogglePG : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - handle_toggle_pg(NULL); - return true; - } -}; - - class LLAdvancedForceParamsToDefault : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -2039,7 +2022,6 @@ class LLAdvancedCompressImage : public view_listener_t }; - ///////////////////////// // SHOW DEBUG SETTINGS // ///////////////////////// @@ -5122,6 +5104,78 @@ class LLEditDelete : public view_listener_t } }; +void handle_spellcheck_replace_with_suggestion(const LLUICtrl* ctrl, const LLSD& param) +{ + const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) ) + { + return; + } + + U32 index = 0; + if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) ) + { + return; + } + + spellcheck_handler->replaceWithSuggestion(index); +} + +bool visible_spellcheck_suggestion(LLUICtrl* ctrl, const LLSD& param) +{ + LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(ctrl); + const LLContextMenu* menu = (item) ? dynamic_cast<const LLContextMenu*>(item->getParent()) : NULL; + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) ) + { + return false; + } + + U32 index = 0; + if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) ) + { + return false; + } + + item->setLabel(spellcheck_handler->getSuggestion(index)); + return true; +} + +void handle_spellcheck_add_to_dictionary(const LLUICtrl* ctrl) +{ + const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + if ( (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()) ) + { + spellcheck_handler->addToDictionary(); + } +} + +bool enable_spellcheck_add_to_dictionary(const LLUICtrl* ctrl) +{ + const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent()); + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + return (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()); +} + +void handle_spellcheck_add_to_ignore(const LLUICtrl* ctrl) +{ + const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + if ( (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()) ) + { + spellcheck_handler->addToIgnore(); + } +} + +bool enable_spellcheck_add_to_ignore(const LLUICtrl* ctrl) +{ + const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent()); + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + return (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()); +} + bool enable_object_delete() { bool new_value = @@ -5367,6 +5421,14 @@ void toggle_debug_menus(void*) // } // +class LLCommunicateBlockList : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); + return true; + } +}; class LLWorldSetHomeLocation : public view_listener_t { @@ -6738,15 +6800,6 @@ void handle_test_female(void*) //gGestureList.requestResetFromServer( FALSE ); } -void handle_toggle_pg(void*) -{ - gAgent.setTeen( !gAgent.isTeen() ); - - LLFloaterWorldMap::reloadIcons(NULL); - - llinfos << "PG status set to " << (S32)gAgent.isTeen() << llendl; -} - void handle_dump_attachments(void*) { if(!isAgentAvatarValid()) return; @@ -8072,6 +8125,19 @@ void initialize_edit_menu() } +void initialize_spellcheck_menu() +{ + LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar(); + LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar(); + + commit.add("SpellCheck.ReplaceWithSuggestion", boost::bind(&handle_spellcheck_replace_with_suggestion, _1, _2)); + enable.add("SpellCheck.VisibleSuggestion", boost::bind(&visible_spellcheck_suggestion, _1, _2)); + commit.add("SpellCheck.AddToDictionary", boost::bind(&handle_spellcheck_add_to_dictionary, _1)); + enable.add("SpellCheck.EnableAddToDictionary", boost::bind(&enable_spellcheck_add_to_dictionary, _1)); + commit.add("SpellCheck.AddToIgnore", boost::bind(&handle_spellcheck_add_to_ignore, _1)); + enable.add("SpellCheck.EnableAddToIgnore", boost::bind(&enable_spellcheck_add_to_ignore, _1)); +} + void initialize_menus() { // A parameterized event handler used as ctrl-8/9/0 zoom controls below. @@ -8152,6 +8218,9 @@ void initialize_menus() // Me > Movement view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying"); + + // Communicate + view_listener_t::addMenu(new LLCommunicateBlockList(), "Communicate.BlockList"); // World menu view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun"); @@ -8311,7 +8380,6 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale"); view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale"); - view_listener_t::addMenu(new LLAdvancedTogglePG(), "Advanced.TogglePG"); // Advanced > Character (toplevel) view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 87cb4efbc4..8c40762865 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -39,6 +39,7 @@ class LLObjectSelection; class LLSelectNode; void initialize_edit_menu(); +void initialize_spellcheck_menu(); void init_menus(); void cleanup_menus(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index d790fbc31d..376a135050 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -42,6 +42,7 @@ #include "llinventorydefines.h" #include "lllslconstants.h" #include "llregionhandle.h" +#include "llsd.h" #include "llsdserialize.h" #include "llteleportflags.h" #include "lltransactionflags.h" @@ -107,6 +108,7 @@ #include "llagentui.h" #include "llpanelblockedlist.h" #include "llpanelplaceprofile.h" +#include "llviewerregion.h" #include <boost/algorithm/string/split.hpp> // #include <boost/regex.hpp> @@ -1993,6 +1995,46 @@ bool lure_callback(const LLSD& notification, const LLSD& response) } static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); +bool mature_lure_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = 0; + if (response.isInteger()) + { + option = response.asInteger(); + } + else + { + option = LLNotificationsUtil::getSelectedOption(notification, response); + } + + LLUUID from_id = notification["payload"]["from_id"].asUUID(); + LLUUID lure_id = notification["payload"]["lure_id"].asUUID(); + BOOL godlike = notification["payload"]["godlike"].asBoolean(); + U8 region_access = static_cast<U8>(notification["payload"]["region_maturity"].asInteger()); + + switch(option) + { + case 0: + { + // accept + gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(region_access)); + gAgent.setMaturityRatingChangeDuringTeleport(region_access); + gAgent.teleportViaLure(lure_id, godlike); + } + break; + case 1: + default: + // decline + send_simple_im(from_id, + LLStringUtil::null, + IM_LURE_DECLINED, + lure_id); + break; + } + return false; +} +static LLNotificationFunctorRegistration mature_lure_callback_reg("TeleportOffered_MaturityExceeded", mature_lure_callback); + bool goto_url_callback(const LLSD& notification, const LLSD& response) { std::string url = notification["payload"]["url"].asString(); @@ -2884,15 +2926,54 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { LLVector3 pos, look_at; U64 region_handle(0); - U8 region_access(0); + U8 region_access(SIM_ACCESS_MIN); std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size); std::string region_access_str = LLStringUtil::null; std::string region_access_icn = LLStringUtil::null; + std::string region_access_lc = LLStringUtil::null; + + bool canUserAccessDstRegion = true; + bool doesUserRequireMaturityIncrease = false; if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) { region_access_str = LLViewerRegion::accessToString(region_access); region_access_icn = LLViewerRegion::getAccessIcon(region_access); + region_access_lc = region_access_str; + LLStringUtil::toLower(region_access_lc); + + if (!gAgent.isGodlike()) + { + switch (region_access) + { + case SIM_ACCESS_MIN : + case SIM_ACCESS_PG : + break; + case SIM_ACCESS_MATURE : + if (gAgent.isTeen()) + { + canUserAccessDstRegion = false; + } + else if (gAgent.prefersPG()) + { + doesUserRequireMaturityIncrease = true; + } + break; + case SIM_ACCESS_ADULT : + if (!gAgent.isAdult()) + { + canUserAccessDstRegion = false; + } + else if (!gAgent.prefersAdult()) + { + doesUserRequireMaturityIncrease = true; + } + break; + default : + llassert(0); + break; + } + } } LLSD args; @@ -2901,28 +2982,130 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) args["MESSAGE"] = message; args["MATURITY_STR"] = region_access_str; args["MATURITY_ICON"] = region_access_icn; + args["REGION_CONTENT_MATURITY"] = region_access_lc; LLSD payload; payload["from_id"] = from_id; payload["lure_id"] = session_id; payload["godlike"] = FALSE; + payload["region_maturity"] = region_access; + + if (!canUserAccessDstRegion) + { + LLNotification::Params params("TeleportOffered_MaturityBlocked"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id); + send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id); + } + else if (doesUserRequireMaturityIncrease) + { + LLNotification::Params params("TeleportOffered_MaturityExceeded"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + } + else + { + LLNotification::Params params("TeleportOffered"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + } - LLNotification::Params params("TeleportOffered"); - params.substitutions = args; - params.payload = payload; - LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); } } break; case IM_GODLIKE_LURE_USER: { + LLVector3 pos, look_at; + U64 region_handle(0); + U8 region_access(SIM_ACCESS_MIN); + std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size); + std::string region_access_str = LLStringUtil::null; + std::string region_access_icn = LLStringUtil::null; + std::string region_access_lc = LLStringUtil::null; + + bool canUserAccessDstRegion = true; + bool doesUserRequireMaturityIncrease = false; + + if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) + { + region_access_str = LLViewerRegion::accessToString(region_access); + region_access_icn = LLViewerRegion::getAccessIcon(region_access); + region_access_lc = region_access_str; + LLStringUtil::toLower(region_access_lc); + + if (!gAgent.isGodlike()) + { + switch (region_access) + { + case SIM_ACCESS_MIN : + case SIM_ACCESS_PG : + break; + case SIM_ACCESS_MATURE : + if (gAgent.isTeen()) + { + canUserAccessDstRegion = false; + } + else if (gAgent.prefersPG()) + { + doesUserRequireMaturityIncrease = true; + } + break; + case SIM_ACCESS_ADULT : + if (!gAgent.isAdult()) + { + canUserAccessDstRegion = false; + } + else if (!gAgent.prefersAdult()) + { + doesUserRequireMaturityIncrease = true; + } + break; + default : + llassert(0); + break; + } + } + } + + LLSD args; + // *TODO: Translate -> [FIRST] [LAST] (maybe) + args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString(); + args["MESSAGE"] = message; + args["MATURITY_STR"] = region_access_str; + args["MATURITY_ICON"] = region_access_icn; + args["REGION_CONTENT_MATURITY"] = region_access_lc; LLSD payload; payload["from_id"] = from_id; payload["lure_id"] = session_id; payload["godlike"] = TRUE; - // do not show a message box, because you're about to be - // teleported. - LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0); + payload["region_maturity"] = region_access; + + if (!canUserAccessDstRegion) + { + LLNotification::Params params("TeleportOffered_MaturityBlocked"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id); + send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id); + } + else if (doesUserRequireMaturityIncrease) + { + LLNotification::Params params("TeleportOffered_MaturityExceeded"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + } + else + { + // do not show a message box, because you're about to be + // teleported. + LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0); + } } break; @@ -3446,6 +3629,9 @@ void process_teleport_start(LLMessageSystem *msg, void**) LL_DEBUGS("Messaging") << "Got TeleportStart with TeleportFlags=" << teleport_flags << ". gTeleportDisplay: " << gTeleportDisplay << ", gAgent.mTeleportState: " << gAgent.getTeleportState() << LL_ENDL; + // *NOTE: The server sends two StartTeleport packets when you are teleporting to a LM + LLViewerMessage::getInstance()->mTeleportStartedSignal(); + if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) { gViewerWindow->setProgressCancelButtonVisible(FALSE); @@ -3465,11 +3651,17 @@ void process_teleport_start(LLMessageSystem *msg, void**) make_ui_sound("UISndTeleportOut"); LL_INFOS("Messaging") << "Teleport initiated by remote TeleportStart message with TeleportFlags: " << teleport_flags << LL_ENDL; + // Don't call LLFirstUse::useTeleport here because this could be // due to being killed, which would send you home, not to a Telehub } } +boost::signals2::connection LLViewerMessage::setTeleportStartedCallback(teleport_started_callback_t cb) +{ + return mTeleportStartedSignal.connect(cb); +} + void process_teleport_progress(LLMessageSystem* msg, void**) { LLUUID agent_id; @@ -5422,23 +5614,35 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) } } - - -bool handle_special_notification_callback(const LLSD& notification, const LLSD& response) +bool handle_prompt_for_maturity_level_change_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option) { // set the preference to the maturity of the region we're calling - int preferredMaturity = notification["payload"]["_region_access"].asInteger(); - gSavedSettings.setU32("PreferredMaturity", preferredMaturity); - gAgent.sendMaturityPreferenceToServer(preferredMaturity); + U8 preferredMaturity = static_cast<U8>(notification["payload"]["_region_access"].asInteger()); + gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(preferredMaturity)); + } + + return false; +} - // notify user that the maturity preference has been changed - LLSD args; - args["RATING"] = LLViewerRegion::accessToString(preferredMaturity); - LLNotificationsUtil::add("PreferredMaturityChanged", args); +bool handle_prompt_for_maturity_level_change_and_reteleport_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if (0 == option) + { + // set the preference to the maturity of the region we're calling + U8 preferredMaturity = static_cast<U8>(notification["payload"]["_region_access"].asInteger()); + gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(preferredMaturity)); + gAgent.setMaturityRatingChangeDuringTeleport(preferredMaturity); + gAgent.restartFailedTeleportRequest(); + } + else + { + gAgent.clearTeleportRequest(); } return false; @@ -5447,39 +5651,148 @@ bool handle_special_notification_callback(const LLSD& notification, const LLSD& // some of the server notifications need special handling. This is where we do that. bool handle_special_notification(std::string notificationID, LLSD& llsdBlock) { - int regionAccess = llsdBlock["_region_access"].asInteger(); - llsdBlock["REGIONMATURITY"] = LLViewerRegion::accessToString(regionAccess); + U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger()); + std::string regionMaturity = LLViewerRegion::accessToString(regionAccess); + LLStringUtil::toLower(regionMaturity); + llsdBlock["REGIONMATURITY"] = regionMaturity; - // we're going to throw the LLSD in there in case anyone ever wants to use it - LLNotificationsUtil::add(notificationID+"_Notify", llsdBlock); + bool returnValue = false; + LLNotificationPtr maturityLevelNotification; + std::string notifySuffix = "_Notify"; + if (regionAccess == SIM_ACCESS_MATURE) + { + if (gAgent.isTeen()) + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; + } + else if (gAgent.prefersPG()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock); + returnValue = true; + } + } + else if (regionAccess == SIM_ACCESS_ADULT) + { + if (!gAgent.isAdult()) + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; + } + else if (gAgent.prefersPG() || gAgent.prefersMature()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock); + returnValue = true; + } + } + + if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored()) + { + // Given a simple notification if no maturityLevelNotification is set or it is ignore + LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); + } + + return returnValue; +} + +// some of the server notifications need special handling. This is where we do that. +bool handle_teleport_access_blocked(LLSD& llsdBlock) +{ + std::string notificationID("TeleportEntryAccessBlocked"); + U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger()); + std::string regionMaturity = LLViewerRegion::accessToString(regionAccess); + LLStringUtil::toLower(regionMaturity); + llsdBlock["REGIONMATURITY"] = regionMaturity; + bool returnValue = false; + LLNotificationPtr maturityLevelNotification; + std::string notifySuffix = "_Notify"; if (regionAccess == SIM_ACCESS_MATURE) { if (gAgent.isTeen()) { - LLNotificationsUtil::add(notificationID+"_KB", llsdBlock); - return true; + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; } else if (gAgent.prefersPG()) { - LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); - return true; + if (gAgent.hasRestartableFailedTeleportRequest()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback); + returnValue = true; + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; } } else if (regionAccess == SIM_ACCESS_ADULT) { if (!gAgent.isAdult()) { - LLNotificationsUtil::add(notificationID+"_KB", llsdBlock); - return true; + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; } else if (gAgent.prefersPG() || gAgent.prefersMature()) { - LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); - return true; + if (gAgent.hasRestartableFailedTeleportRequest()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback); + returnValue = true; + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; } } - return false; + + if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored()) + { + // Given a simple notification if no maturityLevelNotification is set or it is ignore + LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); + } + + return returnValue; } bool attempt_standard_notification(LLMessageSystem* msgsystem) @@ -5523,16 +5836,20 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) RegionEntryAccessBlocked RegionEntryAccessBlocked_Notify + RegionEntryAccessBlocked_NotifyAdultsOnly RegionEntryAccessBlocked_Change - RegionEntryAccessBlocked_KB + RegionEntryAccessBlocked_AdultsOnlyContent + RegionEntryAccessBlocked_ChangeAndReTeleport LandClaimAccessBlocked LandClaimAccessBlocked_Notify + LandClaimAccessBlocked_NotifyAdultsOnly LandClaimAccessBlocked_Change - LandClaimAccessBlocked_KB + LandClaimAccessBlocked_AdultsOnlyContent LandBuyAccessBlocked LandBuyAccessBlocked_Notify + LandBuyAccessBlocked_NotifyAdultsOnly LandBuyAccessBlocked_Change - LandBuyAccessBlocked_KB + LandBuyAccessBlocked_AdultsOnlyContent -----------------------------------------------------------------------*/ if (handle_special_notification(notificationID, llsdBlock)) @@ -5584,6 +5901,30 @@ void process_alert_message(LLMessageSystem *msgsystem, void **user_data) } } +bool handle_not_age_verified_alert(const std::string &pAlertName) +{ + LLNotificationPtr notification = LLNotificationsUtil::add(pAlertName); + if ((notification == NULL) || notification->isIgnored()) + { + LLNotificationsUtil::add(pAlertName + "_Notify"); + } + + return true; +} + +bool handle_special_alerts(const std::string &pAlertName) +{ + bool isHandled = false; + + if (LLStringUtil::compareStrings(pAlertName, "NotAgeVerified") == 0) + { + + isHandled = handle_not_age_verified_alert(pAlertName); + } + + return isHandled; +} + void process_alert_core(const std::string& message, BOOL modal) { // HACK -- handle callbacks for specific alerts. It also is localized in notifications.xml @@ -5607,7 +5948,10 @@ void process_alert_core(const std::string& message, BOOL modal) // Allow the server to spawn a named alert so that server alerts can be // translated out of English. std::string alert_name(message.substr(ALERT_PREFIX.length())); - LLNotificationsUtil::add(alert_name); + if (!handle_special_alerts(alert_name)) + { + LLNotificationsUtil::add(alert_name); + } } else if (message.find(NOTIFY_PREFIX) == 0) { @@ -6193,6 +6537,9 @@ void process_teleport_failed(LLMessageSystem *msg, void**) std::string big_reason; LLSD args; + // Let the interested parties know that teleport failed. + LLViewerParcelMgr::getInstance()->onTeleportFailed(); + // if we have additional alert data if (msg->has(_PREHASH_AlertInfo) && msg->getSizeFast(_PREHASH_AlertInfo, _PREHASH_Message) > 0) { @@ -6222,7 +6569,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**) else { // change notification name in this special case - if (handle_special_notification("RegionEntryAccessBlocked", llsd_block)) + if (handle_teleport_access_blocked(llsd_block)) { if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) { @@ -6251,9 +6598,6 @@ void process_teleport_failed(LLMessageSystem *msg, void**) LLNotificationsUtil::add("CouldNotTeleportReason", args); - // Let the interested parties know that teleport failed. - LLViewerParcelMgr::getInstance()->onTeleportFailed(); - if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) { gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 46bfb2dad0..594c22ed9c 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -37,6 +37,9 @@ #include "llnotifications.h" #include "llextendedstatus.h" +#include <boost/function.hpp> +#include <boost/signals2.hpp> + // // Forward declarations // @@ -205,6 +208,15 @@ bool highlight_offered_object(const LLUUID& obj_id); void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder_uuid); void set_dad_inbox_object(const LLUUID& object_id); +class LLViewerMessage : public LLSingleton<LLViewerMessage> +{ +public: + typedef boost::function<void()> teleport_started_callback_t; + typedef boost::signals2::signal<void()> teleport_started_signal_t; + boost::signals2::connection setTeleportStartedCallback(teleport_started_callback_t cb); + + teleport_started_signal_t mTeleportStartedSignal; +}; class LLOfferInfo : public LLNotificationResponderInterface { @@ -253,5 +265,3 @@ private: void process_feature_disabled_message(LLMessageSystem* msg, void**); #endif - - diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index af007743bf..027b1533e4 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2392,10 +2392,11 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) { // This will put the object underground, but we can't tell if it will stop // at ground level or not min_height = LLWorld::getInstance()->getMinAllowedZ(this, new_pos_global); + // Cap maximum height + new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]); } new_pos.mV[VZ] = llmax(min_height, new_pos.mV[VZ]); - new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]); // Check to see if it's going off the region LLVector3 temp(new_pos); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 30c3d03635..03b50c649e 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -693,6 +693,10 @@ protected: // but not updated on the server yet. After item was updated, its ID will be removed from this list. std::list<LLUUID> mPendingInventoryItemsIDs; + // IDs of of all items in the object's content which are added to the object's content, + // but not updated on the server yet. After item was updated, its ID will be removed from this list. + std::list<LLUUID> mPendingInventoryItemsIDs; + // This is the object's inventory from the viewer's perspective. LLInventoryObject::object_list_t* mInventory; class LLInventoryCallbackInfo diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 9db784101d..ae9c31bfe7 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -82,7 +82,6 @@ LLPointer<LLViewerTexture> sBlockedImage; LLPointer<LLViewerTexture> sPassImage; // Local functions -void optionally_start_music(const std::string& music_url); void callback_start_music(S32 option, void* data); void optionally_prepare_video(const LLParcel *parcelp); void callback_prepare_video(S32 option, void* data); @@ -1589,7 +1588,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use if (instance->mTeleportInProgress) { instance->mTeleportInProgress = FALSE; - instance->mTeleportFinishedSignal(gAgent.getPositionGlobal()); + instance->mTeleportFinishedSignal(gAgent.getPositionGlobal(), false); } } } @@ -1773,13 +1772,13 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use }; } -void optionally_start_music(const std::string& music_url) +void LLViewerParcelMgr::optionally_start_music(const std::string& music_url) { if (gSavedSettings.getBOOL("AudioStreamingMusic")) { // only play music when you enter a new parcel if the UI control for this // was not *explicitly* stopped by the user. (part of SL-4878) - LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel();; + LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel(); if ((nearby_media_panel && nearby_media_panel->getParcelAudioAutoStart()) || // or they have expressed no opinion in the UI, but have autoplay on... @@ -2559,7 +2558,7 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos { // Local teleport. We already have the agent parcel data. // Emit the signal immediately. - getInstance()->mTeleportFinishedSignal(new_pos); + getInstance()->mTeleportFinishedSignal(new_pos, local); } else { diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index cac8d8391c..2a11549426 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -78,8 +78,8 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr> { public: - typedef boost::function<void (const LLVector3d&)> teleport_finished_callback_t; - typedef boost::signals2::signal<void (const LLVector3d&)> teleport_finished_signal_t; + typedef boost::function<void (const LLVector3d&, const bool& local)> teleport_finished_callback_t; + typedef boost::signals2::signal<void (const LLVector3d&, const bool&)> teleport_finished_signal_t; typedef boost::function<void()> parcel_changed_callback_t; typedef boost::signals2::signal<void()> parcel_changed_signal_t; @@ -275,6 +275,8 @@ public: // *NOTE: Taken out 2005-03-21. Phoenix. //void makeLandmarkAtSelection(); + static void optionally_start_music(const std::string& music_url); + static void processParcelOverlay(LLMessageSystem *msg, void **user_data); static void processParcelProperties(LLMessageSystem *msg, void **user_data); static void processParcelAccessListReply(LLMessageSystem *msg, void **user); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e4108e2cd1..61ff2ee12e 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -655,6 +655,31 @@ std::string LLViewerRegion::accessToShortString(U8 sim_access) } // static +U8 LLViewerRegion::shortStringToAccess(const std::string &sim_access) +{ + U8 accessValue; + + if (LLStringUtil::compareStrings(sim_access, "PG") == 0) + { + accessValue = SIM_ACCESS_PG; + } + else if (LLStringUtil::compareStrings(sim_access, "M") == 0) + { + accessValue = SIM_ACCESS_MATURE; + } + else if (LLStringUtil::compareStrings(sim_access, "A") == 0) + { + accessValue = SIM_ACCESS_ADULT; + } + else + { + accessValue = SIM_ACCESS_MIN; + } + + return accessValue; +} + +// static void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) { // send it to 'observers' diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index c483c6ef52..7280c7f2e6 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -202,6 +202,7 @@ public: // Returns "M", "PG", "A" etc. static std::string accessToShortString(U8 sim_access); + static U8 shortStringToAccess(const std::string &sim_access); // Return access icon name static std::string getAccessIcon(U8 sim_access); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 862d53c613..0de867388c 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -614,7 +614,7 @@ public: addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount, LLMeshRepository::sHTTPRetryCount)); ypos += y_inc; - + addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing)); ypos += y_inc; @@ -1705,9 +1705,6 @@ LLViewerWindow::LLViewerWindow(const Params& p) // Can't have spaces in settings.ini strings, so use underscores instead and convert them. LLStringUtil::replaceChar(mOverlayTitle, '_', ' '); - // sync the keyboard's setting with the saved setting - gSavedSettings.getControl("NumpadControl")->firePropertyChanged(); - mDebugText = new LLDebugText(this); mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); @@ -1974,12 +1971,12 @@ void LLViewerWindow::shutdownViews() gMorphView->setVisible(FALSE); } llinfos << "Global views cleaned." << llendl ; - + // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open // will crump with LL_ERRS. LLModalDialog::shutdownModals(); llinfos << "LLModalDialog shut down." << llendl; - + // destroy the nav bar, not currently part of gViewerWindow // *TODO: Make LLNavigationBar part of gViewerWindow if (LLNavigationBar::instanceExists()) @@ -1987,17 +1984,17 @@ void LLViewerWindow::shutdownViews() delete LLNavigationBar::getInstance(); } llinfos << "LLNavigationBar destroyed." << llendl ; - + // destroy menus after instantiating navbar above, as it needs // access to gMenuHolder cleanup_menus(); llinfos << "menus destroyed." << llendl ; - + // Delete all child views. delete mRootView; mRootView = NULL; llinfos << "RootView deleted." << llendl ; - + // Automatically deleted as children of mRootView. Fix the globals. gStatusBar = NULL; gIMMgr = NULL; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 28a25f744b..05febdf93b 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2692,7 +2692,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (isImpostor() && !mNeedsImpostorUpdate) { - LLVector4a ext[2]; + LL_ALIGN_16(LLVector4a ext[2]); F32 distance; LLVector3 angle; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index fab15c200d..f5692bb52f 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -93,6 +93,16 @@ protected: **/ public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual void markDead(); static void initClass(); // Initialize data that's only init'd once per class. @@ -215,7 +225,7 @@ public: bool isBuilt() const { return mIsBuilt; } private: //aligned members - LLVector4a mImpostorExtents[2]; + LL_ALIGN_16(LLVector4a mImpostorExtents[2]); private: BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 543891ca63..2b273e616c 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -49,6 +49,16 @@ class LLVOAvatarSelf : **/ public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVOAvatarSelf(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual ~LLVOAvatarSelf(); virtual void markDead(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index cfa47b3ba3..a35cf98af5 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2530,6 +2530,11 @@ void LLPipeline::updateGL() glu->mInQ = FALSE; LLGLUpdate::sGLQ.pop_front(); } + + { //seed VBO Pools + LLFastTimer t(FTM_SEED_VBO_POOLS); + LLVertexBuffer::seedPools(); + } } { //seed VBO Pools diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index eabcc68916..7ca6820318 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -54,6 +54,8 @@ with the same filename but different name <texture name="Arrow_Down" file_name="widgets/Arrow_Down.png" preload="true" /> <texture name="Arrow_Up" file_name="widgets/Arrow_Up.png" preload="true" /> + <texture name="Arrow_Left" file_name="widgets/Arrow_Left.png" preload="true" /> + <texture name="Arrow_Right" file_name="widgets/Arrow_Right.png" preload="true" /> <texture name="AudioMute_Off" file_name="icons/AudioMute_Off.png" preload="false" /> <texture name="AudioMute_Over" file_name="icons/AudioMute_Over.png" preload="false" /> diff --git a/indra/newview/skins/default/textures/widgets/Arrow_Left.png b/indra/newview/skins/default/textures/widgets/Arrow_Left.png Binary files differnew file mode 100644 index 0000000000..a424282839 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/Arrow_Left.png diff --git a/indra/newview/skins/default/textures/widgets/Arrow_Right.png b/indra/newview/skins/default/textures/widgets/Arrow_Right.png Binary files differnew file mode 100644 index 0000000000..e32bee8f34 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/Arrow_Right.png diff --git a/indra/newview/skins/default/xui/da/floater_model_wizard.xml b/indra/newview/skins/default/xui/da/floater_model_wizard.xml deleted file mode 100644 index 8ad443581a..0000000000 --- a/indra/newview/skins/default/xui/da/floater_model_wizard.xml +++ /dev/null @@ -1,241 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="UPLOAD MODEL WIZARD"> - <button label="5. Upload" name="upload_btn"/> - <button label="4. Review" name="review_btn"/> - <button label="3. Physics" name="physics2_btn"/> - <button label="3. Physics" name="physics_btn"/> - <button label="2. Optimize" name="optimize_btn"/> - <button label="1. Choose File" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="header_panel"> - <text name="header_text"> - Upload Model - </text> - </panel> - <text name="description"> - This wizard will help you import mesh models to Second Life. First specify a file containing the model you wish to import. Second Life supports COLLADA (.dae) files. - </text> - <panel name="content"> - <text name="Cache location"> - Filename: - </text> - <button label="Browse..." label_selected="Browse..." name="browse"/> - <text name="dimensions"> - X: Y: Z: - </text> - <text name="dimension_dividers"> - | | - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="header_panel"> - <text name="header_text"> - Optimize - </text> - </panel> - <text name="description"> - This wizard has optimized your model to improve performance. You may adjust the results of the optimization process bellow or click Next to continue. - </text> - <panel name="content"> - <text name="high_detail_text"> - Generate Level of Detail: High - </text> - <text name="medium_detail_text"> - Generate Level of Detail: Medium - </text> - <text name="low_detail_text"> - Generate Level of Detail: Low - </text> - <text name="lowest_detail_text"> - Generate Level of Detail: Lowest - </text> - </panel> - <panel name="content2"> - <text name="lod_label"> - Model Preview: - </text> - <combo_box name="preview_lod_combo2" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High - </combo_item> - <combo_item name="medium"> - Medium - </combo_item> - <combo_item name="low"> - Low - </combo_item> - <combo_item name="lowest"> - Lowest - </combo_item> - </combo_box> - <text name="streaming cost"> - Resource Cost: [COST] - </text> - <text name="dimensions"> - X: Y: Z: - </text> - <text name="dimension_dividers"> - | | - </text> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="header_panel"> - <text name="header_text"> - Physics - </text> - </panel> - <text name="description"> - The wizard will create a physical shape, which determines how the object interacts with other objects and avatars. Set the slider to the detail level most appropriate for how your object will be used: - </text> - <panel name="content"> - <text name="streaming cost"> - Resource Cost: [COST] - </text> - </panel> - </panel> - <panel name="physics2_panel"> - <panel name="header_panel"> - <text name="header_text"> - Physics - </text> - </panel> - <text name="description"> - Preview the physics shape below then click Next to continue. To modify the physics shape, click the Back button. - </text> - <panel name="content"> - <text name="lod_label"> - Model Preview: - </text> - <combo_box name="preview_lod_combo3" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High - </combo_item> - <combo_item name="medium"> - Medium - </combo_item> - <combo_item name="low"> - Low - </combo_item> - <combo_item name="lowest"> - Lowest - </combo_item> - </combo_box> - <text name="dimensions"> - X: Y: Z: - </text> - <text name="dimension_dividers"> - | | - </text> - <text name="streaming cost"> - Resource Cost: [COST] - </text> - </panel> - </panel> - <panel name="review_panel"> - <panel name="header_panel"> - <text name="header_text"> - Review - </text> - </panel> - <text name="description"> - Review the details below then click. Upload to upload your model. Your L$ balance will be charged when you click Upload. - </text> - <panel name="content"> - <text name="lod_label"> - Model Preview: - </text> - <combo_box name="preview_lod_combo" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High - </combo_item> - <combo_item name="medium"> - Medium - </combo_item> - <combo_item name="low"> - Low - </combo_item> - <combo_item name="lowest"> - Lowest - </combo_item> - </combo_box> - <text name="dimensions"> - X: Y: Z: - </text> - <text name="dimension_dividers"> - | | - </text> - </panel> - <text name="streaming cost"> - Resource Cost: [COST] - </text> - <text name="physics cost"> - Physics Cost: [COST] - </text> - </panel> - <panel name="upload_panel"> - <panel name="header_panel"> - <text name="header_text"> - Upload Complete! - </text> - </panel> - <text name="description"> - Congratulations! Your model has been sucessfully uploaded. You will find the model in the Objects folder in your inventory. - </text> - </panel> - <button label="<< Back" name="back"/> - <button label="Next >>" name="next"/> - <button label="Upload" name="upload" tool_tip="Upload to simulator"/> - <button label="Cancel" name="cancel"/> - <button label="Close" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Idle - </string> - <string name="status_reading_file"> - Loading... - </string> - <string name="status_generating_meshes"> - Generating Meshes... - </string> - <string name="status_vertex_number_overflow"> - Error: Vertex number is more than 65534, aborted! - </string> - <string name="high"> - High - </string> - <string name="medium"> - Medium - </string> - <string name="low"> - Low - </string> - <string name="lowest"> - Lowest - </string> - <string name="mesh_status_good"> - Ship it! - </string> - <string name="mesh_status_na"> - N/A - </string> - <string name="mesh_status_none"> - None - </string> - <string name="mesh_status_submesh_mismatch"> - Levels of detail have a different number of textureable faces. - </string> - <string name="mesh_status_mesh_mismatch"> - Levels of detail have a different number of mesh instances. - </string> - <string name="mesh_status_too_many_vertices"> - Level of detail has too many vertices. - </string> - <string name="mesh_status_missing_lod"> - Missing required level of detail. - </string> - <string name="layer_all"> - All - </string> -</floater> diff --git a/indra/newview/skins/default/xui/de/floater_model_wizard.xml b/indra/newview/skins/default/xui/de/floater_model_wizard.xml deleted file mode 100644 index ee26d51d32..0000000000 --- a/indra/newview/skins/default/xui/de/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="ASSISTENT ZUM HOCHLADEN VON MODELLEN"> - <button label="5. Hochladen" name="upload_btn"/> - <button label="4. Überprüfen" name="review_btn"/> - <button label="3. Physik" name="physics_btn"/> - <button label="2. Optimieren" name="optimize_btn"/> - <button label="1. Datei auswählen" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Modelldatei auswählen - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Fortgeschrittene Benutzer: Wenn Sie bereits mit Tools zur Erstellung von 3D-Inhalten vertraut sind, können Sie den erweiterten Uploader verwenden. - </text> - <button label="Auf Erweitert wechseln" name="switch_to_advanced"/> - <text name="Cache location"> - Hochzuladende Modelldatei auswählen - </text> - <button label="Durchsuchen..." label_selected="Durchsuchen..." name="browse"/> - <text name="Model types"> - Second Life unterstützt COLLADA-Dateien (.dae). - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - ACHTUNG: - </text> - <text name="warning_text"> - Sie können den letzten Schritt nicht abschließen (Modell auf Second Life-Server hochladen). [secondlife:///app/floater/learn_more Weitere Infos], wie Sie Ihr Konto zum Hochladen von Netzmodellen einrichten. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Modell optimieren - </text> - </panel> - <text name="optimize_description"> - Wir haben das Modell auf Leistung optimiert. Sie können es bei Bedarf weiter anpassen. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Detailstufe generieren: hoch - </text> - <text name="medium_detail_text"> - Detailstufe generieren: mittel - </text> - <text name="low_detail_text"> - Detailstufe generieren: niedrig - </text> - <text name="lowest_detail_text"> - Detailstufe generieren: niedrigste - </text> - </panel> - <panel name="content2"> - <button label="Geometrie neu berechnen" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Geometrievorschau - </text> - <combo_box name="preview_lod_combo" tool_tip="Detailstufe zur Anzeige in Vorschaudarstellung"> - <combo_item name="high"> - Viel Details - </combo_item> - <combo_item name="medium"> - Mittlere Details - </combo_item> - <combo_item name="low"> - Wenig Details - </combo_item> - <combo_item name="lowest"> - Wenigste Details - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Physik anpassen - </text> - </panel> - <text name="physics_description"> - Wir erstellen eine Form für die Außenhülle des Modells. Passen Sie die Detailstufe der Form wie für den beabsichtigten Zweck erforderlich an. - </text> - <panel name="physics_content"> - <button label="Physik neu berechnen" name="recalculate_physics_btn"/> - <button label="Neu berechnen..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Physikvorschau - </text> - <combo_box name="preview_lod_combo2" tool_tip="Detailstufe zur Anzeige in Vorschaudarstellung"> - <combo_item name="high"> - Viel Details - </combo_item> - <combo_item name="medium"> - Mittlere Details - </combo_item> - <combo_item name="low"> - Wenig Details - </combo_item> - <combo_item name="lowest"> - Wenigste Details - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Überprüfen - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Auswirkung auf Parzelle/Region: Prim-Äquivalenzwert [EQUIV] - </text> - <text name="review_fee"> - Die für das Hochladen anfallende Gebühr in Höhe von L$ [FEE] wird von Ihrem Konto abgebucht. - </text> - <text name="review_confirmation"> - Durch Klicken auf „Hochladen“ bestätigen Sie, dass Sie die erforderlichen Rechte für das im Modell enthaltene Material besitzen. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Upload abgeschlossen - </text> - </panel> - <text name="model_uploaded_text"> - Ihr Modell wurde hochgeladen. - </text> - <text name="inventory_text"> - Sie finden das Modell im Objektordner Ihres Inventars. - </text> - <text name="charged_fee"> - Von Ihrem Konto wurden [FEE] L$ abgebucht. - </text> - </panel> - <button label="<< Zurück" name="back"/> - <button label="Weiter >>" name="next"/> - <button label="Gewichte und Gebühr berechnen >>" name="calculate"/> - <button label="Berechnen..." name="calculating"/> - <button label="Hochladen" name="upload" tool_tip="An Simulator hochladen"/> - <button label="Abbrechen" name="cancel"/> - <button label="Schließen" name="close"/> - <spinner name="import_scale" value="1,0"/> - <string name="status_idle"> - Inaktiv - </string> - <string name="status_parse_error"> - DAE-Parsing-Fehler. Details siehe Protokoll. - </string> - <string name="status_reading_file"> - Laden... - </string> - <string name="status_generating_meshes"> - Netze werden generiert... - </string> - <string name="status_vertex_number_overflow"> - Fehler: Anzahl von Vertices überschreitet 65534. Operation abgebrochen. - </string> - <string name="bad_element"> - Fehler: ungültiges Element. - </string> - <string name="high"> - Hoch - </string> - <string name="medium"> - Mittel - </string> - <string name="low"> - Niedrig - </string> - <string name="lowest"> - Niedrigste - </string> - <string name="mesh_status_good"> - Ausliefern - </string> - <string name="mesh_status_na"> - -- - </string> - <string name="mesh_status_none"> - Keine - </string> - <string name="mesh_status_submesh_mismatch"> - Detailstufen haben unterschiedliche Anzahl texturfähiger Flächen. - </string> - <string name="mesh_status_mesh_mismatch"> - Detailstufen haben unterschiedliche Anzahl von Netzinstanzen. - </string> - <string name="mesh_status_too_many_vertices"> - Detailstufe hat zu viele Vertices. - </string> - <string name="mesh_status_missing_lod"> - Erforderliche Detailstufe fehlt. - </string> - <string name="layer_all"> - Alle - </string> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 060d889003..63eb87f27a 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -196,27 +196,26 @@ Dummy Name replaced at run time top="5" width="435" word_wrap="true"> - 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion - APR Copyright (C) 2000-2004 The Apache Software Foundation - Collada DOM Copyright 2005 Sony Computer Entertainment Inc. - cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) + 3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion + APR Copyright (C) 2011 The Apache Software Foundation + Collada DOM Copyright 2006 Sony Computer Entertainment Inc. + cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc. expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. - FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org). + FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) jpeglib Copyright (C) 1991-1998, Thomas G. Lane. - ogg/vorbis Copyright (C) 2001, Xiphophorus - OpenSSL Copyright (C) 1998-2002 The OpenSSL Project. - PCRE Copyright (c) 1997-2008 University of Cambridge + ogg/vorbis Copyright (C) 2002, Xiphophorus + OpenSSL Copyright (C) 1998-2008 The OpenSSL Project. + PCRE Copyright (c) 1997-2012 University of Cambridge SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. - zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler. - google-perftools Copyright (c) 2005, Google Inc. + zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. Second Life Viewer uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details. diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index fb123ec4d1..793a6e6fa1 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1354,79 +1354,13 @@ Only large parcels can be listed in search. top="150" width="430" /> <combo_box - enabled="false" - height="23" - layout="topleft" - left="20" - top="194" - name="land category with adult" - visible="false" - width="140"> - <combo_box.item - label="Any Category" - name="item0" - value="any" /> - <combo_box.item - label="Linden Location" - name="item1" - value="linden" /> - <combo_box.item - label="Adult" - name="item2" - value="adult" /> - <combo_box.item - label="Arts & Culture" - name="item3" - value="arts" /> - <combo_box.item - label="Business" - name="item4" - value="store" /> - <combo_box.item - label="Educational" - name="item5" - value="educational" /> - <combo_box.item - label="Gaming" - name="item6" - value="game" /> - <combo_box.item - label="Hangout" - name="item7" - value="gather" /> - <combo_box.item - label="Newcomer Friendly" - name="item8" - value="newcomer" /> - <combo_box.item - label="Parks & Nature" - name="item9" - value="park" /> - <combo_box.item - label="Residential" - name="item10" - value="home" /> - <combo_box.item - label="Shopping" - name="item11" - value="shopping" /> - <combo_box.item - label="Rental" - name="item13" - value="rental" /> - <combo_box.item - label="Other" - name="item12" - value="other" /> - </combo_box> - <combo_box - enabled="false" + enabled="true" height="23" layout="topleft" left="20" top="194" name="land category" - visible="false" + visible="true" width="140"> <combo_box.item label="Any Category" @@ -1989,11 +1923,11 @@ Only large parcels can be listed in search. <check_box follows="top|left" height="16" - label="Have been age-verified [ESTATE_AGE_LIMIT]" + label="Are age 18 or older [ESTATE_AGE_LIMIT]" layout="topleft" left_delta="0" name="limit_age_verified" - tool_tip="Residents must be age verified to access this parcel. See the [SUPPORT_SITE] for more information." + tool_tip="Residents must be age 18 or older to access this parcel. See the [SUPPORT_SITE] for more information." top_pad="4" width="278" /> <check_box diff --git a/indra/newview/skins/default/xui/en/floater_autoreplace.xml b/indra/newview/skins/default/xui/en/floater_autoreplace.xml new file mode 100644 index 0000000000..0bfefc8abe --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_autoreplace.xml @@ -0,0 +1,289 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + border="true" + can_close="true" + can_minimize="true" + can_resize="false" + help_topic="autoreplace_settings" + save_rect="true" + height="455" + width="490" + name="autoreplace_floater" + title="Auto-Replace Settings"> + <check_box + bottom_delta="30" + left_delta="15" + height="16" + width="100" + follows="left|top" + label="Enable Auto-Replace" + name="autoreplace_enable" + tool_tip="As you enter chat text, replace any of the keywords entered with the corresponding replacement"/> + <view_border + top_pad="15" + left="2" + height="0" + width="491" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor1"/> + <button + top_pad="10" + left="10" + height="22" + width="110" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_import_list" + label="Import List..." + tool_tip="Load a previously exported list from a file."/> + <button + top_delta="0" + left_pad="10" + height="22" + width="110" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_export_list" + label="Export List..." + tool_tip="Save the selected list to a file so you can share it."/> + <button + top_delta="0" + left_pad="10" + height="22" + width="110" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_new_list" + label="New List..." + tool_tip="Create a new list."/> + <button + top_delta="0" + left_pad="10" + height="22" + width="110" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_delete_list" + label="Delete List" + tool_tip="Delete the selected list."/> + <scroll_list + top_pad="10" + left="10" + height="100" + width="370" + follows="left|top" + column_padding="0" + draw_heading="false" + multi_select="false" + name="autoreplace_list_name" + search_column="0"> + </scroll_list> + <button + top_delta="23" + left_pad="10" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_list_up" + image_overlay="Arrow_Up" + tool_tip="Move this list up in priority."/> + <button + top_pad="10" + left_delta="0" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_list_down" + image_overlay="Arrow_Down" + tool_tip="Move this list down in priority."/> + <view_border + top_pad="36" + left="2" + height="0" + width="491" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor2"/> + <scroll_list + top_pad="10" + left="10" + height="120" + width="370" + follows="left|top" + column_padding="0" + draw_heading="true" + multi_select="true" + name="autoreplace_list_replacements" + search_column="0"> + <scroll_list.columns + label="Keyword" + name="keyword" + relative_width="0.30" /> + <scroll_list.columns + label="Replacement" + name="replacement" + relative_width="0.70" /> + </scroll_list> + <button + top_delta="41" + left_pad="10" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_add_entry" + label="Add..."/> + <button + top_pad="10" + left_delta="0" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_delete_entry" + label="Remove"/> + <view_border + top_pad="38" + left="2" + height="0" + width="491" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor3"/> + <text + type="string" + follows="left|top" + height="16" + layout="topleft" + left="10" + top_pad="13" + width="50"> + Keyword: + </text> + <line_editor + name="autoreplace_keyword" + follows="left|top" + height="23" + layout="topleft" + left="100" + max_length_bytes="255" + top_delta="-5" + width="150" + /> + <text + type="string" + follows="left|top" + height="16" + layout="topleft" + left="10" + right="90" + top_pad="10" + > + Replacement: + </text> + <line_editor + name="autoreplace_replacement" + follows="left|top" + height="23" + layout="topleft" + left="100" + max_length_bytes="255" + top_delta="-5" + width="280" + /> + <button + top_delta="0" + right="-10" + height="22" + width="90" + enabled="false" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_save_entry" + label="Save Entry" + tool_tip="Save this entry."/> + <view_border + top_pad="10" + left="2" + height="0" + width="491" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor4"/> + <button + top_pad="10" + right="380" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_save_changes" + label="Save Changes" + tool_tip="Save all changes."/> + <button + top_delta="0" + right="480" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_cancel" + label="Cancel" + tool_tip="Discard all changes."/> +</floater> +<!-- + <text + top_pad="10" + left="10" + height="16" + width="260" + follows="left|top" + halign="center" + mouse_opaque="true" + name="autoreplace_text2"> + Entries + </text> +--> diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml index 688a01ce7b..405557242f 100644 --- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/floater_chat_bar.xml @@ -46,6 +46,7 @@ left="0" max_length_bytes="1023" name="chat_box" + spellcheck="true" text_pad_left="5" text_pad_right="25" tool_tip="Press Enter to say, Ctrl+Enter to shout" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index ca73883e53..040b66623e 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -46,7 +46,7 @@ tab_group="2" top="0" height="200" - width="254" + width="244" user_resize="true"> <button height="20" @@ -73,18 +73,20 @@ parse_highlights="true" parse_urls="true" left="1" - width="249"> + width="238"> </chat_history> <line_editor bottom="0" + left="3" follows="left|right|bottom" font="SansSerifSmall" height="20" label="To" layout="bottomleft" name="chat_editor" + spellcheck="true" tab_group="3" - width="249"> + width="236"> </line_editor> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index 0e211551e6..5e92a12251 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -1,8 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater can_close="true" can_drag_on_left="false" can_minimize="false" - can_resize="false" height="480" min_height="480" min_width="940" - name="Model Preview" title="UPLOAD MODEL" width="940" - help_topic="upload_model" > +<floater + can_close="true" + can_drag_on_left="false" + can_minimize="false" + can_resize="false" + height="480" + min_height="480" + width="980" + min_width="980" + name="Model Preview" + title="UPLOAD MODEL" + help_topic="upload_model" > <string name="status_idle"></string> <string name="status_parse_error">Error: Dae parsing issue - see log for details.</string> @@ -98,7 +106,7 @@ top_pad="15" left="0" height="300" - width="625" + width="635" name="import_tab" tab_position="top"> <!-- LOD PANEL --> @@ -116,13 +124,13 @@ left="3" name="lod_tab_border" top_pad="0" - width="619" /> + width="629" /> <text follows="left|top" height="18" initial_value="Source" layout="topleft" - left="75" + left="85" name="source" text_color="ModelUploaderLabels" top="15" @@ -165,7 +173,7 @@ top_pad="10" valign="top" value="High" - width="65" /> + width="75" /> <combo_box follows="top|left" height="20" @@ -175,10 +183,10 @@ top_delta="-3" width="135"> <item - id="Load from file" + name="Load from file" value="Load from file" /> <item - id="Generate" + name="Generate" value="Generate" /> </combo_box> <line_editor @@ -210,10 +218,10 @@ visible="false" width="135"> <item - id="Triangle Limit" + name="Triangle Limit" value="Triangle Limit" /> <item - id="Error Threshold" + name="Error Threshold" value="Error Threshold" /> </combo_box> <spinner @@ -290,7 +298,7 @@ top_pad="15" valign="top" value="Medium" - width="65" /> + width="75" /> <combo_box follows="top|left" height="20" @@ -300,13 +308,13 @@ top_delta="-3" width="135"> <item - id="Load from file" + name="Load from file" value="Load from file" /> <item - id="Generate" + name="Generate" value="Generate" /> <item - id="Use LoD above" + name="Use LoD above" value="Use LoD above" /> </combo_box> <line_editor @@ -339,10 +347,10 @@ top_delta="0" width="135"> <item - id="Triangle Limit" + name="Triangle Limit" value="Triangle Limit" /> <item - id="Error Threshold" + name="Error Threshold" value="Error Threshold" /> </combo_box> <spinner @@ -418,7 +426,7 @@ top_pad="15" valign="top" value="Low" - width="65" /> + width="75" /> <combo_box follows="top|left" height="20" @@ -428,13 +436,13 @@ top_delta="-3" width="135"> <item - id="Load from file" + name="Load from file" value="Load from file" /> <item - id="Generate" + name="Generate" value="Generate" /> <item - id="Use LoD above" + name="Use LoD above" value="Use LoD above" /> </combo_box> <line_editor @@ -467,10 +475,10 @@ top_delta="0" width="135"> <item - id="Triangle Limit" + name="Triangle Limit" value="Triangle Limit" /> <item - id="Error Threshold" + name="Error Threshold" value="Error Threshold" /> </combo_box> <spinner @@ -546,7 +554,7 @@ top_pad="15" valign="top" value="Lowest" - width="65" /> + width="75" /> <combo_box follows="top|left" height="20" @@ -556,13 +564,13 @@ top_delta="-3" width="135"> <item - id="Load from file" + name="Load from file" value="Load from file" /> <item - id="Generate" + name="Generate" value="Generate" /> <item - id="Use LoD above" + name="Use LoD above" value="Use LoD above" /> </combo_box> <line_editor @@ -595,10 +603,10 @@ top_delta="0" width="135"> <item - id="Triangle Limit" + name="Triangle Limit" value="Triangle Limit" /> <item - id="Error Threshold" + name="Error Threshold" value="Error Threshold" /> </combo_box> <spinner @@ -1201,7 +1209,7 @@ name="calculate_btn" top="3" height="20" - width="150" + width="165" tool_tip="Calculate weights &fee"/> <button follows="top|left" @@ -1234,7 +1242,7 @@ right="-2" top="3" height="20" - width="155"/> + width="275"/> <!-- ========== WEIGHTS ==========--> <text follows="top|left" @@ -1343,7 +1351,7 @@ layout="topleft" name="right_panel" top_pad="5" - width="290"> + width="340"> <combo_box top_pad="3" follows="left|top" diff --git a/indra/newview/skins/default/xui/en/floater_model_wizard.xml b/indra/newview/skins/default/xui/en/floater_model_wizard.xml deleted file mode 100644 index 62b8c5f96e..0000000000 --- a/indra/newview/skins/default/xui/en/floater_model_wizard.xml +++ /dev/null @@ -1,841 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - legacy_header_height="18" - layout="topleft" - name="Model Wizard" - help_topic="model_wizard" - bg_opaque_image_overlay="0.5 0.5 0.5 1" - height="480" - save_rect="true" - title="UPLOAD MODEL WIZARD" - width="535"> - <button - top="32" - tab_stop="false" - left="410" - height="32" - name="upload_btn" - enabled="false" - label="5. Upload" - border="false" - image_unselected="BreadCrumbBtn_Right_Off" - image_selected="BreadCrumbBtn_Right_Press" - image_hover_unselected="BreadCrumbBtn_Right_Over" - image_disabled="BreadCrumbBtn_Right_Disabled" - image_disabled_selected="BreadCrumbBtn_Right_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Upload"/> - </button> - <button - top="32" - left="310" - height="32" - tab_stop="false" - name="review_btn" - label="4. Review" - enabled="false" - border="false" - image_unselected="BreadCrumbBtn_Middle_Off" - image_selected="BreadCrumbBtn_Middle_Press" - image_hover_unselected="BreadCrumbBtn_Middle_Over" - image_disabled="BreadCrumbBtn_Middle_Disabled" - image_disabled_selected="BreadCrumbBtn_Middle_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Review"/> - </button> - <button - top="32" - left="210" - height="32" - name="physics_btn" - label="3. Physics" - tab_stop="false" - enabled="false" - border="false" - image_unselected="BreadCrumbBtn_Middle_Off" - image_selected="BreadCrumbBtn_Middle_Press" - image_hover_unselected="BreadCrumbBtn_Middle_Over" - image_disabled="BreadCrumbBtn_Middle_Disabled" - image_disabled_selected="BreadCrumbBtn_Middle_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Physics"/> - </button> - <button - top="32" - left="115" - name="optimize_btn" - label="2. Optimize" - tab_stop="false" - height="32" - border="false" - image_unselected="BreadCrumbBtn_Middle_Off" - image_selected="BreadCrumbBtn_Middle_Press" - image_hover_unselected="BreadCrumbBtn_Middle_Over" - image_disabled="BreadCrumbBtn_Middle_Disabled" - image_disabled_selected="BreadCrumbBtn_Middle_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Optimize"/> - </button> - <button - top="32" - left="15" - name="choose_file_btn" - tab_stop="false" - enabled="false" - label="1. Choose File" - height="32" - image_unselected="BreadCrumbBtn_Left_Off" - image_selected="BreadCrumbBtn_Left_Press" - image_hover_unselected="BreadCrumbBtn_Left_Over" - image_disabled="BreadCrumbBtn_Left_Disabled" - image_disabled_selected="BreadCrumbBtn_Left_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Choose"/> - </button> - <panel - height="388" - top_pad="0" - name="choose_file_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - width="505" - name="choose_file_header_panel" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - top="3" - name="choose_file_header_text" - text_color="White" - height="10" - font="SansSerifBig" - layout="topleft"> - Choose model file - </text> - </panel> - <panel - top_pad="14" - left="15" - height="310" - width="505" - name="choose_file_content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text - height="32" - left="10" - name="advanced_users_text" - text_color="White" - top="15" - width="320" - word_wrap="true"> - Advanced users: If you are familiar with 3D content creation tools you may wish to use the Advanced Uploader. - </text> - <button - follows="left|top" - height="20" - label="Switch to Advanced" - layout="topleft" - left_delta="0" - name="switch_to_advanced" - top_pad="5" - width="130"> - </button> - <text - type="string" - length="1" - text_color="White" - follows="left|top" - top_pad="30" - height="10" - layout="topleft" - left_delta="0" - name="Cache location" - width="320"> - Choose model file to upload - </text> - <line_editor - border_style="line" - border_thickness="1" - follows="left|top" - font="SansSerifSmall" - height="20" - layout="topleft" - left_delta="0" - max_length="4096" - name="lod_file" - top_pad="5" - width="230" /> - <button - follows="left|top" - height="23" - label="Browse..." - label_selected="Browse..." - layout="topleft" - left_pad="5" - name="browse" - top_delta="-1" - width="85"> - </button> - <text - type="string" - length="1" - text_color="White" - follows="left|top" - top_pad="5" - height="10" - layout="topleft" - left="10" - name="Model types" - width="320"> - Second Life supports COLLADA (.dae) files - </text> - <!-- Placeholder panel for 3D preview render --> - <panel - top="30" - right="-10" - name="choose_file_preview_panel" - bevel_style="none" - highlight_light_color="0.09 0.09 0.09 1" - border="true" - border_style="line" - height="150" - follows="all" - width="150"> - </panel> - <text - top_pad="10" - width="130" - height="14" - left_delta="0" - text_color="White" - word_wrap="true"> - Dimensions (meters): - </text> - <text - top_pad="0" - width="160" - height="15" - font="SansSerifSmallBold" - text_color="White" - name="dimensions" - left_delta="0"> - X Y Z - </text> - <text - top_delta="0" - width="160" - height="15" - name="dimension_x" - left="356"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_y" - left="403"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_z" - left="450"/> - <text - height="16" - left="10" - name="warning_label" - text_color="Yellow" - top="200" - visible="false" - width="320"> - WARNING: - </text> - <text - height="50" - left="10" - name="warning_text" - top_pad="0" - visible="false" - width="320" - word_wrap="true"> - You will not be able to complete the final step of uploading this model to the Second Life servers. [secondlife:///app/floater/learn_more Find out how] to set up your account for mesh model uploads. - </text> - </panel> - </panel> - - - <panel - height="388" - top_delta="0" - name="optimize_panel" - visible="true" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="optimize_header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="optimize_header_text" - top="3" - text_color="White" - height="10" - font="SansSerifBig" - layout="topleft"> - Optimize model - </text> - </panel> - <text - top_pad="14" - width="460" - height="20" - font="SansSerifSmall" - layout="topleft" - name="optimize_description" - word_wrap="true" - left_delta="5"> - We have optimized the model for performance. Adjust it further if you wish. - </text> - <panel - top_delta="40" - visible="false" - left="15" - height="270" - width="505" - name="optimize_content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text - top="20" - width="300" - height="12" - font="SansSerifBold" - left="112">Generating Level of Detail</text> - <progress_bar - name="optimize_progress_bar" - image_fill="model_wizard\progress_light.png" - color_bg="1 1 1 1" - color_bar="1 1 1 0.96" - follows="left|right|top" - width="260" - height="16" - image_bar="model_wizard\progress_bar_bg.png" - top_pad="14" - left="110"/> - <icon - top_pad="10" - left_delta="0" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="high_detail_text" - width="200" - height="14">Generate Level of Detail: High</text> - <icon - top_pad="10" - left_delta="-18" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="medium_detail_text" - width="200" - height="14">Generate Level of Detail: Medium</text> - <icon - top_pad="10" - left_delta="-18" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="low_detail_text" - width="200" - height="14">Generate Level of Detail: Low</text> - <icon - top_pad="10" - left_delta="-18" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="lowest_detail_text" - width="200" - height="14">Generate Level of Detail: Lowest</text> - </panel> - <panel - top_delta="0" - left_delta="0" - height="270" - width="505" - name="content2" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text top="69" left="10" text_color="White" font="SansSerifSmallBold" width="120" height="16" wrap="true">Performance</text> - <text top="85" left="10" width="120" word_wrap="true" font="SansSerifSmall" height="40">Faster rendering -Less detail -Lower prim weight</text> - <text top="69" left="184" text_color="White" font="SansSerifSmallBold" width="120" height="16" wrap="true">Accuracy</text> - <text top="85" left="184" width="120" word_wrap="true" font="SansSerifSmall" height="40">Slower rendering -More detail -Higher prim weight</text> - - <slider - follows="left|top" - height="20" - increment="1" - layout="topleft" - left="10" - max_val="2" - initial_value="1" - min_val="0" - name="accuracy_slider" - show_text="false" - top="130" - width="290" /> - <text - font="SansSerifSmall" - top_pad="0" - width="5" - left_delta="6" - height="4">' - </text> - <text - font="SansSerifSmall" - top_delta="0" - width="5" - left_delta="137" - height="4">' - </text> - <text - font="SansSerifSmall" - top_delta="0" - width="5" - left_delta="137" - height="4">' - </text> - <button - follows="left|top" - height="20" - label="Recalculate Geometry" - layout="topleft" - left="80" - name="recalculate_geometry_btn" - top_pad="15" - width="150"> - </button> - <text top="10" right="-10" width="185" text_color="White" follows="left|top" height="15" name="lod_label"> - Geometry preview - </text> - <panel - right="-10" - top="32" - name="optimize_preview_panel" - bevel_style="none" - highlight_light_color="0.09 0.09 0.09 1" - border_style="line" - border="true" - height="185" - follows="all" - width="185"> - </panel> - <combo_box left_delta="75" top_pad="10" follows="left|top" list_position="below" height="22" - name="preview_lod_combo" width="110" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High detail - </combo_item> - <combo_item name="medium"> - Medium detail - </combo_item> - <combo_item name="low"> - Low detail - </combo_item> - <combo_item name="lowest"> - Lowest detail - </combo_item> - </combo_box> - </panel> - </panel> - - <panel - height="388" - top_delta="0" - name="physics_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="physics_header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="physics_header_text" - top="3" - height="10" - font="SansSerifBig" - text_color="White" - layout="topleft"> - Adjust physics - </text> - </panel> - <text - top_pad="10" - width="474" - height="50" - font="SansSerifSmall" - layout="topleft" - name="physics_description" - word_wrap="true" - left_delta="5"> - We will create a shape for the outer hull of the model. Adjust the shape's detail level as needed for the intended purpose of your model. - </text> - <panel - top_delta="44" - left="15" - height="270" - width="505" - name="physics_content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text top="10" left="10" text_color="White" font="SansSerifSmallBold" width="120" halign="right" height="16" wrap="true">Performance</text> - <text top="26" left="10" width="120" word_wrap="true" font="SansSerifSmall" halign="right" height="40">Faster rendering -Less detail -Lower prim weight</text> - <text top="174" left="10" text_color="White" font="SansSerifSmallBold" width="120" halign="right" height="16" wrap="true">Accuracy</text> - <text top="190" left="10" width="120" word_wrap="true" font="SansSerifSmall" halign="right" height="40">Slower rendering -More detail -Higher prim weight</text> - - <slider - follows="left|top" - height="190" - increment=".1" - layout="topleft" - left="140" - max_val="1" - initial_value="0.5" - min_val="0" - name="physics_slider" - orientation="vertical" - show_text="false" - top="25" - width="22" /> - <text top="10" width="120" word_wrap="true" left_pad="10" height="50">Examples: -Moving objects -Flying objects -Vehicles</text> - <text top="95" width="120" word_wrap="true" left_delta="0" height="50">Examples: -Small static objects -Less detailed objects -Simple furniture</text> - <text top="180" width="120" word_wrap="true" left_delta="0" height="50">Examples: -Static objects -Detailed objects -Buildings</text> - <button - follows="left|top" - height="20" - label="Recalculate physics" - layout="topleft" - left="80" - name="recalculate_physics_btn" - top_pad="10" - width="150"> - </button> - <button - enabled="false" - follows="left|top" - height="20" - label="Recalculating..." - layout="topleft" - left_delta="0" - name="recalculating_physics_btn" - top_delta="0" - visible="false" - width="150"> - </button> - <text top="10" right="-10" width="185" text_color="White" follows="left|top" height="15" name="lod_label"> - Physics preview - </text> - <panel - right="-10" - top="32" - name="physics_preview_panel" - bevel_style="none" - highlight_light_color="0.09 0.09 0.09 1" - border_style="line" - border="true" - height="185" - follows="all" - width="185"> - </panel> - <combo_box left_delta="75" top_pad="10" follows="left|top" list_position="below" height="22" - name="preview_lod_combo2" width="110" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High detail - </combo_item> - <combo_item name="medium"> - Medium detail - </combo_item> - <combo_item name="low"> - Low detail - </combo_item> - <combo_item name="lowest"> - Lowest detail - </combo_item> - </combo_box> - </panel> - </panel> - - <panel - height="388" - top_delta="0" - name="review_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="review_header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="review_header_text" - text_color="White" - top="3" - height="10" - font="SansSerifBig" - layout="topleft"> - Review - </text> - </panel> - <panel - top_pad="14" - left="15" - height="310" - width="505" - name="review_content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text - top="20" - width="485" - font="SansSerifMedium" - text_color="White" - left="10" - name="review_prim_equiv" - height="16">Impact to parcel/region: [EQUIV] prim equivalents - </text> - <text - top_pad="20" - width="485" - font="SansSerifMedium" - text_color="White" - left="10" - name="review_fee" - height="16">Your account will be charged an upload fee of L$ [FEE]. - </text> - <text - top_pad="20" - width="485" - font="SansSerifMedium" - text_color="White" - left="10" - name="review_confirmation" - height="32" - word_wrap="true">By clicking the upload button, you confirm that you have the appropriate rights to the material contained in the model. - </text> - </panel> - </panel> - - - - - <panel - height="388" - top_delta="0" - name="upload_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="upload_header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="upload_header_text" - top="3" - text_color="White" - height="10" - font="SansSerifBig" - layout="topleft"> - Upload complete - </text> - </panel> - <text - top_pad="14" - width="495" - height="16" - font="SansSerifMedium" - layout="topleft" - name="model_uploaded_text" - text_color="White" - word_wrap="true" - left="25"> - Your model has been uploaded. - </text> - <text - top_pad="5" - width="495" - height="16" - font="SansSerifMedium" - layout="topleft" - name="inventory_text" - text_color="White" - word_wrap="true" - left="25"> - You will find it in the Objects folder in your inventory. - </text> - <text - top_pad="20" - width="495" - font="SansSerifMedium" - text_color="White" - left="25" - name="charged_fee" - height="16">Your account has been charged L$ [FEE]. - </text> - </panel> - - - - <button - top="440" - right="-285" - width="90" - height="22" - name="back" - label="<< Back" /> - <button - top_delta="0" - right="-190" - width="90" - height="22" - name="next" - label="Next >> " /> - <button - top_delta="0" - left_delta="0" - width="160" - height="22" - name="calculate" - label="Calculate weights & fee >> " /> - <button - enabled="false" - visible="false" - top_delta="0" - left_delta="0" - width="160" - height="22" - name="calculating" - label="Calculating... " /> - <button - enabled="false" - top_delta="0" - right="-150" - width="90" - height="22" - visible="false" - name="upload" - tool_tip="Upload to simulator" - label="Upload" /> - <button - top_delta="0" - right="-15" - width="90" - height="22" - name="cancel" - label="Cancel" /> - <button - top_delta="0" - right="-15" - width="90" - height="22" - name="close" - visible="false" - label="Close" /> - <spinner visible="false" left="10" height="20" follows="top|left" width="80" top_pad="-50" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/> - - <string name="status_idle">Idle</string> - <string name="status_parse_error">Dae parsing issue - see log for details.</string> - <string name="status_reading_file">Loading...</string> - <string name="status_generating_meshes">Generating Meshes...</string> - <string name="status_vertex_number_overflow">Error: Vertex number is more than 65534, aborted!</string> - <string name="bad_element">Error: element is invalid</string> - <string name="high">High</string> - <string name="medium">Medium</string> - <string name="low">Low</string> - <string name="lowest">Lowest</string> - <string name="mesh_status_good">Ship it!</string> - <string name="mesh_status_na">N/A</string> - <string name="mesh_status_none">None</string> - <string name="mesh_status_submesh_mismatch">Levels of detail have a different number of textureable faces.</string> - <string name="mesh_status_mesh_mismatch">Levels of detail have a different number of mesh instances.</string> - <string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string> - <string name="mesh_status_missing_lod">Missing required level of detail.</string> - <string name="layer_all">All</string> - <!-- Text to display in physics layer combo box for "all layers" --> - -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml index be3b2d179d..2e1c8ce670 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml @@ -70,6 +70,7 @@ max_length="65536" name="Notecard Editor" parse_urls="false" + spellcheck="true" tab_group="1" top="46" width="392" diff --git a/indra/newview/skins/default/xui/en/floater_spellcheck.xml b/indra/newview/skins/default/xui/en/floater_spellcheck.xml new file mode 100644 index 0000000000..76a350dd29 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_spellcheck.xml @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + border="true" + can_close="true" + can_minimize="true" + save_rect="true" + help_topic="spelling_settings" + can_resize="false" + height="315" + width="490" + name="spellcheck_floater" + title="Spell Checker Settings"> + <check_box + bottom_delta="30" + control_name="SpellCheck" + left_delta="15" + height="16" + width="100" + follows="left|top" + label="Enable spell checker" + name="spellcheck_enable" /> + <view_border + top_pad="10" + left="2" + height="0" + width="491" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor1"/> + <text + enabled_control="SpellCheck" + follows="top|left" + height="10" + layout="topleft" + left="38" + mouse_opaque="false" + name="spellcheck_main" + top_pad="15" + type="string" + width="90" + > + Main dictionary : + </text> + <combo_box + enabled_control="SpellCheck" + follows="top|left" + height="23" + layout="topleft" + left_pad="10" + name="spellcheck_main_combo" + top_pad="-15" + width="175" + /> + <text + enabled_control="SpellCheck" + follows="top|left" + height="10" + label="Logs:" + layout="topleft" + left="38" + mouse_opaque="false" + name="spellcheck_additional" + top_pad="15" + type="string" + width="190" + > + Additional dictionaries : + </text> + <text + follows="top|left" + height="12" + layout="topleft" + left="55" + length="1" + name="spellcheck_available" + top_pad="10" + type="string" + width="175"> + Available + </text> + <text + follows="top|left" + height="12" + type="string" + left_pad="45" + length="1" + layout="topleft" + name="spellcheck_active" + width="175"> + Active + </text> + <scroll_list + enabled_control="SpellCheck" + follows="top|left" + height="155" + layout="topleft" + left="55" + multi_select="true" + name="spellcheck_available_list" + sort_column="0" + sort_ascending="true" + width="175" /> + <button + enabled_control="SpellCheck" + follows="top|left" + height="26" + image_overlay="Arrow_Right" + hover_glow_amount="0.15" + layout="topleft" + left_pad="10" + name="spellcheck_moveright_btn" + top_delta="50" + width="25"> + </button> + <button + enabled_control="SpellCheck" + follows="top|left" + height="26" + image_overlay="Arrow_Left" + hover_glow_amount="0.15" + layout="topleft" + name="spellcheck_moveleft_btn" + top_delta="30" + width="25"> + </button> + <scroll_list + enabled_control="SpellCheck" + follows="top|left" + height="155" + layout="topleft" + left_pad="10" + multi_select="true" + name="spellcheck_active_list" + sort_column="0" + sort_ascending="true" + top_pad="-105" + width="175" + /> + <button + enabled="false" + follows="left|top" + height="23" + label="Remove" + layout="topleft" + left="55" + name="spellcheck_remove_btn" + top_pad="5" + width="80" /> + <button + follows="left|top" + height="23" + label="Import..." + layout="topleft" + left_pad="15" + name="spellcheck_import_btn" + top_delta="0" + width="80" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_spellcheck_import.xml b/indra/newview/skins/default/xui/en/floater_spellcheck_import.xml new file mode 100644 index 0000000000..b54090015d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_spellcheck_import.xml @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + border="true" + can_close="true" + can_minimize="true" + bottom="275" + left="300" + can_resize="false" + height="140" + width="400" + name="spellcheck_import" + title="Import Dictionary"> + <text + follows="top|left" + height="16" + layout="topleft" + left="25" + top="15" + type="string" + width="65"> + Dictionary: + </text> + <line_editor + enabled="false" + follows="left|top" + height="23" + layout="topleft" + left_pad="10" + max_length_bytes="255" + name="dictionary_path" + top_delta="-5" + width="200" /> + <button + follows="left|top" + height="23" + label="Browse" + label_selected="Browse" + layout="topleft" + left_pad="5" + name="dictionary_path_browse" + top_delta="0" + width="75" /> + <text + follows="top|left" + height="16" + layout="topleft" + left="25" + top_pad="8" + type="string" + width="65"> + Name: + </text> + <line_editor + enabled="false" + follows="left|top" + height="23" + layout="topleft" + left_pad="10" + max_length_bytes="255" + name="dictionary_name" + top_delta="-5" + width="200" /> + <text + follows="top|left" + height="16" + layout="topleft" + left="25" + top_pad="8" + type="string" + width="65"> + Language: + </text> + <line_editor + follows="left|top" + height="23" + layout="topleft" + left_pad="10" + max_length_bytes="255" + name="dictionary_language" + top_delta="-5" + width="200" /> + <view_border + top_pad="10" + left="2" + height="0" + width="396" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor"/> + <button + top_pad="10" + right="280" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="ok_btn" + label="Import" /> + <button + top_delta="0" + right="380" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="cancel_btn" + label="Cancel" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml index 44b6a63bca..f3f8d4ddca 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml @@ -1,341 +1,341 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- legacy_header_height="18"
- can_minimize="false"
- height="550"
- layout="topleft"
- name="TexFetchDebugger"
- help_topic="texfetchdebugger"
- title="Texture Fetching Debugger"
- width="540">
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left="10"
- name="total_num_fetched_label"
- top="30"
- width="400">
- 1, Total number of fetched textures: [NUM]
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_num_fetching_requests_label"
- top_delta="25"
- width="400">
- 2, Total number of fetching requests: [NUM]
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_num_cache_hits_label"
- top_delta="25"
- width="400">
- 3, Total number of cache hits: [NUM]
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_num_visible_tex_label"
- top_delta="25"
- width="400">
- 4, Total number of visible textures: [NUM]
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_num_visible_tex_fetch_req_label"
- top_delta="25"
- width="450">
- 5, Total number of visible texture fetching requests: [NUM]
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_fetched_data_label"
- top_delta="25"
- width="530">
- 6, Total number of fetched data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_fetched_vis_data_label"
- top_delta="25"
- width="480">
- 7, Total number of visible data: [SIZE1]KB, Decoded Data: [SIZE2]KB
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_fetched_rendered_data_label"
- top_delta="25"
- width="530">
- 8, Total number of rendered data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_cache_read_label"
- top_delta="25"
- width="400">
- 9, Total time on cache readings: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_cache_write_label"
- top_delta="25"
- width="400">
- 10, Total time on cache writings: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_decode_label"
- top_delta="25"
- width="400">
- 11, Total time on decodings: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_gl_label"
- top_delta="25"
- width="400">
- 12, Total time on gl texture creation: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_http_label"
- top_delta="25"
- width="400">
- 13, Total time on HTTP fetching: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_fetch_label"
- top_delta="25"
- width="400">
- 14, Total time on entire fetching: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_refetch_vis_cache_label"
- top_delta="25"
- width="540">
- 15, Refetching visibles from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_refetch_vis_http_label"
- top_delta="25"
- width="540">
- 16, Refetching visibles from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
- </text>
- <spinner
- decimal_digits="2"
- follows="left|top"
- height="20"
- increment="0.01"
- initial_value="1.0"
- label="17, Ratio of Texel/Pixel:"
- label_width="130"
- layout="topleft"
- left_delta="0"
- max_val="10.0"
- min_val="0.01"
- name="texel_pixel_ratio"
- top_delta="30"
- width="200">
- <spinner.commit_callback
- function="TexFetchDebugger.ChangeTexelPixelRatio" />
- </spinner>
- <button
- follows="left|top"
- height="20"
- label="Start"
- layout="topleft"
- left_delta="0"
- name="start_btn"
- top_delta="30"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.Start" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Reset"
- layout="topleft"
- left_pad="7"
- name="clear_btn"
- top_delta="0"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.Clear" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Close"
- layout="topleft"
- left_pad="7"
- name="close_btn"
- top_delta="0"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.Close" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Cache Read"
- layout="topleft"
- left="10"
- name="cacheread_btn"
- top_delta="30"
- width="80">
- <button.commit_callback
- function="TexFetchDebugger.CacheRead" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Cache Write"
- layout="topleft"
- left_pad="7"
- name="cachewrite_btn"
- top_delta="0"
- width="80">
- <button.commit_callback
- function="TexFetchDebugger.CacheWrite" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="HTTP"
- layout="topleft"
- left_pad="7"
- name="http_btn"
- top_delta="0"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.HTTPLoad" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Decode"
- layout="topleft"
- left_pad="7"
- name="decode_btn"
- top_delta="0"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.Decode" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="GL Texture"
- layout="topleft"
- left_pad="7"
- name="gl_btn"
- top_delta="0"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.GLTexture" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Refetch Vis Cache"
- layout="topleft"
- left="10"
- name="refetchviscache_btn"
- top_delta="30"
- width="120">
- <button.commit_callback
- function="TexFetchDebugger.RefetchVisCache" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Refetch Vis HTTP"
- layout="topleft"
- left_pad="7"
- name="refetchvishttp_btn"
- top_delta="0"
- width="120">
- <button.commit_callback
- function="TexFetchDebugger.RefetchVisHTTP" />
- </button>
-</floater>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_minimize="false" + height="550" + layout="topleft" + name="TexFetchDebugger" + help_topic="texfetchdebugger" + title="Texture Fetching Debugger" + width="540"> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left="10" + name="total_num_fetched_label" + top="30" + width="400"> + 1, Total number of fetched textures: [NUM] + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_num_fetching_requests_label" + top_delta="25" + width="400"> + 2, Total number of fetching requests: [NUM] + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_num_cache_hits_label" + top_delta="25" + width="400"> + 3, Total number of cache hits: [NUM] + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_num_visible_tex_label" + top_delta="25" + width="400"> + 4, Total number of visible textures: [NUM] + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_num_visible_tex_fetch_req_label" + top_delta="25" + width="450"> + 5, Total number of visible texture fetching requests: [NUM] + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_fetched_data_label" + top_delta="25" + width="530"> + 6, Total number of fetched data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_fetched_vis_data_label" + top_delta="25" + width="480"> + 7, Total number of visible data: [SIZE1]KB, Decoded Data: [SIZE2]KB + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_fetched_rendered_data_label" + top_delta="25" + width="530"> + 8, Total number of rendered data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_cache_read_label" + top_delta="25" + width="400"> + 9, Total time on cache readings: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_cache_write_label" + top_delta="25" + width="400"> + 10, Total time on cache writings: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_decode_label" + top_delta="25" + width="400"> + 11, Total time on decodings: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_gl_label" + top_delta="25" + width="400"> + 12, Total time on gl texture creation: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_http_label" + top_delta="25" + width="400"> + 13, Total time on HTTP fetching: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_fetch_label" + top_delta="25" + width="400"> + 14, Total time on entire fetching: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_refetch_vis_cache_label" + top_delta="25" + width="540"> + 15, Refetching visibles from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_refetch_vis_http_label" + top_delta="25" + width="540"> + 16, Refetching visibles from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels + </text> + <spinner + decimal_digits="2" + follows="left|top" + height="20" + increment="0.01" + initial_value="1.0" + label="17, Ratio of Texel/Pixel:" + label_width="130" + layout="topleft" + left_delta="0" + max_val="10.0" + min_val="0.01" + name="texel_pixel_ratio" + top_delta="30" + width="200"> + <spinner.commit_callback + function="TexFetchDebugger.ChangeTexelPixelRatio" /> + </spinner> + <button + follows="left|top" + height="20" + label="Start" + layout="topleft" + left_delta="0" + name="start_btn" + top_delta="30" + width="70"> + <button.commit_callback + function="TexFetchDebugger.Start" /> + </button> + <button + follows="left|top" + height="20" + label="Reset" + layout="topleft" + left_pad="7" + name="clear_btn" + top_delta="0" + width="70"> + <button.commit_callback + function="TexFetchDebugger.Clear" /> + </button> + <button + follows="left|top" + height="20" + label="Close" + layout="topleft" + left_pad="7" + name="close_btn" + top_delta="0" + width="70"> + <button.commit_callback + function="TexFetchDebugger.Close" /> + </button> + <button + follows="left|top" + height="20" + label="Cache Read" + layout="topleft" + left="10" + name="cacheread_btn" + top_delta="30" + width="80"> + <button.commit_callback + function="TexFetchDebugger.CacheRead" /> + </button> + <button + follows="left|top" + height="20" + label="Cache Write" + layout="topleft" + left_pad="7" + name="cachewrite_btn" + top_delta="0" + width="80"> + <button.commit_callback + function="TexFetchDebugger.CacheWrite" /> + </button> + <button + follows="left|top" + height="20" + label="HTTP" + layout="topleft" + left_pad="7" + name="http_btn" + top_delta="0" + width="70"> + <button.commit_callback + function="TexFetchDebugger.HTTPLoad" /> + </button> + <button + follows="left|top" + height="20" + label="Decode" + layout="topleft" + left_pad="7" + name="decode_btn" + top_delta="0" + width="70"> + <button.commit_callback + function="TexFetchDebugger.Decode" /> + </button> + <button + follows="left|top" + height="20" + label="GL Texture" + layout="topleft" + left_pad="7" + name="gl_btn" + top_delta="0" + width="70"> + <button.commit_callback + function="TexFetchDebugger.GLTexture" /> + </button> + <button + follows="left|top" + height="20" + label="Refetch Vis Cache" + layout="topleft" + left="10" + name="refetchviscache_btn" + top_delta="30" + width="120"> + <button.commit_callback + function="TexFetchDebugger.RefetchVisCache" /> + </button> + <button + follows="left|top" + height="20" + label="Refetch Vis HTTP" + layout="topleft" + left_pad="7" + name="refetchvishttp_btn" + top_delta="0" + width="120"> + <button.commit_callback + function="TexFetchDebugger.RefetchVisHTTP" /> + </button> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_text_editor.xml b/indra/newview/skins/default/xui/en/menu_text_editor.xml index fe8489166b..70b40dd89b 100644 --- a/indra/newview/skins/default/xui/en/menu_text_editor.xml +++ b/indra/newview/skins/default/xui/en/menu_text_editor.xml @@ -2,6 +2,85 @@ <context_menu name="Text editor context menu"> <menu_item_call + label="(unknown)" + layout="topleft" + name="Suggestion 1"> + <menu_item_call.on_click + function="SpellCheck.ReplaceWithSuggestion" + parameter="0" /> + <menu_item_call.on_visible + function="SpellCheck.VisibleSuggestion" + parameter="0" /> + </menu_item_call> + <menu_item_call + label="(unknown)" + layout="topleft" + name="Suggestion 2"> + <menu_item_call.on_click + function="SpellCheck.ReplaceWithSuggestion" + parameter="1" /> + <menu_item_call.on_visible + function="SpellCheck.VisibleSuggestion" + parameter="1" /> + </menu_item_call> + <menu_item_call + label="(unknown)" + layout="topleft" + name="Suggestion 3"> + <menu_item_call.on_click + function="SpellCheck.ReplaceWithSuggestion" + parameter="2" /> + <menu_item_call.on_visible + function="SpellCheck.VisibleSuggestion" + parameter="2" /> + </menu_item_call> + <menu_item_call + label="(unknown)" + layout="topleft" + name="Suggestion 4"> + <menu_item_call.on_click + function="SpellCheck.ReplaceWithSuggestion" + parameter="3" /> + <menu_item_call.on_visible + function="SpellCheck.VisibleSuggestion" + parameter="3" /> + </menu_item_call> + <menu_item_call + label="(unknown)" + layout="topleft" + name="Suggestion 5"> + <menu_item_call.on_click + function="SpellCheck.ReplaceWithSuggestion" + parameter="4" /> + <menu_item_call.on_visible + function="SpellCheck.VisibleSuggestion" + parameter="4" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Suggestion Separator" /> + <menu_item_call + label="Add to Dictionary" + layout="topleft" + name="Add to Dictionary"> + <menu_item_call.on_click + function="SpellCheck.AddToDictionary" /> + <menu_item_call.on_enable + function="SpellCheck.EnableAddToDictionary" /> + </menu_item_call> + <menu_item_call + label="Add to Ignore" + layout="topleft" + name="Add to Ignore"> + <menu_item_call.on_click + function="SpellCheck.AddToIgnore" /> + <menu_item_call.on_enable + function="SpellCheck.EnableAddToIgnore" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Spellcheck Separator" /> + <menu_item_call label="Cut" layout="topleft" name="Cut"> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index a6898c554f..6bcdc615c3 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -193,6 +193,15 @@ <menu_item_call.on_click function="View.ToggleUI" /> </menu_item_call> + <menu_item_check + label="Show HUD Attachments" + name="Show HUD Attachments" + shortcut="alt|shift|H"> + <menu_item_check.on_check + function="View.CheckHUDAttachments" /> + <menu_item_check.on_click + function="View.ShowHUDAttachments" /> + </menu_item_check> <menu_item_separator/> @@ -291,6 +300,12 @@ function="SideTray.PanelPeopleTab" parameter="nearby_panel" /> </menu_item_call> + <menu_item_call + label="Block List" + name="Block List"> + <menu_item_call.on_click + function="Communicate.BlockList" /> + </menu_item_call> </menu> <menu create_jump_keys="true" @@ -1374,15 +1389,6 @@ function="View.HighlightTransparent" /> </menu_item_check> <menu_item_check - label="Show HUD Attachments" - name="Show HUD Attachments" - shortcut="alt|shift|H"> - <menu_item_check.on_check - function="View.CheckHUDAttachments" /> - <menu_item_check.on_click - function="View.ShowHUDAttachments" /> - </menu_item_check> - <menu_item_check label="Show Mouselook Crosshairs" name="ShowCrosshairs"> <menu_item_check.on_check @@ -3125,12 +3131,6 @@ <menu_item_call.on_click function="Advanced.TestFemale" /> </menu_item_call> - <menu_item_call - label="Toggle PG" - name="Toggle PG"> - <menu_item_call.on_click - function="Advanced.TogglePG" /> - </menu_item_call> <menu_item_check label="Allow Select Avatar" name="Allow Select Avatar"> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e806a40951..e0ae009a02 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2359,6 +2359,93 @@ Would you be my friend? </notification> <notification + icon="alertmodal.tga" + label="Add Auto-Replace List" + name="AddAutoReplaceList" + type="alertmodal"> + <tag>addlist</tag> + Name for the new list: + <tag>confirm</tag> + <form name="form"> + <input name="listname" type="text"/> + <button + default="true" + index="0" + name="SetName" + text="OK"/> + </form> + </notification> + + <notification + icon="alertmodal.tga" + label="Rename Auto-Replace List" + name="RenameAutoReplaceList" + type="alertmodal"> + The name '[DUPNAME]' is in use + Enter a new unique name: + <tag>confirm</tag> + <form name="form"> + <input name="listname" type="text"/> + <button + default="false" + index="0" + name="ReplaceList" + text="Replace Current List"/> + <button + default="true" + index="1" + name="SetName" + text="Use New Name"/> + </form> + </notification> + + <notification + icon="alertmodal.tga" + name="InvalidAutoReplaceEntry" + type="alertmodal"> + The keyword must be a single word, and the replacement may not be empty. + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="InvalidAutoReplaceList" + type="alertmodal"> + That replacement list is not valid. + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="SpellingDictImportRequired" + type="alertmodal"> + You must specify a file, a name, and a language. + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="SpellingDictIsSecondary" + type="alertmodal"> +The dictionary [DIC_NAME] does not appear to have an "aff" file; this means that it is a "secondary" dictionary. +It can be used as an additional dictionary, but not as your Main dictionary. + +See https://wiki.secondlife.com/wiki/Adding_Spelling_Dictionaries + <tag>confirm</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="SpellingDictImportFailed" + type="alertmodal"> + Unable to copy + [FROM_NAME] + to + [TO_NAME] + <tag>fail</tag> + </notification> + + <notification icon="alertmodal.tga" label="Save Outfit" name="SaveOutfitAs" @@ -4089,9 +4176,7 @@ Are you sure you want to change the Estate Covenant? name="RegionEntryAccessBlocked" type="alertmodal"> <tag>fail</tag> -You are not allowed in that Region due to your maturity Rating. This may be a result of a lack of information validating your age. - -Please verify you have the latest Viewer installed, and go to the Knowledge Base for details on accessing areas with this maturity rating. + The region you're trying to visit contains content exceeding your current preferences. You can change your preferences using Me > Preferences > General. <usetemplate name="okbutton" yestext="OK"/> @@ -4099,13 +4184,11 @@ Please verify you have the latest Viewer installed, and go to the Knowledge Base <notification icon="alertmodal.tga" - name="RegionEntryAccessBlocked_KB" + name="RegionEntryAccessBlocked_AdultsOnlyContent" type="alertmodal"> <tag>fail</tag> <tag>confirm</tag> -You are not allowed in that region due to your maturity Rating. - -Go to the Knowledge Base for more information about maturity Ratings? + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. <url option="0" name="url"> http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview </url> @@ -4113,7 +4196,7 @@ Go to the Knowledge Base for more information about maturity Ratings? name="okcancelignore" yestext="Go to Knowledge Base" notext="Close" - ignoretext="I can't enter this Region, due to restrictions of the maturity Rating"/> + ignoretext="Region crossing: The region you're trying to visit contains content which is accessible to adults only."/> </notification> <notification @@ -4121,47 +4204,156 @@ Go to the Knowledge Base for more information about maturity Ratings? name="RegionEntryAccessBlocked_Notify" type="notifytip"> <tag>fail</tag> -You are not allowed in that region due to your maturity Rating. +The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. + </notification> + + <notification + icon="notifytip.tga" + name="RegionEntryAccessBlocked_NotifyAdultsOnly" + type="notifytip"> + <tag>fail</tag> + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. </notification> <notification icon="alertmodal.tga" name="RegionEntryAccessBlocked_Change" type="alertmodal"> - <tag>fail</tag> + <tag>fail</tag> <tag>confirm</tag> -You are not allowed in that Region due to your maturity Rating preference. - -To enter the desired region, please change your maturity Rating preference. This will allow you to search for and access [REGIONMATURITY] content. To undo any changes, go to Me > Preferences > General. - <form name="form"> +The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences, or you can cancel. After your preferences are changed, you may attempt to enter the region again. + <form name="form"> <button index="0" name="OK" - text="Change Preference"/> - <button + text="Change preferences"/> + <button default="true" index="1" name="Cancel" - text="Close"/> - <ignore name="ignore" text="My chosen Rating preference prevents me from entering a Region"/> + text="Cancel"/> + <ignore name="ignore" text="Region crossing: The region you're trying to visit contains content excluded by your preferences."/> </form> </notification> <notification + icon="alertmodal.tga" + name="RegionEntryAccessBlocked_PreferencesOutOfSync" + type="alertmodal"> + <tag>fail</tag> + We are having technical difficulties with your teleport because your preferences are out of sync with the server. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="TeleportEntryAccessBlocked" + type="alertmodal"> + <tag>fail</tag> + The region you're trying to visit contains content exceeding your current preferences. You can change your preferences using Me > Preferences > General. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="TeleportEntryAccessBlocked_AdultsOnlyContent" + type="alertmodal"> + <unique> + <context>REGIONMATURITY</context> + </unique> + <tag>fail</tag> + <tag>confirm</tag> + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. + <url option="0" name="url"> + http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview + </url> + <usetemplate + name="okcancelignore" + yestext="Go to Knowledge Base" + notext="Close" + ignoretext="Teleport: The region you're trying to visit contains content which is accessible to adults only."/> + </notification> + + <notification icon="notifytip.tga" - name="PreferredMaturityChanged" + name="TeleportEntryAccessBlocked_Notify" type="notifytip"> -Your maturity Rating preference is now [RATING]. + <unique> + <context>REGIONMATURITY</context> + </unique> + <tag>fail</tag> + The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. + </notification> + + <notification + icon="notifytip.tga" + name="TeleportEntryAccessBlocked_NotifyAdultsOnly" + type="notifytip"> + <unique> + <context>REGIONMATURITY</context> + </unique> + <tag>fail</tag> + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. </notification> <notification icon="alertmodal.tga" - name="LandClaimAccessBlocked" + name="TeleportEntryAccessBlocked_ChangeAndReTeleport" type="alertmodal"> -You cannot claim this land due to your maturity Rating. This may be a result of a lack of information validating your age. + <unique> + <context>REGIONMATURITY</context> + </unique> + <tag>fail</tag> + <tag>confirm</tag> + The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences and continue with the teleport, or you can cancel this teleport. + <form name="form"> + <button + index="0" + name="OK" + text="Change and continue"/> + <button + default="true" + index="1" + name="Cancel" + text="Cancel"/> + <ignore name="ignore" text="Teleport (restartable): The region you're trying to visit contains content excluded by your preferences."/> + </form> + </notification> -Please verify you have the latest Viewer installed, and go to the Knowledge Base for details on accessing areas with this maturity rating. - <tag>fail</tag> + <notification + icon="alertmodal.tga" + name="TeleportEntryAccessBlocked_Change" + type="alertmodal"> + <unique> + <context>REGIONMATURITY</context> + </unique> + <tag>fail</tag> + <tag>confirm</tag> + The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences, or you can cancel the teleport. After your preferences are changed, you will need to attempt the teleport again. + <form name="form"> + <button + index="0" + name="OK" + text="Change preferences"/> + <button + default="true" + index="1" + name="Cancel" + text="Cancel"/> + <ignore name="ignore" text="Teleport (non-restartable): The region you're trying to visit contains content excluded by your preferences."/> + </form> + </notification> + + <notification + icon="alertmodal.tga" + name="TeleportEntryAccessBlocked_PreferencesOutOfSync" + type="alertmodal"> + <tag>fail</tag> + We are having technical difficulties with your teleport because your preferences are out of sync with the server. <usetemplate name="okbutton" yestext="OK"/> @@ -4169,12 +4361,43 @@ Please verify you have the latest Viewer installed, and go to the Knowledge Base <notification icon="alertmodal.tga" - name="LandClaimAccessBlocked_KB" + name="PreferredMaturityChanged" type="alertmodal"> -You cannot claim this land due to your maturity Rating. +You won't receive any more notifications that you're about to visit a region with [RATING] content. You may change your content preferences in the future by using Me > Preferences > General from the menu bar. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> -Go to the Knowledge Base for more information about maturity Ratings? - <tag>fail</tag> + <notification + icon="alertmodal.tga" + name="MaturityChangeError" + type="alertmodal"> + We were unable to change your preferences to view [PREFERRED_MATURITY] content at this time. Your preferences have been reset to view [ACTUAL_MATURITY] content. You may attempt to change your preferences again by using Me > Preferences > General from the menu bar. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="LandClaimAccessBlocked" + type="alertmodal"> + The land you're trying to claim has a maturity rating exceeding your current preferences. You can change your preferences using Me > Preferences > General. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="LandClaimAccessBlocked_AdultsOnlyContent" + type="alertmodal"> + Only adults can claim this land. + <tag>fail</tag> <tag>confirm</tag> <url option="0" name="url"> http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview @@ -4183,41 +4406,52 @@ Go to the Knowledge Base for more information about maturity Ratings? name="okcancelignore" yestext="Go to Knowledge Base" notext="Close" - ignoretext="I can't claim this Land, due to restrictions of the maturity Rating"/> + ignoretext="Only adults can claim this land."/> </notification> <notification icon="notifytip.tga" name="LandClaimAccessBlocked_Notify" type="notifytip"> -You cannot claim this land due to your maturity Rating. - <tag>fail</tag> + The land you're trying to claim contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. + <tag>fail</tag> + </notification> + + <notification + icon="notifytip.tga" + name="LandClaimAccessBlocked_NotifyAdultsOnly" + type="notifytip"> + <tag>fail</tag> + The land you're trying to claim contains [REGIONMATURITY] content, which is accessible to adults only. </notification> <notification icon="alertmodal.tga" name="LandClaimAccessBlocked_Change" type="alertmodal"> -You cannot claim this land due to your maturity Rating preference. - -You can click 'Change Preference' to raise your maturity Rating preference now and allow you to enter. You will be able to search and access [REGIONMATURITY] content from now on. If you later want to change this setting back, go to Me > Preferences > General. + The land you're trying to claim contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences, then you can try claiming the land again. <tag>fail</tag> <tag>confirm</tag> - <usetemplate - name="okcancelignore" - yestext="Change Preference" - notext="Close" - ignoretext="My chosen Rating preference prevents me from claiming Land"/> + <form name="form"> + <button + index="0" + name="OK" + text="Change preferences"/> + <button + default="true" + index="1" + name="Cancel" + text="Cancel"/> + <ignore name="ignore" text="The land you're trying to claim contains content excluded by your preferences."/> + </form> </notification> <notification icon="alertmodal.tga" name="LandBuyAccessBlocked" type="alertmodal"> -You cannot buy this land due to your maturity Rating. This may be a result of a lack of information validating your age. - -Please verify you have the latest Viewer installed, and go to the Knowledge Base for details on accessing areas with this maturity rating. - <tag>fail</tag> + The land you're trying to buy has a maturity rating exceeding your current preferences. You can change your preferences using Me > Preferences > General. + <tag>fail</tag> <usetemplate name="okbutton" yestext="OK"/> @@ -4225,11 +4459,9 @@ Please verify you have the latest Viewer installed, and go to the Knowledge Base <notification icon="alertmodal.tga" - name="LandBuyAccessBlocked_KB" + name="LandBuyAccessBlocked_AdultsOnlyContent" type="alertmodal"> -You cannot buy this land due to your maturity Rating. - -Go to the Knowledge Base for more information about maturity Ratings? + Only adults can buy this land. <tag>confirm</tag> <tag>fail</tag> <url option="0" name="url"> @@ -4239,31 +4471,44 @@ Go to the Knowledge Base for more information about maturity Ratings? name="okcancelignore" yestext="Go to Knowledge Base" notext="Close" - ignoretext="I can't buy this Land, due to restrictions of the maturity Rating"/> + ignoretext="Only adults can buy this land."/> </notification> <notification icon="notifytip.tga" name="LandBuyAccessBlocked_Notify" type="notifytip"> -You cannot buy this land due to your maturity Rating. - <tag>fail</tag> + The land you're trying to buy contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. + <tag>fail</tag> + </notification> + + <notification + icon="notifytip.tga" + name="LandBuyAccessBlocked_NotifyAdultsOnly" + type="notifytip"> + <tag>fail</tag> + The land you're trying to buy contains [REGIONMATURITY] content, which is accessible to adults only. </notification> <notification icon="alertmodal.tga" name="LandBuyAccessBlocked_Change" type="alertmodal"> -You cannot buy this land due to your maturity Rating preference. - -You can click 'Change Preference' to raise your maturity Rating preference now and allow you to enter. You will be able to search and access [REGIONMATURITY] content from now on. If you later want to change this setting back, go to Me > Preferences > General. + The land you're trying to buy contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences, then you can try buying the land again. <tag>confirm</tag> <tag>fail</tag> - <usetemplate - name="okcancelignore" - yestext="Change Preference" - notext="Close" - ignoretext="My chosen Rating preference prevents me from buying Land"/> + <form name="form"> + <button + index="0" + name="OK" + text="Change preferences"/> + <button + default="true" + index="1" + name="Cancel" + text="Cancel"/> + <ignore name="ignore" text="The land you're trying to buy contains content excluded by your preferences."/> + </form> </notification> <notification @@ -4418,10 +4663,11 @@ Type a short announcement which will be sent to everyone in this region. label="Changed Region Maturity" name="RegionMaturityChange" type="alertmodal"> -The maturity rating for this region has been updated. -It may take some time for the change to be reflected on the map. - -To enter Adult regions, Residents must be Account Verified, either by age-verification or payment-verification. +The maturity rating for this region has been changed. +It may take some time for this change to be reflected on the map. + <usetemplate + name="okbutton" + yestext="OK"/> </notification> <notification @@ -5127,20 +5373,20 @@ Would you like to automatically wear the clothing you are about to create? icon="alertmodal.tga" name="NotAgeVerified" type="alertmodal"> - <tag>fail</tag> -To access adult content and areas in Second Life you must be at least 18 years old. Please visit our age verification page to confirm you are over 18. -Note this will launch your web browser. - -[_URL] - <tag>confirm</tag> - <url option="0" name="url"> - https://secondlife.com/my/account/verification.php - </url> + The location you're trying to visit is restricted to residents age 18 and over. + <tag>fail</tag> <usetemplate - ignoretext="I have not verified my age" - name="okcancelignore" - notext="Cancel" - yestext="Go to Age Verification"/> + ignoretext="I am not old enough to visit age restricted areas." + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="notifytip.tga" + name="NotAgeVerified_Notify" + type="notifytip"> + Location restricted to age 18 and over. + <tag>fail</tag> </notification> <notification @@ -5287,7 +5533,7 @@ Terrain.raw downloaded icon="notifytip.tga" name="GestureMissing" type="notifytip"> -Hmm. Gesture [NAME] is missing from the database. +Gesture [NAME] is missing from the database. <tag>fail</tag> </notification> @@ -5825,9 +6071,7 @@ You can only claim public land in the Region you're in. persist="true" type="notify"> <tag>fail</tag> -You aren't allowed in that Region due to your maturity Rating. You may need to validate your age and/or install the latest Viewer. - -Please go to the Knowledge Base for details on accessing areas with this maturity Rating. + The region you're trying to visit contains content exceeding your current preferences. You can change your preferences using Me > Preferences > General. </notification> <notification @@ -5859,11 +6103,11 @@ You do not have proper payment status to enter this region. <notification icon="notify.tga" - name="MustGetAgeRgion" + name="MustGetAgeRegion" persist="true" type="notify"> <tag>fail</tag> -You must be age-verified to enter this region. +You must be age 18 or over to enter this region. </notification> <notification @@ -5872,7 +6116,7 @@ You must be age-verified to enter this region. persist="true" type="notify"> <tag>fail</tag> -You must be age-verified to enter this parcel. + You must be age 18 or over to enter this parcel. </notification> <notification @@ -6147,7 +6391,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th type="offer"> [NAME_SLURL] has offered to teleport you to their location: -[MESSAGE] - [MATURITY_STR] <icon>[MATURITY_ICON]</icon> +“[MESSAGE]” +<icon>[MATURITY_ICON]</icon> - [MATURITY_STR] <tag>confirm</tag> <form name="form"> <button @@ -6163,6 +6408,42 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" + name="TeleportOffered_MaturityExceeded" + type="offer"> +[NAME_SLURL] has offered to teleport you to their location: + +“[MESSAGE]” +<icon>[MATURITY_ICON]</icon> - [MATURITY_STR] + +This region contains [REGION_CONTENT_MATURITY] content, but your current preferences are set to exclude [REGION_CONTENT_MATURITY] content. We can change your preferences and continue with the teleport, or you can cancel this teleport. + <tag>confirm</tag> + <form name="form"> + <button + index="0" + name="Teleport" + text="Change and Continue"/> + <button + index="1" + name="Cancel" + text="Cancel"/> + </form> + </notification> + + <notification + icon="notify.tga" + name="TeleportOffered_MaturityBlocked" + type="notifytip"> +[NAME_SLURL] has offered to teleport you to their location: + +“[MESSAGE]” +<icon>[MATURITY_ICON]</icon> - [MATURITY_STR] + +However, this region contains content accessible to adults only. + <tag>fail</tag> + </notification> + + <notification + icon="notify.tga" name="TeleportOfferSent" type="offer"> Teleport offer sent to [TO_NAME] @@ -7209,6 +7490,18 @@ We cannot display a preview of this texture because it is no-copy and/or no-tran <notification icon="alertmodal.tga" + name="LivePreviewUnavailable" + type="alert"> + +We cannot display a preview of this texture because it is no-copy and/or no-transfer. + <usetemplate + ignoretext="Warn me that Live Preview mode is not available for no-copy and/or no-transfer textures" + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="ConfirmLeaveCall" type="alert"> Are you sure you want to leave this call? diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml index 0faa1598b1..553c112e6f 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml @@ -134,6 +134,7 @@ top_pad="2" max_length="1023" name="pick_desc" + spellcheck="true" text_color="black" word_wrap="true" /> <text diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index 607e1bb213..6d5fb51e85 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -141,6 +141,7 @@ Maximum 200 per group daily max_length_bytes="63" name="create_subject" prevalidate_callback="ascii" + spellcheck="true" width="218" /> <text follows="left|top" @@ -161,6 +162,7 @@ Maximum 200 per group daily left_pad="3" max_length="511" name="create_message" + spellcheck="true" top_delta="0" width="218" word_wrap="true" /> @@ -309,6 +311,7 @@ Maximum 200 per group daily left_pad="3" max_length_bytes="63" name="view_subject" + spellcheck="true" top_delta="-1" visible="false" width="200" /> @@ -333,6 +336,7 @@ Maximum 200 per group daily right="-1" max_length="511" name="view_message" + spellcheck="true" top_delta="-40" width="313" word_wrap="true" /> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml index 21c627cdfb..6bc9c48729 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml @@ -19,6 +19,7 @@ left="0" max_length_bytes="1023" name="chat_box" + spellcheck="true" text_pad_left="5" text_pad_right="25" tool_tip="Press Enter to say, Ctrl+Enter to shout" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index caf7fc85f5..27193a984f 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -207,13 +207,36 @@ <button follows="left|top" height="23" - label="Chat Translation Settings" + label="Translation..." layout="topleft" left="30" name="ok_btn" - top="-40" + top="-50" width="170"> <button.commit_callback function="Pref.TranslationSettings" /> </button> -</panel>
\ No newline at end of file + <button + follows="top|left" + height="23" + layout="topleft" + top_pad="-23" + left_pad="5" + name="autoreplace_showgui" + commit_callback.function="Pref.AutoReplace" + label="Auto-Replace..." + width="150"> + </button> + <button + follows="top|left" + height="23" + layout="topleft" + top_pad="-23" + left_pad="5" + name="spellcheck_showgui" + commit_callback.function="Pref.SpellChecker" + label="Spell Checking..." + width="150"> + </button> + +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml index bfd796a62b..76a82212ae 100644 --- a/indra/newview/skins/default/xui/en/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml @@ -149,11 +149,11 @@ <check_box follows="top|left" height="16" - label="Have been age-verified" + label="Are age 18 or older" layout="topleft" left_delta="0" name="limit_age_verified" - tool_tip="Residents must be age verified to access this estate. See the [SUPPORT_SITE] for more information." + tool_tip="Residents must be age 18 or older to access this estate. See the [SUPPORT_SITE] for more information." top_pad="2" width="278" /> diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index 6ecb57b41d..14bd349480 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -48,7 +48,7 @@ height="300" width="330" /> </layout_panel> - <layout_panel + <layout_panel width="330" layout="topleft" auto_resize="false" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 866ea296c3..6dd80dc11a 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -441,6 +441,7 @@ Please try logging in again in a minute.</string> <string name="load_files">Load Files</string> <string name="choose_the_directory">Choose Directory</string> <string name="script_files">Scripts</string> + <string name="dictionary_files">Dictionaries</string> <!-- LSL Usage Hover Tips --> <!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window). @@ -3758,4 +3759,9 @@ Try enclosing path to the editor with double quotes. <string name="snapshot_quality_high">High</string> <string name="snapshot_quality_very_high">Very High</string> + <string name="TeleportMaturityExceeded">The Resident cannot visit this region.</string> + + <!-- Spell check settings floater --> + <string name="UserDictionary">[User]</string> + </strings> diff --git a/indra/newview/skins/default/xui/en/teleport_strings.xml b/indra/newview/skins/default/xui/en/teleport_strings.xml index dce6b8dd6d..fdf41991cd 100644 --- a/indra/newview/skins/default/xui/en/teleport_strings.xml +++ b/indra/newview/skins/default/xui/en/teleport_strings.xml @@ -45,6 +45,9 @@ Go to 'Welcome Island Public' to repeat the tutorial. <message name="no_inventory_host"> The inventory system is currently unavailable. </message> + <message name="MustGetAgeRegion"> + You must be age 18 or over to enter this region. + </message> </message_set> <message_set name="progress"> <message name="sending_dest"> @@ -80,5 +83,8 @@ Go to 'Welcome Island Public' to repeat the tutorial. <message name="requesting"> Requesting Teleport... </message> - </message_set> + <message name="pending"> + Pending Teleport... + </message> + </message_set> </teleport_messages> diff --git a/indra/newview/skins/default/xui/es/floater_model_wizard.xml b/indra/newview/skins/default/xui/es/floater_model_wizard.xml deleted file mode 100644 index 5bd6b5e0e5..0000000000 --- a/indra/newview/skins/default/xui/es/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="CARGAR ASISTENTE DE MODELO"> - <button label="5. Subir" name="upload_btn"/> - <button label="4. Revisar" name="review_btn"/> - <button label="3. Física" name="physics_btn"/> - <button label="2. Optimizar" name="optimize_btn"/> - <button label="1. Seleccionar archivo" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Elige el archivo de modelo - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Usuarios avanzados: si tienes experiencia con las herramientas de creación de contenidos 3D, quizá te interese utilizar la función de subida avanzada. - </text> - <button label="Cambiar al modo Avanzado" name="switch_to_advanced"/> - <text name="Cache location"> - Elige el archivo de modelo que deseas subir - </text> - <button label="Examinar..." label_selected="Examinar..." name="browse"/> - <text name="Model types"> - Second Life admite los archivos COLLADA (.dae) - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - ATENCIÓN: - </text> - <text name="warning_text"> - No podrás completar el paso final de la subida de este modelo a los servidores de Second Life. [secondlife:///app/floater/learn_more Averigua cómo] configurar tu cuenta para subir modelos de malla. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Optimizar el modelo - </text> - </panel> - <text name="optimize_description"> - Hemos optimizado el rendimiento del modelo, pero puedes ajustarlo más si lo deseas. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Generar el nivel de detalle: Alto - </text> - <text name="medium_detail_text"> - Generar el nivel de detalle: Medio - </text> - <text name="low_detail_text"> - Generar el nivel de detalle: Bajo - </text> - <text name="lowest_detail_text"> - Generar el nivel de detalle: Mínimo - </text> - </panel> - <panel name="content2"> - <button label="Recalcular la geometría" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Vista previa de geometría - </text> - <combo_box name="preview_lod_combo" tool_tip="LOD para ver en renderizado de prueba"> - <combo_item name="high"> - Detalle alto - </combo_item> - <combo_item name="medium"> - Detalles medios - </combo_item> - <combo_item name="low"> - Detalle bajo - </combo_item> - <combo_item name="lowest"> - Detalles mínimos - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Ajustar la física - </text> - </panel> - <text name="physics_description"> - Crearemos una forma para la apariencia exterior del modelo. Ajusta el nivel de detalle de la forma según se necesite para el propósito proyectado del modelo. - </text> - <panel name="physics_content"> - <button label="Recalcular física" name="recalculate_physics_btn"/> - <button label="Recalculando..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Prueba de física - </text> - <combo_box name="preview_lod_combo2" tool_tip="LOD para ver en renderizado de prueba"> - <combo_item name="high"> - Detalle alto - </combo_item> - <combo_item name="medium"> - Detalles medios - </combo_item> - <combo_item name="low"> - Detalle bajo - </combo_item> - <combo_item name="lowest"> - Detalles mínimos - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Revisar - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Impacto en la parcela/región: [EQUIV] equivalentes en prim - </text> - <text name="review_fee"> - Cargaremos en tu cuenta el precio de subida de L$ [FEE]. - </text> - <text name="review_confirmation"> - Al pulsar en el botón de subida, confirmas que posees los derechos necesarios sobre el material que contiene el modelo. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Subida finalizada - </text> - </panel> - <text name="model_uploaded_text"> - Se ha subido tu modelo. - </text> - <text name="inventory_text"> - Puedes buscar la carpeta Objetos en tu inventario. - </text> - <text name="charged_fee"> - Se han cargado [FEE] L$ en tu cuenta. - </text> - </panel> - <button label="<< Atrás" name="back"/> - <button label="Siguiente >>" name="next"/> - <button label="Calcular pesos y precio >>" name="calculate"/> - <button label="Calculando..." name="calculating"/> - <button label="Subir" name="upload" tool_tip="Cargar al simulador"/> - <button label="Cancelar" name="cancel"/> - <button label="Cerrar" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Inactivo - </string> - <string name="status_parse_error"> - Problema de análisis de DAE - consulta los datos en el registro. - </string> - <string name="status_reading_file"> - Cargando... - </string> - <string name="status_generating_meshes"> - Generando redes... - </string> - <string name="status_vertex_number_overflow"> - Error: El número de intersección es superior a 65534. Cancelado. - </string> - <string name="bad_element"> - Error: el elemento no es válido - </string> - <string name="high"> - Alto - </string> - <string name="medium"> - Media - </string> - <string name="low"> - Bajo - </string> - <string name="lowest"> - Mínimo - </string> - <string name="mesh_status_good"> - Factúralo. - </string> - <string name="mesh_status_na"> - N/A - </string> - <string name="mesh_status_none"> - Ninguno - </string> - <string name="mesh_status_submesh_mismatch"> - Los niveles de detalle poseen un número distinto de caras a las que se pueden aplicar texturas. - </string> - <string name="mesh_status_mesh_mismatch"> - Los niveles de detalle poseen un número distinto de ejemplos de red. - </string> - <string name="mesh_status_too_many_vertices"> - El nivel de detalle posee demasiadas intersecciones. - </string> - <string name="mesh_status_missing_lod"> - Falta un nivel de detalle requerido. - </string> - <string name="layer_all"> - Todo - </string> -</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_model_preview.xml b/indra/newview/skins/default/xui/fr/floater_model_preview.xml index a3b50351ae..0f272891c7 100644 --- a/indra/newview/skins/default/xui/fr/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/fr/floater_model_preview.xml @@ -214,7 +214,7 @@ </panel> </tab_container> <panel name="weights_and_warning_panel"> - <button label="Calculer les poids et les frais." name="calculate_btn" tool_tip="Calculer les poids et les frais."/> + <button label="Calculer les poids et les frais" name="calculate_btn" tool_tip="Calculer les poids et les frais."/> <button label="Annuler" name="cancel_btn"/> <button label="Charger le modèle" name="ok_btn" tool_tip="Charger dans le simulateur"/> <button label="Effacer les paramètres et réinitialiser le formulaire" name="reset_btn"/> diff --git a/indra/newview/skins/default/xui/fr/floater_model_wizard.xml b/indra/newview/skins/default/xui/fr/floater_model_wizard.xml deleted file mode 100644 index 128b9d6fa4..0000000000 --- a/indra/newview/skins/default/xui/fr/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="ASSISTANT DE CHARGEMENT DE MODÈLE"> - <button label="5. Chargement" name="upload_btn"/> - <button label="4. Vérification" name="review_btn"/> - <button label="3. Propriétés physiques" name="physics_btn"/> - <button label="2. Optimisation" name="optimize_btn"/> - <button label="1. Sélection du fichier" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Choisir un fichier de modèle - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Utilisateurs expérimentés : si vous êtes habitué à utiliser des outils de création de contenu en 3D, l'outil de chargement avancé est mis à votre disposition. - </text> - <button label="Passer à Avancé" name="switch_to_advanced"/> - <text name="Cache location"> - Choisir un fichier de modèle à charger - </text> - <button label="Parcourir..." label_selected="Parcourir..." name="browse"/> - <text name="Model types"> - Second Life prend en charge les fichiers COLLADA (.dae). - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - AVERTISSEMENT : - </text> - <text name="warning_text"> - Vous ne pourrez pas effectuer l'étape de chargement finale du modèle sur les serveurs Second Life. [secondlife:///app/floater/learn_more Découvrez comment] configurer votre compte pour le chargement de modèles de maillage. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Optimiser le modèle - </text> - </panel> - <text name="optimize_description"> - Le modèle a été optimisé en termes de performances. Vous pouvez l'ajuster si vous le souhaitez. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Générer le niveau de détail : Élevé - </text> - <text name="medium_detail_text"> - Générer le niveau de détail : Moyen - </text> - <text name="low_detail_text"> - Générer le niveau de détail : Faible - </text> - <text name="lowest_detail_text"> - Générer le niveau de détail : Le plus faible - </text> - </panel> - <panel name="content2"> - <button label="Recalcul géométrique" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Aperçu de la géométrie - </text> - <combo_box name="preview_lod_combo" tool_tip="Niveau de détail à afficher en rendu d'aperçu."> - <combo_item name="high"> - Niveau de détail élevé - </combo_item> - <combo_item name="medium"> - Niveau de détail moyen - </combo_item> - <combo_item name="low"> - Niveau de détail faible - </combo_item> - <combo_item name="lowest"> - Niveau de détail le plus faible - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Ajuster les propriétés physiques - </text> - </panel> - <text name="physics_description"> - Une forme va être créée pour l'enveloppe externe du modèle. Ajustez le niveau de détail de la forme en fonction de l'objectif souhaité pour votre modèle. - </text> - <panel name="physics_content"> - <button label="Recalcul physique" name="recalculate_physics_btn"/> - <button label="Recalcul en cours..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Aperçu des propriétés physiques - </text> - <combo_box name="preview_lod_combo2" tool_tip="Niveau de détail à afficher en rendu d'aperçu."> - <combo_item name="high"> - Niveau de détail élevé - </combo_item> - <combo_item name="medium"> - Niveau de détail moyen - </combo_item> - <combo_item name="low"> - Niveau de détail faible - </combo_item> - <combo_item name="lowest"> - Niveau de détail le plus faible - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Vérification - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Impact sur la parcelle/région : équivalent à [EQUIV] prims - </text> - <text name="review_fee"> - Votre compte sera débité de [FEE] L$ de frais de chargement. - </text> - <text name="review_confirmation"> - En cliquant sur le bouton de chargement, vous confirmez que vous disposez des droits appropriés sur le contenu du modèle. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Chargement terminé - </text> - </panel> - <text name="model_uploaded_text"> - Votre modèle a été chargé. - </text> - <text name="inventory_text"> - Vous le trouverez dans le dossier Objets de votre inventaire. - </text> - <text name="charged_fee"> - Votre compte a été débité de [FEE] L$. - </text> - </panel> - <button label="<< Préc." name="back"/> - <button label="Suiv. >>" name="next"/> - <button label="Calculer les poids et les frais >>" name="calculate"/> - <button label="Calcul en cours..." name="calculating"/> - <button label="Charger" name="upload" tool_tip="Charger dans le simulateur."/> - <button label="Annuler" name="cancel"/> - <button label="Fermer" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Inactif - </string> - <string name="status_parse_error"> - Problème d'analyse de fichier .dae ; reportez-vous au journal pour plus de détails. - </string> - <string name="status_reading_file"> - Chargement... - </string> - <string name="status_generating_meshes"> - Génération des maillages... - </string> - <string name="status_vertex_number_overflow"> - Erreur : valeur de sommet supérieure à 65534. Opération abandonnée. - </string> - <string name="bad_element"> - Erreur : élément non valide - </string> - <string name="high"> - Élevé - </string> - <string name="medium"> - Moyen - </string> - <string name="low"> - Faible - </string> - <string name="lowest"> - Le plus faible - </string> - <string name="mesh_status_good"> - Bon à publier ! - </string> - <string name="mesh_status_na"> - N/A - </string> - <string name="mesh_status_none"> - Aucun - </string> - <string name="mesh_status_submesh_mismatch"> - Un nombre différent de faces d'application de texture est associé aux niveaux de détail. - </string> - <string name="mesh_status_mesh_mismatch"> - Un nombre différent d'instances de maillage est associé aux niveaux de détail. - </string> - <string name="mesh_status_too_many_vertices"> - Trop de sommets pour le niveau de détail. - </string> - <string name="mesh_status_missing_lod"> - Niveau de détail requis manquant. - </string> - <string name="layer_all"> - Tout - </string> -</floater> diff --git a/indra/newview/skins/default/xui/it/floater_model_wizard.xml b/indra/newview/skins/default/xui/it/floater_model_wizard.xml deleted file mode 100644 index ab5fdb29e4..0000000000 --- a/indra/newview/skins/default/xui/it/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="PROCEDURA GUIDATA CARICA MODELLO"> - <button label="5. Carica sul server" name="upload_btn"/> - <button label="4. Rivedi" name="review_btn"/> - <button label="3. Fisica" name="physics_btn"/> - <button label="2. Ottimizza" name="optimize_btn"/> - <button label="1. Seleziona file" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Seleziona file modello - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Utenti avanzati: Gli utenti che hanno dimestichezza con gli strumenti di creazione 3D possono usare le opzioni di caricamento avanzate. - </text> - <button label="Passa a modalità avanzata" name="switch_to_advanced"/> - <text name="Cache location"> - Scegli il file del modello da caricare - </text> - <button label="Sfoglia..." label_selected="Sfoglia..." name="browse"/> - <text name="Model types"> - Second Life supporta file COLLADA (.dae) - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - ATTENZIONE: - </text> - <text name="warning_text"> - Non sarà possibile completare il passaggio finale per il caricamento finale di questo modello sui server di Second Life. [secondlife:///app/floater/learn_more Scopri come] impostare l'account per il caricamento di modelli con reticolo. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Ottimizza modello - </text> - </panel> - <text name="optimize_description"> - Abbiamo ottimizzato il modello per migliorare le prestazioni. Se necessario, può essere regolato ulteriormente. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Genera livello di dettaglio: Alto - </text> - <text name="medium_detail_text"> - Genera livello di dettaglio: Medio - </text> - <text name="low_detail_text"> - Genera livello di dettaglio: Basso - </text> - <text name="lowest_detail_text"> - Genera livello di dettaglio: Bassissimo - </text> - </panel> - <panel name="content2"> - <button label="Ricalcola geometria" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Anteprima geometria - </text> - <combo_box name="preview_lod_combo" tool_tip="Livello di dettaglio per anteprima rendering"> - <combo_item name="high"> - Molti dettagli - </combo_item> - <combo_item name="medium"> - Dettagli medi - </combo_item> - <combo_item name="low"> - Meno dettagli - </combo_item> - <combo_item name="lowest"> - Dettaglio minimo - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Modifica fisica - </text> - </panel> - <text name="physics_description"> - Verrà creata una forma per lo scafo esterno del modello. Regola il livello di dettaglio della forma in base al fine desiderato del modello. - </text> - <panel name="physics_content"> - <button label="Ricalcola fisica" name="recalculate_physics_btn"/> - <button label="Ricalcolo in corso..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Anteprima fisica - </text> - <combo_box name="preview_lod_combo2" tool_tip="Livello di dettaglio per anteprima rendering"> - <combo_item name="high"> - Molti dettagli - </combo_item> - <combo_item name="medium"> - Dettagli medi - </combo_item> - <combo_item name="low"> - Meno dettagli - </combo_item> - <combo_item name="lowest"> - Dettaglio minimo - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Rivedi - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Impatto sul lotto o sulla regione: [EQUIV] prim equivalenti - </text> - <text name="review_fee"> - All'account verrà accreditata una tariffa di caricamento pari a L$ [FEE]. - </text> - <text name="review_confirmation"> - Facendo clic sul pulsante Carica, confermi di possedere i diritti relativi ai materiali contenuti nel modello. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Caricamento completato - </text> - </panel> - <text name="model_uploaded_text"> - Il modello è stato caricato. - </text> - <text name="inventory_text"> - Puoi trovarlo nella cartella Oggetti nel tuo inventario. - </text> - <text name="charged_fee"> - La somma di L$ [FEE] è stata addebitata sul tuo account. - </text> - </panel> - <button label="<< Indietro" name="back"/> - <button label="Avanti >>" name="next"/> - <button label="Calcolare pesi e tariffa >>" name="calculate"/> - <button label="Calcolo in corso..." name="calculating"/> - <button label="Carica" name="upload" tool_tip="Carica al simulatore"/> - <button label="Annulla" name="cancel"/> - <button label="Chiudi" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Pausa - </string> - <string name="status_parse_error"> - Problema nell'elaborazione DAE - vedi il registro per informazioni al riguardo. - </string> - <string name="status_reading_file"> - Caricamento in corso... - </string> - <string name="status_generating_meshes"> - Generazione reticoli... - </string> - <string name="status_vertex_number_overflow"> - Errore: numero di vertici maggiore di 65534, annullato. - </string> - <string name="bad_element"> - Errore: elemento non valido - </string> - <string name="high"> - Alto - </string> - <string name="medium"> - Medio - </string> - <string name="low"> - Basso - </string> - <string name="lowest"> - Bassissimo - </string> - <string name="mesh_status_good"> - Invia! - </string> - <string name="mesh_status_na"> - N/D - </string> - <string name="mesh_status_none"> - Nessuno - </string> - <string name="mesh_status_submesh_mismatch"> - Ai vari livelli del dettaglio corrispondono numeri diversi di faccette con texture. - </string> - <string name="mesh_status_mesh_mismatch"> - Ai vari livelli del dettaglio corrispondono numeri diversi istanze di reticoli. - </string> - <string name="mesh_status_too_many_vertices"> - Troppi vertici per il livello di dettaglio. - </string> - <string name="mesh_status_missing_lod"> - Livello di dettaglio minimo mancante. - </string> - <string name="layer_all"> - Tutto - </string> -</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_model_wizard.xml b/indra/newview/skins/default/xui/ja/floater_model_wizard.xml deleted file mode 100644 index 746bd8553c..0000000000 --- a/indra/newview/skins/default/xui/ja/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="モデルウィザードをアップロード"> - <button label="5. アップロード" name="upload_btn"/> - <button label="4. 確認" name="review_btn"/> - <button label="3. 物理効果" name="physics_btn"/> - <button label="2. 最適化" name="optimize_btn"/> - <button label="1. ファイルを選択" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - モデルファイルを選択 - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - 上級ユーザーの場合:3D コンテンツ制作ツールの使用に慣れている方は、高度なアップローダーもお試しください。 - </text> - <button label="アドバンスモードに切り替える" name="switch_to_advanced"/> - <text name="Cache location"> - アップロードするモデルファイルを選択 - </text> - <button label="参照..." label_selected="参照..." name="browse"/> - <text name="Model types"> - Second Life は COLLADA (.dae) ファイルをサポートします。 - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - 警告: - </text> - <text name="warning_text"> - このモデルを Second Life サーバーにアップロードするための最終手順を実行できません。[secondlife:///app/floater/learn_more こちらを参照して]、メッシュモデルをアップロードできるようにアカウントを設定してください。 - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - モデルを最適化 - </text> - </panel> - <text name="optimize_description"> - モデルはパフォーマンスを重視して最適化されています。必要に応じて調整してください。 - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - 次の描画詳細度を作成:高 - </text> - <text name="medium_detail_text"> - 次の描画詳細度を作成:中 - </text> - <text name="low_detail_text"> - 次の描画詳細度を作成:低 - </text> - <text name="lowest_detail_text"> - 次の描画詳細度を作成:最低 - </text> - </panel> - <panel name="content2"> - <button label="ジオメトリを再計算" name="recalculate_geometry_btn"/> - <text name="lod_label"> - ジオメトリのプレビュー - </text> - <combo_box name="preview_lod_combo" tool_tip="プレビュー表示の LOD 設定"> - <combo_item name="high"> - 高い詳細度 - </combo_item> - <combo_item name="medium"> - 中の詳細度 - </combo_item> - <combo_item name="low"> - 低い詳細度 - </combo_item> - <combo_item name="lowest"> - 最低の詳細度 - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - 物理作用の調整 - </text> - </panel> - <text name="physics_description"> - モデルの外殻構造のシェイプは弊社が作成します。モデルの目的に応じてシェイプの詳細度を調整してください。 - </text> - <panel name="physics_content"> - <button label="物理作用を再計算" name="recalculate_physics_btn"/> - <button label="再計算中..." name="recalculating_physics_btn"/> - <text name="lod_label"> - 物理作用のプレビュー - </text> - <combo_box name="preview_lod_combo2" tool_tip="プレビュー表示の LOD 設定"> - <combo_item name="high"> - 高い詳細度 - </combo_item> - <combo_item name="medium"> - 中の詳細度 - </combo_item> - <combo_item name="low"> - 低い詳細度 - </combo_item> - <combo_item name="lowest"> - 最低の詳細度 - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - 確認 - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - 区画/リージョンへの負荷:[EQUIV] プリム換算値 - </text> - <text name="review_fee"> - L$ [FEE] のアップロード料金があなたのアカウントに請求されます。 - </text> - <text name="review_confirmation"> - アップロードボタンをクリックすることにより、モデルに含まれるマテリアルの所有権や使用許可の所持を認めたことになります。 - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - アップロード完了 - </text> - </panel> - <text name="model_uploaded_text"> - モデルがアップロードされました。 - </text> - <text name="inventory_text"> - それはインベントリの「オブジェクト」フォルダにあります。 - </text> - <text name="charged_fee"> - あなたのアカウントに L$ [FEE] が請求されました。 - </text> - </panel> - <button label="<< 戻る" name="back"/> - <button label="次へ>>" name="next"/> - <button label="ウェイトと料金の計算 >>" name="calculate"/> - <button label="計算中..." name="calculating"/> - <button label="アップロード" name="upload" tool_tip="シミュレーターにアップロード"/> - <button label="取り消し" name="cancel"/> - <button label="閉じる" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - 待機状態 - </string> - <string name="status_parse_error"> - Dae に問題が見つかりました - 詳細についてはログをご参照ください。 - </string> - <string name="status_reading_file"> - ローディング... - </string> - <string name="status_generating_meshes"> - メッシュを作成中 - </string> - <string name="status_vertex_number_overflow"> - エラー:頂点の数が65534を超過したので中止されました。 - </string> - <string name="bad_element"> - エラー:要素が無効です - </string> - <string name="high"> - 高 - </string> - <string name="medium"> - 中 - </string> - <string name="low"> - 低 - </string> - <string name="lowest"> - 最低 - </string> - <string name="mesh_status_good"> - 発送 - </string> - <string name="mesh_status_na"> - 該当なし - </string> - <string name="mesh_status_none"> - なし - </string> - <string name="mesh_status_submesh_mismatch"> - テクスチャ編集可能な面の数は描画詳細度に応じて異なります。 - </string> - <string name="mesh_status_mesh_mismatch"> - メッシュインスタンスの数は描画詳細度に応じて異なります。 - </string> - <string name="mesh_status_too_many_vertices"> - 描画詳細度に対して頂点の数が多すぎます。 - </string> - <string name="mesh_status_missing_lod"> - 必要な描画詳細度が見つかりません。 - </string> - <string name="layer_all"> - 全て - </string> -</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_model_wizard.xml b/indra/newview/skins/default/xui/pt/floater_model_wizard.xml deleted file mode 100644 index 0d07303c91..0000000000 --- a/indra/newview/skins/default/xui/pt/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="CARREGAR ASSISTENTE DE MODELAGEM"> - <button label="5. Carregar" name="upload_btn"/> - <button label="4. Revisar" name="review_btn"/> - <button label="3. Física" name="physics_btn"/> - <button label="2. Otimizar" name="optimize_btn"/> - <button label="1. Selecionra arquivo" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Escolher arquivo de modelo - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Usuários avançados: se você estiver familiarizado com ferramentas de criação de conteúdo 3D, use o Advanced Uploader. - </text> - <button label="Trocar para avançado" name="switch_to_advanced"/> - <text name="Cache location"> - Escolha o arquivo de modelo para upload - </text> - <button label="Procurar..." label_selected="Procurar..." name="browse"/> - <text name="Model types"> - O Second Life oferece suporte a arquivos COLLADA (.dae) - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - AVISO: - </text> - <text name="warning_text"> - Não será possível concluir a etapa final do upload desse modelo para os servidores do Second Life. [secondlife:///app/floater/learn_more Saiba como] configurar sua conta para uploads de modelos mesh. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Otimizar modelo - </text> - </panel> - <text name="optimize_description"> - O modelo foi ajustado para desempenho. Faça novos ajustes, se desejar. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Gerar nível de detalhes: Alto - </text> - <text name="medium_detail_text"> - Gerar nível de detalhes: Médio - </text> - <text name="low_detail_text"> - Gerar nível de detalhes: Baixo - </text> - <text name="lowest_detail_text"> - Gerar nível de detalhes: Mais baixo - </text> - </panel> - <panel name="content2"> - <button label="Recalcular geometria" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Visualização da geometria - </text> - <combo_box name="preview_lod_combo" tool_tip="LOD para exibir na renderização de visualização"> - <combo_item name="high"> - Máximo de detalhes - </combo_item> - <combo_item name="medium"> - Detalhes médios - </combo_item> - <combo_item name="low"> - Poucos detalhes - </combo_item> - <combo_item name="lowest"> - Mínimo de detalhes - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Ajustar físico - </text> - </panel> - <text name="physics_description"> - Criaremos uma forma para o corpo externo do modelo. Ajuste o nível de detalhes como necessário para a finalidade desejada de seu modelo. - </text> - <panel name="physics_content"> - <button label="Recalcular físico" name="recalculate_physics_btn"/> - <button label="Recalculando..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Visualização do físico - </text> - <combo_box name="preview_lod_combo2" tool_tip="LOD para exibir na renderização de visualização"> - <combo_item name="high"> - Máximo de detalhes - </combo_item> - <combo_item name="medium"> - Detalhes médios - </combo_item> - <combo_item name="low"> - Poucos detalhes - </combo_item> - <combo_item name="lowest"> - Mínimo de detalhes - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Revisar - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Impacto no lote/região: [EQUIV] equivalentes de prim - </text> - <text name="review_fee"> - Uma tarifa de upload de L$ [FEE] será debitada da sua conta. - </text> - <text name="review_confirmation"> - Ao clicar no botão de upload, você confirma que detém os direitos apropriados sobre o material contido no modelo. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Upload concluído - </text> - </panel> - <text name="model_uploaded_text"> - Seu modelo foi carregado. - </text> - <text name="inventory_text"> - Disponível na pasta Objetos do seu inventário. - </text> - <text name="charged_fee"> - L$ [FEE] foram debitados da sua conta. - </text> - </panel> - <button label="<< Voltar" name="back"/> - <button label="Próximo >>" name="next"/> - <button label="Calcular pesos e tarifa >>" name="calculate"/> - <button label="Calculando..." name="calculating"/> - <button label="Carregar" name="upload" tool_tip="Carregar no simulador"/> - <button label="Cancelar" name="cancel"/> - <button label="Fechar" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Inativo - </string> - <string name="status_parse_error"> - Dae parsing - erro, detalhes no log. - </string> - <string name="status_reading_file"> - Carregando... - </string> - <string name="status_generating_meshes"> - Gerando meshes... - </string> - <string name="status_vertex_number_overflow"> - Erro: Número de Vertex acima de 65534. Abortado. - </string> - <string name="bad_element"> - Erro: elemento inválido - </string> - <string name="high"> - Alto - </string> - <string name="medium"> - Médio - </string> - <string name="low"> - Baixo - </string> - <string name="lowest"> - Mais baixo - </string> - <string name="mesh_status_good"> - Entregar! - </string> - <string name="mesh_status_na"> - N/D - </string> - <string name="mesh_status_none"> - Nenhum - </string> - <string name="mesh_status_submesh_mismatch"> - Cada nível de detalhamento têm um número de faces para textura. - </string> - <string name="mesh_status_mesh_mismatch"> - Cada nível de detalhamento têm um número de faces para textura. - </string> - <string name="mesh_status_too_many_vertices"> - O nível de detalhamento possui vértices demais. - </string> - <string name="mesh_status_missing_lod"> - Falta o nível de detalhamento necessário. - </string> - <string name="layer_all"> - Tudo - </string> -</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_model_wizard.xml b/indra/newview/skins/default/xui/ru/floater_model_wizard.xml deleted file mode 100644 index c1a63bf7da..0000000000 --- a/indra/newview/skins/default/xui/ru/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="ПЕРЕДАТЬ МАСТЕР МОДЕЛИРОВАНИЯ"> - <button label="5. Передать" name="upload_btn"/> - <button label="4. Просмотр" name="review_btn"/> - <button label="3. Физика" name="physics_btn"/> - <button label="2. Оптимизировать" name="optimize_btn"/> - <button label="1. Выбрать файл" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Выберите файл модели - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Пользователям, работающим в расширенном режиме: если вы умеете создавать трехмерные графические объекты, то, возможно, захотите воспользоваться средством Advanced Uploader, которое предоставляет расширенные возможности передачи объектов. - </text> - <button label="Перейти в расширенный режим" name="switch_to_advanced"/> - <text name="Cache location"> - Выберите файл модели для передачи - </text> - <button label="Обзор..." label_selected="Обзор..." name="browse"/> - <text name="Model types"> - В Second Life поддерживаются файлы COLLADA (.dae) - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - ВНИМАНИЕ! - </text> - <text name="warning_text"> - Вы не сможете завершить передачу этой модели на серверы Second Life. [secondlife:///app/floater/learn_more Узнайте, как] настроить в вашем аккаунте передачу сеточных моделей. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Оптимизировать модель - </text> - </panel> - <text name="optimize_description"> - Мы оптимизировали модель для повышения быстродействия. По желанию можно выполнить дополнительную настройку. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Создать уровень детализации: Высокий - </text> - <text name="medium_detail_text"> - Создать уровень детализации: Средний - </text> - <text name="low_detail_text"> - Создать уровень детализации: Низкий - </text> - <text name="lowest_detail_text"> - Создать уровень детализации: Самый низкий - </text> - </panel> - <panel name="content2"> - <button label="Пересчитать геометрию" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Просмотр геометрии - </text> - <combo_box name="preview_lod_combo" tool_tip="Детализация при предварительном просмотре"> - <combo_item name="high"> - Детально - </combo_item> - <combo_item name="medium"> - Средняя детализация - </combo_item> - <combo_item name="low"> - Мало деталей - </combo_item> - <combo_item name="lowest"> - Минимум деталей - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Настроить физические параметры - </text> - </panel> - <text name="physics_description"> - Мы создадим форму для внешнего каркаса модели. Настройте уровень детализации формы в соответствии с целями, для которых предназначена модель. - </text> - <panel name="physics_content"> - <button label="Пересчитать физические данные" name="recalculate_physics_btn"/> - <button label="Пересчет..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Просмотр физических данных - </text> - <combo_box name="preview_lod_combo2" tool_tip="Уровень детализации при предварительном просмотре"> - <combo_item name="high"> - Детально - </combo_item> - <combo_item name="medium"> - Средняя детализация - </combo_item> - <combo_item name="low"> - Мало деталей - </combo_item> - <combo_item name="lowest"> - Минимум деталей - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Просмотр - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Воздействие на участок/регион: эквивалент в примитивах: [EQUIV] - </text> - <text name="review_fee"> - За передачу с вашего счета будет снята плата в размере L$[FEE]. - </text> - <text name="review_confirmation"> - Нажав кнопку «Передать», вы подтверждаете, что у вас есть надлежащие права на все составляющие модели. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Передача завершена - </text> - </panel> - <text name="model_uploaded_text"> - Ваша модель передана. - </text> - <text name="inventory_text"> - Находится в папке «Объекты» вашего инвентаря. - </text> - <text name="charged_fee"> - С вашего счета снято: L$[FEE]. - </text> - </panel> - <button label="<< Назад" name="back"/> - <button label="Далее >>" name="next"/> - <button label="Рассчитать вес и плату >>" name="calculate"/> - <button label="Расчет..." name="calculating"/> - <button label="Передать" name="upload" tool_tip="Передать в симулятор"/> - <button label="Отмена" name="cancel"/> - <button label="Закрыть" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Неактивно - </string> - <string name="status_parse_error"> - Проблема при анализе файла DAE – см. подробности в журнале. - </string> - <string name="status_reading_file"> - Загрузка... - </string> - <string name="status_generating_meshes"> - Создаются меши... - </string> - <string name="status_vertex_number_overflow"> - Ошибка. Число вершин превышает 65534. Прервано. - </string> - <string name="bad_element"> - Ошибка: недопустимый элемент - </string> - <string name="high"> - высокий - </string> - <string name="medium"> - средний - </string> - <string name="low"> - низкий - </string> - <string name="lowest"> - самый низкий - </string> - <string name="mesh_status_good"> - Доставлено! - </string> - <string name="mesh_status_na"> - Н/Д - </string> - <string name="mesh_status_none"> - Нет - </string> - <string name="mesh_status_submesh_mismatch"> - Отличается число текстурируемых граней на уровнях детализации. - </string> - <string name="mesh_status_mesh_mismatch"> - Отличается число экземпляров меша на уровнях детализации. - </string> - <string name="mesh_status_too_many_vertices"> - Слишком много вершин на уровне детализации. - </string> - <string name="mesh_status_missing_lod"> - Отсутствует необходимый уровень детализации. - </string> - <string name="layer_all"> - Все - </string> -</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_model_wizard.xml b/indra/newview/skins/default/xui/tr/floater_model_wizard.xml deleted file mode 100644 index 9d8b982c24..0000000000 --- a/indra/newview/skins/default/xui/tr/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="KARŞIYA MODEL YÜKLEME SİHİRBAZI"> - <button label="5. Karşıya Yükle" name="upload_btn"/> - <button label="4. İncele" name="review_btn"/> - <button label="3. Fizik" name="physics_btn"/> - <button label="2. Optimize et" name="optimize_btn"/> - <button label="1. Dosya Seç" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Model dosyasını seçin - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Gelişmiş kullanıcılar: Eğer 3B içerik oluşturma araçlarını kullanmayı biliyorsanız, Gelişmiş Karşıya Yükleyiciyi kullanmak isteyebilirsiniz. - </text> - <button label="Gelişmişe geç" name="switch_to_advanced"/> - <text name="Cache location"> - Karşıya yüklenecek model dosyasını seçin - </text> - <button label="Gözat..." label_selected="Gözat..." name="browse"/> - <text name="Model types"> - Second Life, COLLADA (.dae) dosyalarını destekler - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - UYARI: - </text> - <text name="warning_text"> - Bu modelin Second Life sunucularına nihai karşıya yükleme adımını tamamlayamayacaksınız. Hesabınızı örgü modellerinin karşıya yüklenmesi için ayarlamanın [secondlife:///app/floater/learn_more nasıl yapılacağını öğrenin]. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Modeli optimize et - </text> - </panel> - <text name="optimize_description"> - Modeli performans için optimize ettik. İstiyorsanız daha da ayarlayabilirsiniz. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Ayrıntı Seviyesi Oluştur: Yüksek - </text> - <text name="medium_detail_text"> - Ayrıntı Seviyesi Oluştur: Orta - </text> - <text name="low_detail_text"> - Ayrıntı Seviyesi Oluştur: Düşük - </text> - <text name="lowest_detail_text"> - Ayrıntı Seviyesi Oluştur: En Düşük - </text> - </panel> - <panel name="content2"> - <button label="Geometri hesaplarını tekrar yap" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Geometri önizleme - </text> - <combo_box name="preview_lod_combo" tool_tip="Önizleme işlemesinde görülecek ayrıntı seviyesi"> - <combo_item name="high"> - Çok ayrıntı - </combo_item> - <combo_item name="medium"> - Orta düzey ayrıntı - </combo_item> - <combo_item name="low"> - Az ayrıntı - </combo_item> - <combo_item name="lowest"> - En az ayrıntı - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Fizik ayarlarını yap - </text> - </panel> - <text name="physics_description"> - Modelin dış gövdesi için bir şekil oluşturacağız. Modelinizin amacına uygun olarak şeklin ayrıntı seviyesini belirleyin. - </text> - <panel name="physics_content"> - <button label="Fizik hesaplarını tekrar yap" name="recalculate_physics_btn"/> - <button label="Tekrar hesaplanıyor..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Fizik önizleme - </text> - <combo_box name="preview_lod_combo2" tool_tip="Önizleme işlemesinde görülecek ayrıntı seviyesi"> - <combo_item name="high"> - Çok ayrıntı - </combo_item> - <combo_item name="medium"> - Orta düzey ayrıntı - </combo_item> - <combo_item name="low"> - Az ayrıntı - </combo_item> - <combo_item name="lowest"> - En az ayrıntı - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - İncele - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Parsele/bölgeye etkisi: [EQUIV] prim eşdeğerleri - </text> - <text name="review_fee"> - Hesabınızdan L$ [FEE] karşıya yükleme ücreti düşülecektir. - </text> - <text name="review_confirmation"> - Karşıya yükleme düğmesine tıkladığınızda, modelde yer alan malzeme için ilgili haklara sahip olduğunuzu teyid edersiniz. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Karşıya yükleme bitti - </text> - </panel> - <text name="model_uploaded_text"> - Modeliniz karşıya yüklendi. - </text> - <text name="inventory_text"> - Bunu, envanterinizdeki Nesneler klasöründe bulacaksınız. - </text> - <text name="charged_fee"> - Hesabınızdan L$ [FEE] düşüldü. - </text> - </panel> - <button label="<< Geri" name="back"/> - <button label="Sonraki >>" name="next"/> - <button label="Ağırlıkları ve ücreti hesapla >>" name="calculate"/> - <button label="Hesaplanıyor..." name="calculating"/> - <button label="Karşıya Yükle" name="upload" tool_tip="Simülatöre karşıya yükle"/> - <button label="İptal" name="cancel"/> - <button label="Kapat" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Boşta - </string> - <string name="status_parse_error"> - Dae ayrıştırma sorunu - ayrıntılar için günlüğe bakın. - </string> - <string name="status_reading_file"> - Yükleniyor... - </string> - <string name="status_generating_meshes"> - Örgüler Oluşturuluyor... - </string> - <string name="status_vertex_number_overflow"> - Hata: Köşe numarası 65534'ten fazla, işlem durduruldu! - </string> - <string name="bad_element"> - Hata: Öğe geçersiz - </string> - <string name="high"> - Yüksek - </string> - <string name="medium"> - Orta - </string> - <string name="low"> - Düşük - </string> - <string name="lowest"> - En Düşük - </string> - <string name="mesh_status_good"> - Uygula! - </string> - <string name="mesh_status_na"> - G/D - </string> - <string name="mesh_status_none"> - Hiçbiri - </string> - <string name="mesh_status_submesh_mismatch"> - Ayrıntı seviyelerinde farklı sayıda dokulanabilir yüz var. - </string> - <string name="mesh_status_mesh_mismatch"> - Ayrıntı seviyelerinde farklı sayıda örgü örneği var. - </string> - <string name="mesh_status_too_many_vertices"> - Ayrıntı seviyesinde fazla sayıda köşe var. - </string> - <string name="mesh_status_missing_lod"> - Gereken ayrıntı seviyesi eksik. - </string> - <string name="layer_all"> - Tümü - </string> -</floater> diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index c970d79975..0141a219c5 100644 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -111,18 +111,6 @@ namespace tut ensure("1 isMature", !aa.isMature()); ensure("1 isAdult", !aa.isAdult()); - // this is kinda bad -- setting this forces maturity to MATURE but !teen != Mature anymore - aa.setTeen(false); - ensure("2 isTeen", !aa.isTeen()); - ensure("2 isMature", aa.isMature()); - ensure("2 isAdult", !aa.isAdult()); - - // have to flip it back and make sure it still works - aa.setTeen(true); - ensure("3 isTeen", aa.isTeen()); - ensure("3 isMature", !aa.isMature()); - ensure("3 isAdult", !aa.isAdult()); - // check the conversion routine ensure_equals("1 conversion", SIM_ACCESS_PG, aa.convertTextToMaturity('P')); ensure_equals("2 conversion", SIM_ACCESS_MATURE, aa.convertTextToMaturity('M')); @@ -131,21 +119,21 @@ namespace tut // now try the other method of setting it - PG aa.setMaturity('P'); - ensure("4 isTeen", aa.isTeen()); - ensure("4 isMature", !aa.isMature()); - ensure("4 isAdult", !aa.isAdult()); + ensure("2 isTeen", aa.isTeen()); + ensure("2 isMature", !aa.isMature()); + ensure("2 isAdult", !aa.isAdult()); // Mature aa.setMaturity('M'); - ensure("5 isTeen", !aa.isTeen()); - ensure("5 isMature", aa.isMature()); - ensure("5 isAdult", !aa.isAdult()); + ensure("3 isTeen", !aa.isTeen()); + ensure("3 isMature", aa.isMature()); + ensure("3 isAdult", !aa.isAdult()); // Adult aa.setMaturity('A'); - ensure("6 isTeen", !aa.isTeen()); - ensure("6 isMature", aa.isMature()); - ensure("6 isAdult", aa.isAdult()); + ensure("4 isTeen", !aa.isTeen()); + ensure("4 isMature", aa.isMature()); + ensure("4 isAdult", aa.isAdult()); } @@ -239,18 +227,6 @@ namespace tut cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); LLAgentAccess aa(cgr); - ensure("1 transition starts false", !aa.isInTransition()); - aa.setTransition(); - ensure("2 transition now true", aa.isInTransition()); - } - - template<> template<> - void agentaccess_object_t::test<6>() - { - LLControlGroup cgr("test"); - cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); - LLAgentAccess aa(cgr); - cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT); aa.setMaturity('M'); ensure("1 preferred maturity pegged to M when maturity is M", cgr.getU32("PreferredMaturity") == SIM_ACCESS_MATURE); diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 36267803e3..d1c952ac3b 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -91,6 +91,13 @@ class ViewerManifest(LLManifest): # ... and the entire windlight directory self.path("windlight") + + # ... and the included spell checking dictionaries + pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') + if self.prefix(src=pkgdir,dst=""): + self.path("dictionaries") + self.end_prefix(pkgdir) + self.end_prefix("app_settings") if self.prefix(src="character"): @@ -393,6 +400,9 @@ class WindowsManifest(ViewerManifest): self.path("ssleay32.dll") self.path("libeay32.dll") + # Hunspell + self.path("libhunspell.dll") + # For google-perftools tcmalloc allocator. try: if self.args['configuration'].lower() == 'debug': @@ -659,6 +669,7 @@ class DarwinManifest(ViewerManifest): # copy additional libs in <bundle>/Contents/MacOS/ self.path("../packages/lib/release/libndofdev.dylib", dst="Resources/libndofdev.dylib") + self.path("../packages/lib/release/libhunspell-1.3.0.dylib", dst="Resources/libhunspell-1.3.0.dylib") self.path("../viewer_components/updater/scripts/darwin/update_install", "MacOS/update_install") @@ -1043,10 +1054,15 @@ class Linux_i686Manifest(LinuxManifest): self.path("libopenjpeg.so*") self.path("libdirectfb-1.4.so.5") self.path("libfusion-1.4.so.5") + self.path("libdirect-1.4.so.5.0.4") self.path("libdirect-1.4.so.5") + self.path("libhunspell-1.3.so") + self.path("libhunspell-1.3.so.0") + self.path("libhunspell-1.3.so.0.0.0") self.path("libalut.so") self.path("libopenal.so", "libopenal.so.1") self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname + # KLUDGE: As of 2012-04-11, the 'fontconfig' package installs # libfontconfig.so.1.4.4, along with symlinks libfontconfig.so.1 # and libfontconfig.so. Before we added support for library-file |