From e4a1b12e7a9c4bb8cbc2a1e41fddb8cec5a1b1e0 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 15 Dec 2011 12:48:07 -0500 Subject: SH-2789 WIP - build without tcmalloc, force alignment in various places --- indra/cmake/FindGooglePerfTools.cmake | 2 ++ indra/cmake/GooglePerfTools.cmake | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) mode change 100644 => 100755 indra/cmake/FindGooglePerfTools.cmake mode change 100644 => 100755 indra/cmake/GooglePerfTools.cmake (limited to 'indra/cmake') diff --git a/indra/cmake/FindGooglePerfTools.cmake b/indra/cmake/FindGooglePerfTools.cmake old mode 100644 new mode 100755 index bb125d538e..1c785d3461 --- a/indra/cmake/FindGooglePerfTools.cmake +++ b/indra/cmake/FindGooglePerfTools.cmake @@ -64,3 +64,5 @@ MARK_AS_ADVANCED( PROFILER_LIBRARY GOOGLE_PERFTOOLS_INCLUDE_DIR ) + +SET(GOOGLE_PERFTOOLS_FOUND "NO") diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake old mode 100644 new mode 100755 index d9f91193be..2e96912769 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -29,7 +29,7 @@ if (GOOGLE_PERFTOOLS_FOUND) endif (GOOGLE_PERFTOOLS_FOUND) if (WINDOWS) - set(USE_GOOGLE_PERFTOOLS ON) + set(USE_GOOGLE_PERFTOOLS OFF) endif (WINDOWS) if (USE_GOOGLE_PERFTOOLS) -- cgit v1.3 From ba67b9359f13968b13b1facbb1e4c7948405b767 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 5 Jan 2012 17:37:02 -0500 Subject: SH-2789 WIP - allow building with or without tcmalloc, default to tcmalloc enabled --- indra/cmake/FindGooglePerfTools.cmake | 2 -- indra/cmake/GooglePerfTools.cmake | 38 ++++++++++++++++++++++++++--------- indra/newview/CMakeLists.txt | 13 +++++++----- 3 files changed, 36 insertions(+), 17 deletions(-) (limited to 'indra/cmake') diff --git a/indra/cmake/FindGooglePerfTools.cmake b/indra/cmake/FindGooglePerfTools.cmake index 1c785d3461..bb125d538e 100755 --- a/indra/cmake/FindGooglePerfTools.cmake +++ b/indra/cmake/FindGooglePerfTools.cmake @@ -64,5 +64,3 @@ MARK_AS_ADVANCED( PROFILER_LIBRARY GOOGLE_PERFTOOLS_INCLUDE_DIR ) - -SET(GOOGLE_PERFTOOLS_FOUND "NO") diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 2e96912769..0c31d73655 100755 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -1,20 +1,32 @@ # -*- 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) + else (USE_TCMALLOC) + set(TCMALLOC_LIBRARIES) + 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 +41,19 @@ if (GOOGLE_PERFTOOLS_FOUND) endif (GOOGLE_PERFTOOLS_FOUND) if (WINDOWS) - set(USE_GOOGLE_PERFTOOLS OFF) + set(USE_GOOGLE_PERFTOOLS ON) endif (WINDOWS) -if (USE_GOOGLE_PERFTOOLS) +# Apparently buggy - LL_USE_TCMALLOC never gets set. Fix when we have time to test the +# corresponding source code. +if (USE_TCMALLOC) set(TCMALLOC_FLAG -ULL_USE_TCMALLOC=1) +else (USE_TCMALLOC) + set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) +endif (USE_TCMALLOC) + +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/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 825cbbef8f..00cf1ba8df 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1505,12 +1505,15 @@ set(PACKAGE ON CACHE BOOL "Add a package target that builds an installer package.") if (WINDOWS) + if (USE_TCMALLOC) + set(TCMALLOC_INCLUDE_FLAGS "/INCLUDE:__tcmalloc") + else (USE_TCMALLOC) + set(TCMALLOC_INCLUDE_FLAGS) + endif (USE_TCMALLOC) + 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" + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_INCLUDE_FLAGS}" LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO" LINK_FLAGS_RELEASE "" ) @@ -1765,7 +1768,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${CRYPTO_LIBRARIES} ${LLLOGIN_LIBRARIES} ${LLCONVEXDECOMP_LIBRARY} -# ${TCMALLOC_LIBRARIES} + ${TCMALLOC_LIBRARIES} ) if (USE_KDU) -- cgit v1.3 From d3b0a1375509f772ec3ddbc790b5a5d9f4fa7594 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 5 Jan 2012 18:24:42 -0500 Subject: SH-2789 WIP - fix for linux build failure --- indra/cmake/GooglePerfTools.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/cmake') diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 0c31d73655..834da6d9b8 100755 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -47,7 +47,7 @@ endif (WINDOWS) # Apparently buggy - LL_USE_TCMALLOC never gets set. Fix when we have time to test the # corresponding source code. if (USE_TCMALLOC) - set(TCMALLOC_FLAG -ULL_USE_TCMALLOC=1) + set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) # was -ULL_USE_TCMALLOC=1 which makes no sense. else (USE_TCMALLOC) set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) endif (USE_TCMALLOC) -- cgit v1.3 From bfe6e94f5388b887253ba77f633ae332affe9f92 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 6 Jan 2012 13:01:17 -0500 Subject: SH-2789 WIP - fixing the LL_USE_TCMALLOC code, make tests build with the same tcmalloc options as the sl executable --- indra/cmake/GooglePerfTools.cmake | 16 +++++++++------- indra/cmake/LLAddBuildTest.cmake | 9 +++++++++ indra/llcommon/llallocator.cpp | 2 +- indra/newview/CMakeLists.txt | 8 +------- 4 files changed, 20 insertions(+), 15 deletions(-) mode change 100644 => 100755 indra/cmake/LLAddBuildTest.cmake mode change 100644 => 100755 indra/llcommon/llallocator.cpp (limited to 'indra/cmake') diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 834da6d9b8..09501e0406 100755 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -14,8 +14,10 @@ else (STANDALONE) 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) @@ -44,13 +46,13 @@ if (WINDOWS) set(USE_GOOGLE_PERFTOOLS ON) endif (WINDOWS) -# Apparently buggy - LL_USE_TCMALLOC never gets set. Fix when we have time to test the -# corresponding source code. -if (USE_TCMALLOC) - set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) # was -ULL_USE_TCMALLOC=1 which makes no sense. -else (USE_TCMALLOC) - set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) -endif (USE_TCMALLOC) +if (USE_GOOGLE_PERFTOOLS) + 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}) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake old mode 100644 new mode 100755 index 08feab6e36..a6f69a09e9 --- 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/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp old mode 100644 new mode 100755 index 6f6abefc67..87654b5b97 --- 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/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 00cf1ba8df..f929e8d379 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1505,15 +1505,9 @@ set(PACKAGE ON CACHE BOOL "Add a package target that builds an installer package.") if (WINDOWS) - if (USE_TCMALLOC) - set(TCMALLOC_INCLUDE_FLAGS "/INCLUDE:__tcmalloc") - else (USE_TCMALLOC) - set(TCMALLOC_INCLUDE_FLAGS) - endif (USE_TCMALLOC) - set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES - LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_INCLUDE_FLAGS}" + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_LINK_FLAGS}" LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO" LINK_FLAGS_RELEASE "" ) -- cgit v1.3 From c0fffdea8812e5eed8da9f341d3bfc9590301ada Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 12 Jan 2012 16:11:06 -0500 Subject: SH-2789 WIP --- indra/cmake/GooglePerfTools.cmake | 2 +- indra/llui/llview.cpp | 2 +- indra/newview/llappviewerwin32.cpp | 2 +- indra/newview/llface.cpp | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'indra/cmake') diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 09501e0406..73b3642ae6 100755 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -3,7 +3,7 @@ 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) +set (USE_TCMALLOC OFF) if (STANDALONE) include(FindGooglePerfTools) diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 542f57ee5f..7abe4ecd9f 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -283,7 +283,7 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child) bool LLView::addChild(LLView* child, S32 tab_group) { // NOTE: Changed this to not crash in release mode - llassert(mInDraw == false); + //llassert(mInDraw == false); if (!child) { diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 647ace7ee3..8087453ee5 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -117,7 +117,7 @@ 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 - _CrtSetDbgFlag(0); // default, just making explicit + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // default, just making explicit ULONG ulEnableLFH = 2; HANDLE* hHeaps = new HANDLE[MAX_HEAPS]; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 6dbeae6677..f60f311b9e 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1377,7 +1377,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { if (!do_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 { -- cgit v1.3 From 9c66ac87fd46db3987e60ae50989b2497099480b Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Fri, 20 Jan 2012 18:06:32 +0100 Subject: STORM-276 Basic spellchecking framework --- indra/cmake/Copy3rdPartyLibs.cmake | 3 + indra/cmake/ViewerMiscLibs.cmake | 1 + indra/llui/CMakeLists.txt | 3 + indra/llui/llmenugl.cpp | 6 +- indra/llui/llmenugl.h | 6 +- indra/llui/llspellcheck.cpp | 345 ++++++++++++++++++++++++++++++++ indra/llui/llspellcheck.h | 77 +++++++ indra/llui/llspellcheckmenuhandler.h | 46 +++++ indra/newview/app_settings/settings.xml | 22 ++ indra/newview/llappviewer.cpp | 14 ++ indra/newview/llstartup.cpp | 1 + indra/newview/llviewercontrol.cpp | 24 +++ indra/newview/llviewermenu.cpp | 86 ++++++++ indra/newview/llviewermenu.h | 1 + indra/newview/viewer_manifest.py | 8 + 15 files changed, 641 insertions(+), 2 deletions(-) create mode 100644 indra/llui/llspellcheck.cpp create mode 100644 indra/llui/llspellcheck.h create mode 100644 indra/llui/llspellcheckmenuhandler.h (limited to 'indra/cmake') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 394db362b1..ebeae3e5be 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,6 +54,7 @@ if(WINDOWS) libeay32.dll libcollada14dom22.dll glod.dll + libhunspell.dll ) if(USE_GOOGLE_PERFTOOLS) @@ -215,6 +217,7 @@ elseif(DARWIN) libllqtwebkit.dylib libminizip.a libndofdev.dylib + libhunspell-1.3.dylib libexception_handler.dylib libcollada14dom.dylib ) 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/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 772f173f17..1377336bb4 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -87,6 +87,7 @@ set(llui_SOURCE_FILES llsearcheditor.cpp llslider.cpp llsliderctrl.cpp + llspellcheck.cpp llspinctrl.cpp llstatbar.cpp llstatgraph.cpp @@ -192,6 +193,8 @@ set(llui_HEADER_FILES llsdparam.h llsliderctrl.h llslider.h + llspellcheck.h + llspellcheckmenuhandler.h llspinctrl.h llstatbar.h llstatgraph.h diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 95ecbb1c94..2a65262bbb 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,10 @@ 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 getHandle() { return getDerivedHandle(); } + LLView* getSpawningView() const { return mSpawningViewHandle.get(); } + void setSpawningView(LLHandle spawning_view) { mSpawningViewHandle = spawning_view; } + protected: BOOL mHoveredAnyItem; LLMenuItemGL* mHoverItem; LLRootHandle mHandle; + LLHandle mSpawningViewHandle; }; diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp new file mode 100644 index 0000000000..433ca02852 --- /dev/null +++ b/indra/llui/llspellcheck.cpp @@ -0,0 +1,345 @@ +/** + * @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 + #pragma comment(lib, "libhunspell.lib") +#else + #include +#endif + +static const std::string DICT_DIR = "dictionaries"; +static const std::string DICT_CUSTOM_SUFFIX = "_custom"; +static const std::string DICT_IGNORE_SUFFIX = "_ignore"; + +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& 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(); +} + +const LLSD LLSpellChecker::getDictionaryData(const std::string& dict_name) const +{ + for (LLSD::array_const_iterator it = mDictMap.beginArray(); it != mDictMap.endArray(); ++it) + { + const LLSD& dict_entry = *it; + if (dict_name == dict_entry["language"].asString()) + return dict_entry; + } + return LLSD(); +} + +void LLSpellChecker::refreshDictionaryMap() +{ + const std::string app_path = getDictionaryAppPath(); + const std::string user_path = getDictionaryUserPath(); + + // Load dictionary information (file name, friendly name, ...) + llifstream user_map(user_path + "dictionaries.xml", std::ios::binary); + if ( (!user_map.is_open()) || (0 == LLSDSerialize::fromXMLDocument(mDictMap, user_map)) || (0 == mDictMap.size()) ) + { + llifstream app_map(app_path + "dictionaries.xml", std::ios::binary); + if ( (!app_map.is_open()) || (0 == LLSDSerialize::fromXMLDocument(mDictMap, app_map)) || (0 == mDictMap.size()) ) + return; + } + + // Look for installed dictionaries + std::string tmp_app_path, tmp_user_path; + for (LLSD::array_iterator it = mDictMap.beginArray(); it != mDictMap.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 + ".aff")) && (gDirUtilp->fileExists(tmp_user_path + ".dic"))) || + ((gDirUtilp->fileExists(tmp_app_path + ".aff")) && (gDirUtilp->fileExists(tmp_app_path + ".dic"))) ); + sdDict["has_custom"] = (!tmp_user_path.empty()) && (gDirUtilp->fileExists(tmp_user_path + DICT_CUSTOM_SUFFIX + ".dic")); + sdDict["has_ignore"] = (!tmp_user_path.empty()) && (gDirUtilp->fileExists(tmp_user_path + DICT_IGNORE_SUFFIX + ".dic")); + } +} + +void LLSpellChecker::addToCustomDictionary(const std::string& word) +{ + if (mHunspell) + { + mHunspell->add(word.c_str()); + } + addToDictFile(getDictionaryUserPath() + mDictFile + DICT_CUSTOM_SUFFIX + ".dic", 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() + mDictFile + DICT_IGNORE_SUFFIX + ".dic", word_lower); + sSettingsChangeSignal(); + } +} + +void LLSpellChecker::addToDictFile(const std::string& dict_path, const std::string& word) +{ + std::vector 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::const_iterator itWord = word_list.begin(); itWord != word_list.end(); ++itWord) + file_out << *itWord << std::endl; + file_out.close(); + } +} + +void LLSpellChecker::setSecondaryDictionaries(std::list dict_list) +{ + if (!getUseSpellCheck()) + { + return; + } + + // Check if we're only adding secondary dictionaries, or removing them + std::list dict_add(llmax(dict_list.size(), mDictSecondary.size())), dict_rem(llmax(dict_list.size(), mDictSecondary.size())); + dict_list.sort(); + mDictSecondary.sort(); + std::list::iterator end_added = std::set_difference(dict_list.begin(), dict_list.end(), mDictSecondary.begin(), mDictSecondary.end(), dict_add.begin()); + std::list::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_name = mDictName; + initHunspell(dict_name); + } + 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 (std::list::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_name) +{ + if (mHunspell) + { + delete mHunspell; + mHunspell = NULL; + mDictName.clear(); + mDictFile.clear(); + mIgnoreList.clear(); + } + + const LLSD dict_entry = (!dict_name.empty()) ? getDictionaryData(dict_name) : LLSD(); + if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].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; + + mDictName = dict_name; + mDictFile = dict_entry["name"].asString(); + + if (dict_entry["has_custom"].asBoolean()) + { + const std::string filename_dic = user_path + mDictFile + DICT_CUSTOM_SUFFIX + ".dic"; + mHunspell->add_dic(filename_dic.c_str()); + } + + if (dict_entry["has_ignore"].asBoolean()) + { + llifstream file_in(user_path + mDictFile + DICT_IGNORE_SUFFIX + ".dic", 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 (std::list::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 +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_name) +{ + if ( (((dict_name.empty()) && (getUseSpellCheck())) || (!dict_name.empty())) && + (LLSpellChecker::instance().mDictName != dict_name) ) + { + LLSpellChecker::instance().initHunspell(dict_name); + } +} diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h new file mode 100644 index 0000000000..affdac2907 --- /dev/null +++ b/indra/llui/llspellcheck.h @@ -0,0 +1,77 @@ +/** + * @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 + +class Hunspell; + +class LLSpellChecker : public LLSingleton +{ + friend class LLSingleton; +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& suggestions) const; + +public: + const LLSD getDictionaryData(const std::string& dict_name) const; + const LLSD& getDictionaryMap() const { return mDictMap; } + void refreshDictionaryMap(); + void setSecondaryDictionaries(std::list dictList); +protected: + void addToDictFile(const std::string& dict_path, const std::string& word); + void initHunspell(const std::string& dict_name); + +public: + static const std::string getDictionaryAppPath(); + static const std::string getDictionaryUserPath(); + static bool getUseSpellCheck(); + static void setUseSpellCheck(const std::string& dict_name); + + typedef boost::signals2::signal settings_change_signal_t; + static boost::signals2::connection setSettingsChangeCallback(const settings_change_signal_t::slot_type& cb); + +protected: + Hunspell* mHunspell; + std::string mDictName; + std::string mDictFile; + LLSD mDictMap; + std::list mDictSecondary; + std::vector mIgnoreList; + + 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/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 1ea623791d..1ad3ee1dd1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12082,6 +12082,28 @@ Value 10.0 + SpellCheck + + Comment + Enable spellchecking on line and text editors + Persist + 1 + Type + Boolean + Value + 1 + + SpellCheckDictionary + + Comment + Current primary and secondary dictionaries used for spell checking + Persist + 1 + Type + String + Value + English (United States) + UseNewWalkRun Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0861fe85a8..698f2469a3 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -91,6 +91,7 @@ #include "llsecondlifeurls.h" #include "llupdaterservice.h" #include "llcallfloater.h" +#include "llspellcheck.h" // Linden library includes #include "llavatarnamecache.h" @@ -112,6 +113,7 @@ // Third party library includes #include #include +#include @@ -2488,6 +2490,18 @@ bool LLAppViewer::initConfiguration() //gDirUtilp->setSkinFolder("default"); } + if (gSavedSettings.getBOOL("SpellCheck")) + { + std::list dict_list; + boost::split(dict_list, gSavedSettings.getString("SpellCheckDictionary"), 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. diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 7e02a41e7e..89360778d1 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -739,6 +739,7 @@ bool idle_startup() { display_startup(); initialize_edit_menu(); + initialize_spellcheck_menu(); display_startup(); init_menus(); display_startup(); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 093b84413a..7b6dbfaa0b 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 + #ifdef TOGGLE_HACKED_GODLIKE_VIEWER BOOL gHackGodmode = FALSE; #endif @@ -498,6 +502,24 @@ bool handleForceShowGrid(const LLSD& newvalue) return true; } +bool handleSpellCheckChanged() +{ + if (gSavedSettings.getBOOL("SpellCheck")) + { + std::list dict_list; + boost::split(dict_list, gSavedSettings.getString("SpellCheckDictionary"), 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() ) @@ -704,6 +726,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/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 0104d35e53..2a11f3cc16 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -81,6 +81,7 @@ #include "llrootview.h" #include "llsceneview.h" #include "llselectmgr.h" +#include "llspellcheckmenuhandler.h" #include "llstatusbar.h" #include "lltextureview.h" #include "lltoolcomp.h" @@ -4984,6 +4985,78 @@ class LLEditDelete : public view_listener_t } }; +void handle_spellcheck_replace_with_suggestion(const LLUICtrl* ctrl, const LLSD& param) +{ + const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(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(ctrl); + const LLContextMenu* menu = (item) ? dynamic_cast(item->getParent()) : NULL; + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(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(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(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(ctrl->getParent()); + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; + return (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()); +} + +void handle_spellcheck_add_to_ignore(const LLUICtrl* ctrl) +{ + const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(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(ctrl->getParent()); + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; + return (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()); +} + bool enable_object_delete() { bool new_value = @@ -7933,6 +8006,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. 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/viewer_manifest.py b/indra/newview/viewer_manifest.py index 0931c4ec9b..1b732676e4 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -91,6 +91,8 @@ class ViewerManifest(LLManifest): # ... and the entire windlight directory self.path("windlight") + # ... and the pre-installed spell checking dictionaries + self.path("dictionaries") self.end_prefix("app_settings") if self.prefix(src="character"): @@ -393,6 +395,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 +664,7 @@ class DarwinManifest(ViewerManifest): # copy additional libs in /Contents/MacOS/ self.path("../packages/lib/release/libndofdev.dylib", dst="Resources/libndofdev.dylib") + self.path("../packages/lib/release/libhunspell-1.3.dylib", dst="Resources/libhunspell-1.3.dylib") self.path("../viewer_components/updater/scripts/darwin/update_install", "MacOS/update_install") @@ -1053,6 +1059,8 @@ class Linux_i686Manifest(LinuxManifest): self.path("libopenjpeg.so.1.4.0") self.path("libopenjpeg.so.1") self.path("libopenjpeg.so") + self.path("libhunspell-1.3.so") + self.path("libhunspell-1.3.so.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 -- cgit v1.3 From e0f919711034ee4a112ae4b583486693bc104a7b Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 25 Jan 2012 14:58:47 -0500 Subject: Fix for build failures when tcmalloc disabled --- indra/cmake/Copy3rdPartyLibs.cmake | 4 ++-- indra/newview/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/cmake') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 394db362b1..8e5d901779 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -55,10 +55,10 @@ if(WINDOWS) glod.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) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f929e8d379..3e8b365f3a 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1526,7 +1526,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 @@ -1534,7 +1534,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 -- cgit v1.3 From 16b6595fa75047c6c53ee11a6c3004e99ae0937d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 26 Jan 2012 13:38:11 -0500 Subject: trying to fix linux build error --- indra/cmake/Copy3rdPartyLibs.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra/cmake') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 8e5d901779..966300f1c7 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -268,13 +268,16 @@ elseif(LINUX) 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) -- cgit v1.3 From b13fe12fb950f714a2e2fd97708a3baef39ef285 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 3 Feb 2012 14:10:51 -0500 Subject: tcmalloc on by default --- indra/cmake/GooglePerfTools.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/cmake') diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 73b3642ae6..09501e0406 100755 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -3,7 +3,7 @@ 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 OFF) +set (USE_TCMALLOC ON) if (STANDALONE) include(FindGooglePerfTools) -- cgit v1.3 From 6d050cad618493b7881ea6d0073e64ba732b6352 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Fri, 10 Feb 2012 16:25:55 +0100 Subject: - fixed : Hunspell linking issues --- indra/cmake/CMakeLists.txt | 1 + indra/cmake/FindHUNSPELL.cmake | 38 ++++++++++++++++++++++++++++++++++++++ indra/cmake/Hunspell.cmake | 21 +++++++++++++++++++++ indra/newview/CMakeLists.txt | 1 + 4 files changed, 61 insertions(+) create mode 100644 indra/cmake/FindHUNSPELL.cmake create mode 100644 indra/cmake/Hunspell.cmake (limited to 'indra/cmake') 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/FindHUNSPELL.cmake b/indra/cmake/FindHUNSPELL.cmake new file mode 100644 index 0000000000..d411bdb9e5 --- /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 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/Hunspell.cmake b/indra/cmake/Hunspell.cmake new file mode 100644 index 0000000000..def2198c93 --- /dev/null +++ b/indra/cmake/Hunspell.cmake @@ -0,0 +1,21 @@ +# -*- 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) + set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell) + elseif(DARWIN) + set(HUNSPELL_LIBRARY hunspell-1.3) + set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell) + else() + set(HUNSPELL_LIBRARY hunspell-1.3) + set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell) + endif() +endif (STANDALONE) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0ec3e0e08a..fed9ea6790 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) -- cgit v1.3 From e02bf8f90dba7cd7ac8874d7ee1baf782397784f Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 23 Apr 2012 14:00:25 -0400 Subject: add dictionaries to the Hunspell.cmake so that it gets installed --- build.sh | 27 +++++++++++++-------------- indra/cmake/Hunspell.cmake | 1 + 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'indra/cmake') diff --git a/build.sh b/build.sh index 90818009c3..c14fdc006f 100755 --- a/build.sh +++ b/build.sh @@ -15,6 +15,12 @@ # * The basic convention is that the build name can be mapped onto a mercurial URL, # which is also used as the "branch" name. +check_for() +{ + if [ -e "$2" ]; then found_dict='FOUND'; else found_dict='MISSING'; fi + echo "$1 ${found_dict} '$2' " 1>&2 +} + build_dir_Darwin() { echo build-darwin-i386 @@ -59,8 +65,7 @@ pre_build() && [ -r "$master_message_template_checkout/message_template.msg" ] \ && template_verifier_master_url="-DTEMPLATE_VERIFIER_MASTER_URL=file://$master_message_template_checkout/message_template.msg" - echo -n "Before 'autobuild configure' ${build_dir}/packages/dictionaries " 1>&2 - (test -d "${build_dir}/packages/dictionaries" && 'found' || echo 'missing' ) 1>&2 + check_for "Before 'autobuild configure'" ${build_dir}/packages/dictionaries "$AUTOBUILD" configure -c $variant -- \ -DPACKAGE:BOOL=ON \ @@ -71,10 +76,9 @@ pre_build() -DLL_TESTS:BOOL="$run_tests" \ -DTEMPLATE_VERIFIER_OPTIONS:STRING="$template_verifier_options" $template_verifier_master_url - echo -n "After 'autobuild configure' ${build_dir}/packages/dictionaries " 1>&2 - (test -d "${build_dir}/packages/dictionaries" && 'found' || echo 'missing' ) 1>&2 + check_for "After 'autobuild configure'" ${build_dir}/packages/dictionaries - end_section "Pre$variant" + end_section "Pre$variant" } build() @@ -84,8 +88,7 @@ build() then begin_section "Viewer$variant" - echo -n "Before 'autobuild build' ${build_dir}/packages/dictionaries " 1>&2 - (test -d "${build_dir}/packages/dictionaries" && 'found' || echo 'missing' ) 1>&2 + check_for "Before 'autobuild build'" ${build_dir}/packages/dictionaries if "$AUTOBUILD" build --no-configure -c $variant then @@ -93,8 +96,7 @@ build() else echo false >"$build_dir"/build_ok fi - echo -n "After 'autobuild build' ${build_dir}/packages/dictionaries " 1>&2 - (test -d "${build_dir}/packages/dictionaries" && 'found' || echo 'missing' ) 1>&2 + check_for "After 'autobuild configure'" ${build_dir}/packages/dictionaries end_section "Viewer$variant" fi @@ -190,15 +192,12 @@ eval "$("$AUTOBUILD" source_environment)" # dump environment variables for debugging env|sort - -echo -n "Before 'autobuild install' ${build_dir}/packages/dictionaries " 1>&2 -(test -d "${build_dir}/packages/dictionaries" && 'found' || echo 'missing' ) 1>&2 +check_for "Before 'autobuild install'" ${build_dir}/packages/dictionaries # Install packages. "$AUTOBUILD" install --skip-license-check -echo -n "After 'autobuild install' ${build_dir}/packages/dictionaries " 1>&2 -(test -d "${build_dir}/packages/dictionaries" && 'found' || echo 'missing' ) 1>&2 +check_for "After 'autobuild install'" ${build_dir}/packages/dictionaries # Now run the build succeeded=true diff --git a/indra/cmake/Hunspell.cmake b/indra/cmake/Hunspell.cmake index def2198c93..24cf41f4e4 100644 --- a/indra/cmake/Hunspell.cmake +++ b/indra/cmake/Hunspell.cmake @@ -8,6 +8,7 @@ if (STANDALONE) include(FindHUNSPELL) else (STANDALONE) use_prebuilt_binary(libhunspell) + use_prebuilt_binary(dictionaries) if (WINDOWS) set(HUNSPELL_LIBRARY libhunspell) set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell) -- cgit v1.3 From 7bcfd3a4ae824d973802b1431a13e91eee18c89a Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 23 Apr 2012 17:27:54 -0400 Subject: fix version number of the libhunspell dylib in another place --- indra/cmake/Copy3rdPartyLibs.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/cmake') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index ebeae3e5be..6765d36ba3 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -217,7 +217,7 @@ elseif(DARWIN) libllqtwebkit.dylib libminizip.a libndofdev.dylib - libhunspell-1.3.dylib + libhunspell-1.3.0.dylib libexception_handler.dylib libcollada14dom.dylib ) -- cgit v1.3 From 9b64464d02918307048be6fe5f0b784010d38bf8 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 25 Apr 2012 12:27:34 -0400 Subject: more attempts to fix the hunspell lib for Mac --- indra/cmake/Copy3rdPartyLibs.cmake | 11 ++++++----- indra/cmake/FindHUNSPELL.cmake | 2 +- indra/cmake/Hunspell.cmake | 10 +++++----- 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'indra/cmake') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 6765d36ba3..224e0a8b51 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -214,12 +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 @@ -260,14 +260,15 @@ 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 diff --git a/indra/cmake/FindHUNSPELL.cmake b/indra/cmake/FindHUNSPELL.cmake index d411bdb9e5..6faf22959c 100644 --- a/indra/cmake/FindHUNSPELL.cmake +++ b/indra/cmake/FindHUNSPELL.cmake @@ -10,7 +10,7 @@ find_path(HUNSPELL_INCLUDE_DIR hunspell.h PATH_SUFFIXES hunspell ) -set(HUNSPELL_NAMES ${HUNSPELL_NAMES} libhunspell-1.3 libhunspell) +set(HUNSPELL_NAMES ${HUNSPELL_NAMES} libhunspell-1.3.0 libhunspell) find_library(HUNSPELL_LIBRARY NAMES ${HUNSPELL_NAMES} ) diff --git a/indra/cmake/Hunspell.cmake b/indra/cmake/Hunspell.cmake index 24cf41f4e4..0c9cf93316 100644 --- a/indra/cmake/Hunspell.cmake +++ b/indra/cmake/Hunspell.cmake @@ -8,15 +8,15 @@ if (STANDALONE) include(FindHUNSPELL) else (STANDALONE) use_prebuilt_binary(libhunspell) - use_prebuilt_binary(dictionaries) if (WINDOWS) set(HUNSPELL_LIBRARY libhunspell) - set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell) elseif(DARWIN) + set(HUNSPELL_LIBRARY hunspell-1.3.0) + elseif(LINUX) set(HUNSPELL_LIBRARY hunspell-1.3) - set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell) else() - set(HUNSPELL_LIBRARY hunspell-1.3) - set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell) + message(FATAL_ERROR "Invalid platform") endif() + set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell) + use_prebuilt_binary(dictionaries) endif (STANDALONE) -- cgit v1.3 From ad745867ed820c39718de9519b15f25a5526ae37 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 8 Jun 2012 14:19:36 -0500 Subject: MAINT-646 Enable /fp:fast in Visual Studio --- indra/cmake/00-Common.cmake | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/cmake') diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 98eeed09b3..00baf626d2 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -69,6 +69,7 @@ if (WINDOWS) /Oy- /Zc:wchar_t- /arch:SSE2 + /fp:fast ) # Are we using the crummy Visual Studio KDU build workaround? -- cgit v1.3