diff options
Diffstat (limited to 'indra')
178 files changed, 3240 insertions, 4920 deletions
diff --git a/indra/cmake/CARes.cmake b/indra/cmake/CARes.cmake index 8a2dc01561..1850b706ac 100644 --- a/indra/cmake/CARes.cmake +++ b/indra/cmake/CARes.cmake @@ -9,6 +9,7 @@ if (STANDALONE) include(FindCARes) else (STANDALONE) use_prebuilt_binary(ares) + add_definitions("-DCARES_STATICLIB") if (WINDOWS) set(CARES_LIBRARIES areslib) elseif (DARWIN) diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index c9dc301b8b..9900a8fb45 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -171,6 +171,7 @@ elseif(DARWIN) libexpat.dylib libllqtwebkit.dylib libndofdev.dylib + libexception_handler.dylib ) # fmod is statically linked on darwin @@ -220,6 +221,7 @@ elseif(LINUX) libapr-1.so.0 libaprutil-1.so.0 libatk-1.0.so + libbreakpad_client.so.0 libcrypto.so.0.9.7 libdb-4.2.so libexpat.so diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake new file mode 100644 index 0000000000..8270c0fabb --- /dev/null +++ b/indra/cmake/GoogleBreakpad.cmake @@ -0,0 +1,19 @@ +# -*- cmake -*- +include(Prebuilt) + +if (STANDALONE) + MESSAGE(FATAL_ERROR "*TODO standalone support for google breakad is unimplemented") + # *TODO - implement this include(FindGoogleBreakpad) +else (STANDALONE) + use_prebuilt_binary(google_breakpad) + if (DARWIN) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler) + endif (DARWIN) + if (LINUX) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client) + endif (LINUX) + if (WINDOWS) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client common) + endif (WINDOWS) +endif (STANDALONE) + diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp index 039b70ec4a..ce03ea0d6f 100644 --- a/indra/linux_crash_logger/llcrashloggerlinux.cpp +++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp @@ -120,7 +120,6 @@ LLCrashLoggerLinux::~LLCrashLoggerLinux(void) void LLCrashLoggerLinux::gatherPlatformSpecificFiles() { - mFileMap["CrashLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log").c_str(); } bool LLCrashLoggerLinux::mainLoop() diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 3c689930b8..2a036df06e 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -9,6 +9,7 @@ include(Linking) include(Boost) include(Pth) include(LLSharedLibs) +include(GoogleBreakpad) include(GooglePerfTools) include(Copy3rdPartyLibs) @@ -232,7 +233,6 @@ set(llcommon_HEADER_FILES metaclasst.h metaproperty.h metapropertyt.h - processor.h reflective.h reflectivet.h roles_constants.h @@ -259,6 +259,7 @@ endif(LLCOMMON_LINK_SHARED) target_link_libraries( llcommon + ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES} ${APRUTIL_LIBRARIES} ${APR_LIBRARIES} ${EXPAT_LIBRARIES} @@ -290,6 +291,7 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6b2d1b7c20..eedec0b24e 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -30,6 +30,8 @@ * $/LicenseInfo$ */ +#include <cstdlib> + #include "linden_common.h" #include "llapp.h" @@ -41,8 +43,11 @@ #include "lllivefile.h" #include "llmemory.h" #include "llstl.h" // for DeletePointer() +#include "llstring.h" #include "lleventtimer.h" +#include "google_breakpad/exception_handler.h" + // // Signal handling // @@ -51,11 +56,22 @@ #if LL_WINDOWS LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop); BOOL ConsoleCtrlHandler(DWORD fdwCtrlType); +bool windows_post_minidump_callback(const wchar_t* dump_path, + const wchar_t* minidump_id, + void* context, + EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion, + bool succeeded); #else # include <signal.h> # include <unistd.h> // for fork() void setup_signals(); void default_unix_signal_handler(int signum, siginfo_t *info, void *); + +// Called by breakpad exception handler after the minidump has been generated. +bool unix_post_minidump_callback(const char *dump_dir, + const char *minidump_id, + void *context, bool succeeded); # if LL_DARWIN /* OSX doesn't support SIGRT* */ S32 LL_SMACKDOWN_SIGNAL = SIGUSR1; @@ -81,7 +97,6 @@ BOOL LLApp::sLogInSignal = FALSE; // static LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status LLAppErrorHandler LLApp::sErrorHandler = NULL; -LLAppErrorHandler LLApp::sSyncErrorHandler = NULL; BOOL LLApp::sErrorThreadRunning = FALSE; #if !LL_WINDOWS LLApp::child_map LLApp::sChildMap; @@ -123,7 +138,12 @@ void LLApp::commonCtor() // Set the application to this instance. sApplication = this; - + + mExceptionHandler = 0; + + // initialize the buffer to write the minidump filename to + // (this is used to avoid allocating memory in the crash handler) + memset(minidump_path, 0, MAX_MINDUMP_PATH_LENGTH); } LLApp::LLApp(LLErrorThread *error_thread) : @@ -152,6 +172,8 @@ LLApp::~LLApp() delete mThreadErrorp; mThreadErrorp = NULL; } + + if(mExceptionHandler != 0) delete mExceptionHandler; LLCommon::cleanupClass(); } @@ -262,19 +284,18 @@ void LLApp::setupErrorHandling() // occasionally checks to see if the app is in an error state, and sees if it needs to be run. #if LL_WINDOWS - // Windows doesn't have the same signal handling mechanisms as UNIX, thus APR doesn't provide - // a signal handling thread implementation. - // What we do is install an unhandled exception handler, which will try to do the right thing - // in the case of an error (generate a minidump) - - // Disable this until the viewer gets ported so server crashes can be JIT debugged. - //LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - //prev_filter = SetUnhandledExceptionFilter(default_windows_exception_handler); - // This sets a callback to handle w32 signals to the console window. // The viewer shouldn't be affected, sicne its a windowed app. SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE); + // Install the Google Breakpad crash handler for Windows + if(mExceptionHandler == 0) + { + llwarns << "adding breakpad exception handler" << llendl; + mExceptionHandler = new google_breakpad::ExceptionHandler( + L"C:\\Temp\\", 0, windows_post_minidump_callback, 0, google_breakpad::ExceptionHandler::HANDLER_ALL); + } + #else // // Start up signal handling. @@ -282,9 +303,14 @@ void LLApp::setupErrorHandling() // There are two different classes of signals. Synchronous signals are delivered to a specific // thread, asynchronous signals can be delivered to any thread (in theory) // - setup_signals(); - + + // Add google breakpad exception handler configured for Darwin/Linux. + if(mExceptionHandler == 0) + { + std::string dumpPath = "/tmp/"; + mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true); + } #endif startErrorThread(); @@ -310,21 +336,6 @@ void LLApp::setErrorHandler(LLAppErrorHandler handler) LLApp::sErrorHandler = handler; } - -void LLApp::setSyncErrorHandler(LLAppErrorHandler handler) -{ - LLApp::sSyncErrorHandler = handler; -} - -// static -void LLApp::runSyncErrorHandler() -{ - if (LLApp::sSyncErrorHandler) - { - LLApp::sSyncErrorHandler(); - } -} - // static void LLApp::runErrorHandler() { @@ -337,7 +348,6 @@ void LLApp::runErrorHandler() LLApp::setStopped(); } - // static void LLApp::setStatus(EAppStatus status) { @@ -348,15 +358,27 @@ void LLApp::setStatus(EAppStatus status) // static void LLApp::setError() { - if (!isError()) - { - // perform any needed synchronous error-handling - runSyncErrorHandler(); - // set app status to ERROR so that the LLErrorThread notices - setStatus(APP_STATUS_ERROR); - } + // set app status to ERROR so that the LLErrorThread notices + setStatus(APP_STATUS_ERROR); } +void LLApp::setMiniDumpDir(const std::string &path) +{ + llassert(mExceptionHandler); +#ifdef LL_WINDOWS + wchar_t buffer[MAX_MINDUMP_PATH_LENGTH]; + mbstowcs(buffer, path.c_str(), MAX_MINDUMP_PATH_LENGTH); + mExceptionHandler->set_dump_path(std::wstring(buffer)); +#else + mExceptionHandler->set_dump_path(path); +#endif +} + +void LLApp::writeMiniDump() +{ + llassert(mExceptionHandler); + mExceptionHandler->WriteMinidump(); +} // static void LLApp::setQuitting() @@ -587,6 +609,7 @@ void setup_signals() // Asynchronous signals that result in core sigaction(SIGQUIT, &act, NULL); + } void clear_signals() @@ -765,4 +788,97 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) } } +bool unix_post_minidump_callback(const char *dump_dir, + const char *minidump_id, + void *context, bool succeeded) +{ + // Copy minidump file path into fixed buffer in the app instance to avoid + // heap allocations in a crash handler. + + // path format: <dump_dir>/<minidump_id>.dmp + int dirPathLength = strlen(dump_dir); + int idLength = strlen(minidump_id); + + // The path must not be truncated. + llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH); + + char * path = LLApp::instance()->getMiniDumpFilename(); + S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; + strncpy(path, dump_dir, remaining); + remaining -= dirPathLength; + path += dirPathLength; + if (remaining > 0 && dirPathLength > 0 && path[-1] != '/') + { + *path++ = '/'; + --remaining; + } + if (remaining > 0) + { + strncpy(path, minidump_id, remaining); + remaining -= idLength; + path += idLength; + strncpy(path, ".dmp", remaining); + } + + llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; + LLApp::runErrorHandler(); + return true; +} #endif // !WINDOWS + +#ifdef LL_WINDOWS +bool windows_post_minidump_callback(const wchar_t* dump_path, + const wchar_t* minidump_id, + void* context, + EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion, + bool succeeded) +{ + char * path = LLApp::instance()->getMiniDumpFilename(); + S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; + size_t bytesUsed; + + bytesUsed = wcstombs(path, dump_path, static_cast<size_t>(remaining)); + remaining -= bytesUsed; + path += bytesUsed; + if(remaining > 0 && bytesUsed > 0 && path[-1] != '\\') + { + *path++ = '\\'; + --remaining; + } + if(remaining > 0) + { + bytesUsed = wcstombs(path, minidump_id, static_cast<size_t>(remaining)); + remaining -= bytesUsed; + path += bytesUsed; + } + if(remaining > 0) + { + strncpy(path, ".dmp", remaining); + } + + llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; + // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. + //OSMessageBox("Attach Debugger Now", "Error", OSMB_OK); + // *TODO: Translate the signals/exceptions into cross-platform stuff + // Windows implementation + llinfos << "Entering Windows Exception Handler..." << llendl; + + if (LLApp::isError()) + { + llwarns << "Got another fatal signal while in the error handler, die now!" << llendl; + } + + // Flag status to error, so thread_error starts its work + LLApp::setError(); + + // Block in the exception handler until the app has stopped + // This is pretty sketchy, but appears to work just fine + while (!LLApp::isStopped()) + { + ms_sleep(10); + } + + return true; +} +#endif diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index e5b8edf9c3..fef05a7939 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -66,6 +66,10 @@ public: }; #endif +namespace google_breakpad { + class ExceptionHandler; // See exception_handler.h +} + class LL_COMMON_API LLApp : public LLOptionInterface { friend class LLErrorThread; @@ -227,8 +231,20 @@ public: void setupErrorHandling(); void setErrorHandler(LLAppErrorHandler handler); - void setSyncErrorHandler(LLAppErrorHandler handler); + static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. //@} + + // the maximum length of the minidump filename returned by getMiniDumpFilename() + static const U32 MAX_MINDUMP_PATH_LENGTH = 256; + + // change the directory where Breakpad minidump files are written to + void setMiniDumpDir(const std::string &path); + + // Return the Google Breakpad minidump filename after a crash. + char *getMiniDumpFilename() { return minidump_path; } + + // Write out a Google Breakpad minidump file. + void writeMiniDump(); #if !LL_WINDOWS // @@ -286,15 +302,14 @@ protected: private: void startErrorThread(); - static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. - static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread. + // Contains the filename of the minidump file after a crash. + char minidump_path[MAX_MINDUMP_PATH_LENGTH]; // *NOTE: On Windows, we need a routine to reset the structured // exception handler when some evil driver has taken it over for // their own purposes typedef int(*signal_handler_func)(int signum); static LLAppErrorHandler sErrorHandler; - static LLAppErrorHandler sSyncErrorHandler; // Default application threads LLErrorThread* mThreadErrorp; // Waits for app to go to status ERROR, then runs the error callback @@ -315,6 +330,8 @@ private: private: // the static application instance if it was created. static LLApp* sApplication; + + google_breakpad::ExceptionHandler * mExceptionHandler; #if !LL_WINDOWS diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index de7f2ead74..a7ef28b431 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -248,8 +248,27 @@ bool LLDate::fromStream(std::istream& s) s >> fractional; seconds_since_epoch += fractional; } - c = s.get(); // skip the Z - if (c != 'Z') { return false; } + + c = s.peek(); // check for offset + if (c == '+' || c == '-') + { + S32 offset_sign = (c == '+') ? 1 : -1; + S32 offset_hours = 0; + S32 offset_minutes = 0; + S32 offset_in_seconds = 0; + + s >> offset_hours; + + c = s.get(); // skip the colon a get the minutes if there are any + if (c == ':') + { + s >> offset_minutes; + } + + offset_in_seconds = (offset_hours * 60 + offset_sign * offset_minutes) * 60; + seconds_since_epoch -= offset_in_seconds; + } + else if (c != 'Z') { return false; } // skip the Z mSecondsSinceEpoch = seconds_since_epoch; return true; diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp index f39a4e6619..20727dd76e 100644 --- a/indra/llcommon/llfasttimer_class.cpp +++ b/indra/llcommon/llfasttimer_class.cpp @@ -238,7 +238,7 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer #else // windows or x86-mac or x86-linux or x86-solaris U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer { - static U64 sCPUClockFrequency = U64(CProcessor().GetCPUFrequency(50)); + static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()); // we drop the low-order byte in our timers, so report a lower frequency return sCPUClockFrequency >> 8; diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index f6ab55a6b5..d3ba215751 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -30,139 +30,389 @@ * $/LicenseInfo$ */ -// Filename: Processor.cpp -// ======================= -// Author: Benjamin Jurke -// File history: 27.02.2002 - File created. Support for Intel and AMD processors -// 05.03.2002 - Fixed the CPUID bug: On Pre-Pentium CPUs the CPUID -// command is not available -// - The CProcessor::WriteInfoTextFile function do not -// longer use Win32 file functions (-> os independend) -// - Optional include of the windows.h header which is -// still need for CProcessor::GetCPUFrequency. -// 06.03.2002 - My birthday (18th :-)) -// - Replaced the '\r\n' line endings in function -// CProcessor::CPUInfoToText by '\n' -// - Replaced unsigned __int64 by signed __int64 for -// solving some compiler conversion problems -// - Fixed a bug at family=6, model=6 (Celeron -> P2) -////////////////////////////////////////////////////////////////////////////////// - #include "linden_common.h" +#include "llprocessor.h" -#include "processor.h" +#include "llerror.h" -#include <memory> +//#include <memory> #if LL_WINDOWS # define WIN32_LEAN_AND_MEAN # include <winsock2.h> # include <windows.h> +# define _interlockedbittestandset _renamed_interlockedbittestandset +# define _interlockedbittestandreset _renamed_interlockedbittestandreset +# include <intrin.h> +# undef _interlockedbittestandset +# undef _interlockedbittestandreset #endif -#if LL_LINUX -#include "llsys.h" -#endif // LL_LINUX +#include "llsd.h" + +#if LL_MSVC && _M_X64 +# define LL_X86_64 1 +# define LL_X86 1 +#elif LL_MSVC && _M_IX86 +# define LL_X86 1 +#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) +# define LL_X86_64 1 +# define LL_X86 1 +#elif LL_GNUC && ( defined(__i386__) ) +# define LL_X86 1 +#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) +# define LL_PPC 1 +#endif + +class LLProcessorInfoImpl; // foward declaration for the mImpl; + +namespace +{ + enum cpu_info + { + eBrandName = 0, + eFrequency, + eVendor, + eStepping, + eFamily, + eExtendedFamily, + eModel, + eExtendedModel, + eType, + eBrandID, + eFamilyName + }; + + + const char* cpu_info_names[] = + { + "Processor Name", + "Frequency", + "Vendor", + "Stepping", + "Family", + "Extended Family", + "Model", + "Extended Model", + "Type", + "Brand ID", + "Family Name" + }; + + enum cpu_config + { + eMaxID, + eMaxExtID, + eCLFLUSHCacheLineSize, + eAPICPhysicalID, + eCacheLineSize, + eL2Associativity, + eCacheSizeK, + eFeatureBits, + eExtFeatureBits + }; + + const char* cpu_config_names[] = + { + "Max Supported CPUID level", + "Max Supported Ext. CPUID level", + "CLFLUSH cache line size", + "APIC Physical ID", + "Cache Line Size", + "L2 Associativity", + "Cache Size", + "Feature Bits", + "Ext. Feature Bits" + }; -#if !LL_DARWIN && !LL_SOLARIS -#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -// We need the QueryPerformanceCounter and Sleep functions -#define FORCEINLINE __forceinline -#else -#define FORCEINLINE -#endif + // *NOTE:Mani - this contains the elements we reference directly and extensions beyond the first 32. + // The rest of the names are referenced by bit maks returned from cpuid. + enum cpu_features + { + eSSE_Ext=25, + eSSE2_Ext=26, + + eSSE3_Features=32, + eMONTIOR_MWAIT=33, + eCPLDebugStore=34, + eThermalMonitor2=35, + eAltivec=36 + }; -// Some macros we often need -//////////////////////////// -#define CheckBit(var, bit) ((var & (1 << bit)) ? true : false) + const char* cpu_feature_names[] = + { + "x87 FPU On Chip", + "Virtual-8086 Mode Enhancement", + "Debugging Extensions", + "Page Size Extensions", + "Time Stamp Counter", + "RDMSR and WRMSR Support", + "Physical Address Extensions", + "Machine Check Exception", + "CMPXCHG8B Instruction", + "APIC On Chip", + "Unknown1", + "SYSENTER and SYSEXIT", + "Memory Type Range Registers", + "PTE Global Bit", + "Machine Check Architecture", + "Conditional Move/Compare Instruction", + "Page Attribute Table", + "Page Size Extension", + "Processor Serial Number", + "CFLUSH Extension", + "Unknown2", + "Debug Store", + "Thermal Monitor and Clock Ctrl", + "MMX Technology", + "FXSAVE/FXRSTOR", + "SSE Extensions", + "SSE2 Extensions", + "Self Snoop", + "Hyper-threading Technology", + "Thermal Monitor", + "Unknown4", + "Pend. Brk. EN.", // 31 End of FeatureInfo bits + + "SSE3 New Instructions", // 32 + "MONITOR/MWAIT", + "CPL Qualified Debug Store", + "Thermal Monitor 2", + + "Altivec" + }; + + std::string intel_CPUFamilyName(int composed_family) + { + switch(composed_family) + { + case 3: return "Intel i386"; + case 4: return "Intel i486"; + case 5: return "Intel Pentium"; + case 6: return "Intel Pentium Pro/2/3, Core"; + case 7: return "Intel Itanium (IA-64)"; + case 0xF: return "Intel Pentium 4"; + case 0x10: return "Intel Itanium 2 (IA-64)"; + } + return "Unknown"; + } + + std::string amd_CPUFamilyName(int composed_family) + { + switch(composed_family) + { + case 4: return "AMD 80486/5x86"; + case 5: return "AMD K5/K6"; + case 6: return "AMD K7"; + case 0xF: return "AMD K8"; + case 0x10: return "AMD K8L"; + } + return "Unknown"; + } + + std::string compute_CPUFamilyName(const char* cpu_vendor, int composed_family) + { + const char* intel_string = "GenuineIntel"; + const char* amd_string = "AuthenticAMD"; + if(!strncmp(cpu_vendor, intel_string, strlen(intel_string))) + { + return intel_CPUFamilyName(composed_family); + } + else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string))) + { + return amd_CPUFamilyName(composed_family); + } + return "Unknown"; + } + + std::string compute_CPUFamilyName(const char* cpu_vendor, int family, int ext_family) + { + const char* intel_string = "GenuineIntel"; + const char* amd_string = "AuthenticAMD"; + if(!strncmp(cpu_vendor, intel_string, strlen(intel_string))) + { + U32 composed_family = family + ext_family; + return intel_CPUFamilyName(composed_family); + } + else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string))) + { + U32 composed_family = (family == 0xF) + ? family + ext_family + : family; + return amd_CPUFamilyName(composed_family); + } + return "Unknown"; + } + +} // end unnamed namespace + +// The base class for implementations. +// Each platform should override this class. +class LLProcessorInfoImpl +{ +public: + LLProcessorInfoImpl() + { + mProcessorInfo["info"] = LLSD::emptyMap(); + mProcessorInfo["config"] = LLSD::emptyMap(); + mProcessorInfo["extension"] = LLSD::emptyMap(); + } + virtual ~LLProcessorInfoImpl() {} + + F64 getCPUFrequency() const + { + return getInfo(eFrequency, 0).asReal(); + } + + bool hasSSE() const + { + return hasExtension(cpu_feature_names[eSSE_Ext]); + } + + bool hasSSE2() const + { + return hasExtension(cpu_feature_names[eSSE2_Ext]); + } + + bool hasAltivec() const + { + return hasExtension("Altivec"); + } + + std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unknown").asString(); } + std::string getCPUBrandName() const { return getInfo(eBrandName, "Unknown").asString(); } + + // This is virtual to support a different linux format. + // *NOTE:Mani - I didn't want to screw up server use of this data... + virtual std::string getCPUFeatureDescription() const + { + std::ostringstream out; + out << std::endl << std::endl; + out << "// CPU General Information" << std::endl; + out << "//////////////////////////" << std::endl; + out << "Processor Name: " << getCPUBrandName() << std::endl; + out << "Frequency: " << getCPUFrequency() << " MHz" << std::endl; + out << "Vendor: " << getInfo(eVendor, "Unknown").asString() << std::endl; + out << "Family: " << getCPUFamilyName() << " (" << getInfo(eFamily, 0) << ")" << std::endl; + out << "Extended family: " << getInfo(eExtendedFamily, 0) << std::endl; + out << "Model: " << getInfo(eModel, 0) << std::endl; + out << "Extended model: " << getInfo(eExtendedModel, 0) << std::endl; + out << "Type: " << getInfo(eType, 0) << std::endl; + out << "Brand ID: " << getInfo(eBrandID, 0) << std::endl; + out << std::endl; + out << "// CPU Configuration" << std::endl; + out << "//////////////////////////" << std::endl; + + // Iterate through the dictionary of configuration options. + LLSD configs = mProcessorInfo["config"]; + for(LLSD::map_const_iterator cfgItr = configs.beginMap(); cfgItr != configs.endMap(); ++cfgItr) + { + out << cfgItr->first << " = " << cfgItr->second << std::endl; + } + out << std::endl; + + out << "// CPU Extensions" << std::endl; + out << "//////////////////////////" << std::endl; + + for(LLSD::map_const_iterator itr = mProcessorInfo["extension"].beginMap(); itr != mProcessorInfo["extension"].endMap(); ++itr) + { + out << " " << itr->first << std::endl; + } + return out.str(); + } + +protected: + void setInfo(cpu_info info_type, const LLSD& value) + { + setInfo(cpu_info_names[info_type], value); + } + LLSD getInfo(cpu_info info_type, const LLSD& defaultVal) const + { + return getInfo(cpu_info_names[info_type], defaultVal); + } + + void setConfig(cpu_config config_type, const LLSD& value) + { + setConfig(cpu_config_names[config_type], value); + } + LLSD getConfig(cpu_config config_type, const LLSD& defaultVal) const + { + return getConfig(cpu_config_names[config_type], defaultVal); + } + + void setExtension(const std::string& name) { mProcessorInfo["extension"][name] = "true"; } + bool hasExtension(const std::string& name) const + { + return mProcessorInfo["extension"].has(name); + } + +private: + void setInfo(const std::string& name, const LLSD& value) { mProcessorInfo["info"][name]=value; } + LLSD getInfo(const std::string& name, const LLSD& defaultVal) const + { + if(mProcessorInfo["info"].has(name)) + { + return mProcessorInfo["info"][name]; + } + return defaultVal; + } + void setConfig(const std::string& name, const LLSD& value) { mProcessorInfo["config"][name]=value; } + LLSD getConfig(const std::string& name, const LLSD& defaultVal) const + { + LLSD r = mProcessorInfo["config"].get(name); + return r.isDefined() ? r : defaultVal; + } + +private: + + LLSD mProcessorInfo; +}; + + +#ifdef LL_MSVC +// LL_MSVC and not LLWINDOWS because some of the following code +// uses the MSVC compiler intrinsics __cpuid() and __rdtsc(). -#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE // Delays for the specified amount of milliseconds -static void _Delay(unsigned int ms) +static void _Delay(unsigned int ms) { - LARGE_INTEGER freq, c1, c2; - __int64 x; + LARGE_INTEGER freq, c1, c2; + __int64 x; - // Get High-Res Timer frequency + // Get High-Res Timer frequency if (!QueryPerformanceFrequency(&freq)) return; - + // Convert ms to High-Res Timer value x = freq.QuadPart/1000*ms; - // Get first snapshot of High-Res Timer value + // Get first snapshot of High-Res Timer value QueryPerformanceCounter(&c1); do { - // Get second snapshot - QueryPerformanceCounter(&c2); + // Get second snapshot + QueryPerformanceCounter(&c2); }while(c2.QuadPart-c1.QuadPart < x); // Loop while (second-first < x) } -#endif - -// CProcessor::CProcessor -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ - uqwFrequency = 0; - strCPUName[0] = 0; - memset(&CPUInfo, 0, sizeof(CPUInfo)); -} -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to measure the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) +static F64 calculate_cpu_frequency(U32 measure_msecs) { -#if LL_LINUX - // use the shinier LLCPUInfo interface - return 1000000.0F * gSysCPU.getMHz(); -#endif - -#ifndef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE - return 0; -#else - // If there are invalid measure time parameters, zero msecs for example, - // we've to exit the function - if (uiMeasureMSecs < 1) + if(measure_msecs == 0) { - // If theres already a measured frequency available, we return it - if (uqwFrequency > 0) - return uqwFrequency; - else - return 0; - } - - // Now we check if the CPUID command is available - if (!CheckCPUIDPresence()) return 0; - - // First we get the CPUID standard level 0x00000001 - unsigned long reg; - __asm - { - mov eax, 1 - cpuid - mov reg, edx } - // Then we check, if the RDTSC (Real Date Time Stamp Counter) is available. - // This function is necessary for our measure process. - if (!(reg & (1 << 4))) - return 0; - // After that we declare some vars and check the frequency of the high // resolution timer for the measure process. - // If there's no high-res timer, we exit. - __int64 starttime, endtime, timedif, freq, start, end, dif; + // If there"s no high-res timer, we exit. + unsigned __int64 starttime, endtime, timedif, freq, start, end, dif; if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq)) + { return 0; + } // Now we can init the measure process. We set the process and thread priority // to the highest available level (Realtime priority). Also we focus the @@ -178,35 +428,27 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); SetProcessAffinityMask(hProcess, dwNewMask); - // Now we call a CPUID to ensure, that all other prior called functions are - // completed now (serialization) - __asm cpuid + //// Now we call a CPUID to ensure, that all other prior called functions are + //// completed now (serialization) + //__asm cpuid + int cpu_info[4] = {-1}; + __cpuid(cpu_info, 0); // We ask the high-res timer for the start time QueryPerformanceCounter((LARGE_INTEGER *) &starttime); // Then we get the current cpu clock and store it - __asm - { - rdtsc - mov dword ptr [start+4], edx - mov dword ptr [start], eax - } + start = __rdtsc(); // Now we wart for some msecs - _Delay(uiMeasureMSecs); -// Sleep(uiMeasureMSecs); + _Delay(measure_msecs); + // Sleep(uiMeasureMSecs); // We ask for the end time QueryPerformanceCounter((LARGE_INTEGER *) &endtime); // And also for the end cpu clock - __asm - { - rdtsc - mov dword ptr [end+4], edx - mov dword ptr [end], eax - } + end = __rdtsc(); // Now we can restore the default process and thread priorities SetProcessAffinityMask(hProcess, dwProcessMask); @@ -219,2075 +461,433 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) // And finally the frequency is the clock difference divided by the time // difference. - uqwFrequency = (F64)dif / (((F64)timedif) / freq); + F64 frequency = (F64)dif / (((F64)timedif) / freq); // At last we just return the frequency that is also stored in the call - // member var uqwFrequency - return uqwFrequency; -#endif + // member var uqwFrequency - converted to MHz + return frequency / (F64)1000000; } -// bool CProcessor::AnalyzeIntelProcessor() -// ======================================== -// Private class function for analyzing an Intel processor -////////////////////////////////////////////////////////// -bool CProcessor::AnalyzeIntelProcessor() +// Windows implementation +class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl { -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, edxreg; - - // First we check if the CPUID command is available - if (!CheckCPUIDPresence()) - return false; - - // Now we get the CPUID standard level 0x00000001 - __asm +public: + LLProcessorInfoWindowsImpl() { - mov eax, 1 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov edxreg, edx + getCPUIDInfo(); + setInfo(eFrequency, calculate_cpu_frequency(50)); } - - // Then get the cpu model, family, type, stepping and brand id by masking - // the eax and ebx register - CPUInfo.uiStepping = eaxreg & 0xF; - CPUInfo.uiModel = (eaxreg >> 4) & 0xF; - CPUInfo.uiFamily = (eaxreg >> 8) & 0xF; - CPUInfo.uiType = (eaxreg >> 12) & 0x3; - CPUInfo.uiBrandID = ebxreg & 0xF; - - static const char* INTEL_BRAND[] = - { - /* 0x00 */ "", - /* 0x01 */ "0.18 micron Intel Celeron", - /* 0x02 */ "0.18 micron Intel Pentium III", - /* 0x03 */ "0.13 micron Intel Celeron", - /* 0x04 */ "0.13 micron Intel Pentium III", - /* 0x05 */ "", - /* 0x06 */ "0.13 micron Intel Pentium III Mobile", - /* 0x07 */ "0.13 micron Intel Celeron Mobile", - /* 0x08 */ "0.18 micron Intel Pentium 4", - /* 0x09 */ "0.13 micron Intel Pentium 4", - /* 0x0A */ "0.13 micron Intel Celeron", - /* 0x0B */ "0.13 micron Intel Pentium 4 Xeon", - /* 0x0C */ "Intel Xeon MP", - /* 0x0D */ "", - /* 0x0E */ "0.18 micron Intel Pentium 4 Xeon", - /* 0x0F */ "Mobile Intel Celeron", - /* 0x10 */ "", - /* 0x11 */ "Mobile Genuine Intel", - /* 0x12 */ "Intel Celeron M", - /* 0x13 */ "Mobile Intel Celeron", - /* 0x14 */ "Intel Celeron", - /* 0x15 */ "Mobile Genuine Intel", - /* 0x16 */ "Intel Pentium M", - /* 0x17 */ "Mobile Intel Celeron", - }; - // Only override the brand if we have it in the lookup table. We should - // already have a string here from GetCPUInfo(). JC - if ( CPUInfo.uiBrandID < LL_ARRAY_SIZE(INTEL_BRAND) ) +private: + void getCPUIDInfo() { - strncpy(CPUInfo.strBrandID, INTEL_BRAND[CPUInfo.uiBrandID], sizeof(CPUInfo.strBrandID)-1); - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; + // http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx + + // __cpuid with an InfoType argument of 0 returns the number of + // valid Ids in cpu_info[0] and the CPU identification string in + // the other three array elements. The CPU identification string is + // not in linear order. The code below arranges the information + // in a human readable form. + int cpu_info[4] = {-1}; + __cpuid(cpu_info, 0); + unsigned int ids = (unsigned int)cpu_info[0]; + setConfig(eMaxID, (S32)ids); + + char cpu_vendor[0x20]; + memset(cpu_vendor, 0, sizeof(cpu_vendor)); + *((int*)cpu_vendor) = cpu_info[1]; + *((int*)(cpu_vendor+4)) = cpu_info[3]; + *((int*)(cpu_vendor+8)) = cpu_info[2]; + setInfo(eVendor, cpu_vendor); - if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6) + // Get the information associated with each valid Id + for(unsigned int i=0; i<=ids; ++i) { - strcpy(CPUInfo.strBrandID, "0.18 micron Intel Pentium III Xeon"); - } - } + __cpuid(cpu_info, i); - // Then we translate the cpu family - switch (CPUInfo.uiFamily) - { - case 3: // Family = 3: i386 (80386) processor family - strcpy(CPUInfo.strFamily, "Intel i386"); /* Flawfinder: ignore */ - break; - case 4: // Family = 4: i486 (80486) processor family - strcpy(CPUInfo.strFamily, "Intel i486"); /* Flawfinder: ignore */ - break; - case 5: // Family = 5: Pentium (80586) processor family - strcpy(CPUInfo.strFamily, "Intel Pentium"); /* Flawfinder: ignore */ - break; - case 6: // Family = 6: Pentium Pro (80686) processor family - strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core"); /* Flawfinder: ignore */ - break; - case 15: // Family = 15: Extended family specific - // Masking the extended family - CPUInfo.uiExtendedFamily = (eaxreg >> 20) & 0xFF; - switch (CPUInfo.uiExtendedFamily) - { - case 0: // Family = 15, Ext. Family = 0: Pentium 4 (80786 ??) processor family - strcpy(CPUInfo.strFamily, "Intel Pentium 4"); /* Flawfinder: ignore */ - break; - case 1: // Family = 15, Ext. Family = 1: McKinley (64-bit) processor family - strcpy(CPUInfo.strFamily, "Intel McKinley (IA-64)"); /* Flawfinder: ignore */ - break; - default: // Sure is sure - strcpy(CPUInfo.strFamily, "Unknown Intel Pentium 4+"); /* Flawfinder: ignore */ - break; - } - break; - default: // Failsave - strcpy(CPUInfo.strFamily, "Unknown"); /* Flawfinder: ignore */ - break; - } - - // Now we come to the big deal, the exact model name - switch (CPUInfo.uiFamily) - { - case 3: // i386 (80386) processor family - strcpy(CPUInfo.strModel, "Unknown Intel i386"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i386", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 4: // i486 (80486) processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: i486 DX-25/33 processor model - strcpy(CPUInfo.strModel, "Intel i486 DX-25/33"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX-25/33", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 1: // Model = 1: i486 DX-50 processor model - strcpy(CPUInfo.strModel, "Intel i486 DX-50"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX-50", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 2: // Model = 2: i486 SX processor model - strcpy(CPUInfo.strModel, "Intel i486 SX"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 SX", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 3: // Model = 3: i486 DX2 (with i487 numeric coprocessor) processor model - strcpy(CPUInfo.strModel, "Intel i486 487/DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX2 with i487 numeric coprocessor", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 4: // Model = 4: i486 SL processor model (never heard ?!?) - strcpy(CPUInfo.strModel, "Intel i486 SL"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 SL", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 5: // Model = 5: i486 SX2 processor model - strcpy(CPUInfo.strModel, "Intel i486 SX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 SX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 7: // Model = 7: i486 write-back enhanced DX2 processor model - strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 write-back enhanced DX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 8: // Model = 8: i486 DX4 processor model - strcpy(CPUInfo.strModel, "Intel i486 DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 9: // Model = 9: i486 write-back enhanced DX4 processor model - strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown Intel i486"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 (Unknown model)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - } - break; - case 5: // Pentium (80586) processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: Pentium (P5 A-Step) processor model - strcpy(CPUInfo.strModel, "Intel Pentium (P5 A-Step)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium (P5 A-Step core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; // Famous for the DIV bug, as far as I know - case 1: // Model = 1: Pentium 60/66 processor model - strcpy(CPUInfo.strModel, "Intel Pentium 60/66 (P5)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 60/66 (P5 core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 2: // Model = 2: Pentium 75-200 (P54C) processor model - strcpy(CPUInfo.strModel, "Intel Pentium 75-200 (P54C)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 75-200 (P54C core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 3: // Model = 3: Pentium overdrive for 486 systems processor model - strcpy(CPUInfo.strModel, "Intel Pentium for 486 system (P24T Overdrive)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium for 486 (P24T overdrive core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 4: // Model = 4: Pentium MMX processor model - strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 7: // Model = 7: Pentium processor model (don't know difference to Model=2) - strcpy(CPUInfo.strModel, "Intel Pentium (P54C)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 8: // Model = 8: Pentium MMX (0.25 micron) processor model - strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C), 0.25 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium MMX (P55C core), 0.25 micron", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown Intel Pentium"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium (Unknown P5-model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 6: // Pentium Pro (80686) processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: Pentium Pro (P6 A-Step) processor model - strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6 A-Step)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium Pro (P6 A-Step core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 1: // Model = 1: Pentium Pro - strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium Pro (P6 core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 3: // Model = 3: Pentium II (66 MHz FSB, I think) processor model - strcpy(CPUInfo.strModel, "Intel Pentium II Model 3, 0.28 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium II (Model 3 core, 0.28 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 5: // Model = 5: Pentium II/Xeon/Celeron (0.25 micron) processor model - strcpy(CPUInfo.strModel, "Intel Pentium II Model 5/Xeon/Celeron, 0.25 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium II/Xeon/Celeron (Model 5 core, 0.25 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 6: // Model = 6: Pentium II with internal L2 cache - strcpy(CPUInfo.strModel, "Intel Pentium II - internal L2 cache"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium II with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 7: // Model = 7: Pentium III/Xeon (extern L2 cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Pentium III Xeon - external L2 cache, 0.25 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium III/Pentium III Xeon (0.25 micron process) with external L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 8: // Model = 8: Pentium III/Xeon/Celeron (256 KB on-die L2 cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/ - // We want to know it exactly: - switch (CPUInfo.uiBrandID) - { - case 1: // Model = 8, Brand id = 1: Celeron (on-die L2 cache) processor model - strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 2: // Model = 8, Brand id = 2: Pentium III (on-die L2 cache) processor model (my current cpu :-)) - strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 3: // Model = 8, Brand id = 3: Pentium III Xeon (on-die L2 cache) processor model - strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // ... - strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 9: // Model = 9: Intel Pentium M processor, Intel Celeron M processor, model 9 - strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 0xA: // Model = 0xA: Pentium III/Xeon/Celeron (1 or 2 MB on-die L2 cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/ - // Exact detection: - switch (CPUInfo.uiBrandID) - { - case 1: // Model = 0xA, Brand id = 1: Celeron (1 or 2 MB on-die L2 cache (does it exist??)) processor model - strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 2: // Model = 0xA, Brand id = 2: Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model - strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 3: // Model = 0xA, Brand id = 3: Pentium III Xeon (1 or 2 MB on-die L2 cache) processor model - strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // Getting bored of this............ - strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 0xB: // Model = 0xB: Pentium III/Xeon/Celeron (Tualatin core, on-die cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.13 micron"); /*Flawfinder: ignore*/ - // Omniscient: ;-) - switch (CPUInfo.uiBrandID) - { - case 3: // Model = 0xB, Brand id = 3: Celeron (Tualatin core) processor model - strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 4: // Model = 0xB, Brand id = 4: Pentium III (Tualatin core) processor model - strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 7: // Model = 0xB, Brand id = 7: Celeron mobile (Tualatin core) processor model - strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // *bored* - strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 0xD: // Model = 0xD: Intel Pentium M processor, Intel Celeron M processor, model D - strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 0xE: // Model = 0xE: Intel Core Duo processor, Intel Core Solo processor, model E - strcpy(CPUInfo.strModel, "Intel Core Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 0xF: // Model = 0xF: Intel Core 2 Duo processor, model F - strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // *more bored* - strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 15: // Extended processor family - // Masking the extended model - CPUInfo.uiExtendedModel = (eaxreg >> 16) & 0xFF; - switch (CPUInfo.uiModel) + // Interpret CPU feature information. + if (i == 1) { - case 0: // Model = 0: Pentium 4 Willamette (A-Step) core - if ((CPUInfo.uiBrandID) == 8) // Brand id = 8: P4 Willamette - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette (A-Step)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium 4 Willamette (A-Step)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - } - else // else Xeon - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon (A-Step)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Willamette Xeon (A-Step)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - break; - case 1: // Model = 1: Pentium 4 Willamette core - if ((CPUInfo.uiBrandID) == 8) // Brand id = 8: P4 Willamette + setInfo(eStepping, cpu_info[0] & 0xf); + setInfo(eModel, (cpu_info[0] >> 4) & 0xf); + int family = (cpu_info[0] >> 8) & 0xf; + setInfo(eFamily, family); + setInfo(eType, (cpu_info[0] >> 12) & 0x3); + setInfo(eExtendedModel, (cpu_info[0] >> 16) & 0xf); + int ext_family = (cpu_info[0] >> 20) & 0xff; + setInfo(eExtendedFamily, ext_family); + setInfo(eBrandID, cpu_info[1] & 0xff); + + setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family)); + + setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + + if(cpu_info[2] & 0x1) + { + setExtension(cpu_feature_names[eSSE3_Features]); + } + + if(cpu_info[2] & 0x8) + { + setExtension(cpu_feature_names[eMONTIOR_MWAIT]); + } + + if(cpu_info[2] & 0x10) + { + setExtension(cpu_feature_names[eCPLDebugStore]); + } + + if(cpu_info[2] & 0x100) + { + setExtension(cpu_feature_names[eThermalMonitor2]); + } + + unsigned int feature_info = (unsigned int) cpu_info[3]; + for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) + { + if(feature_info & bit) { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ + setExtension(cpu_feature_names[index]); } - else // else Xeon - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - break; - case 2: // Model = 2: Pentium 4 Northwood core - if (((CPUInfo.uiBrandID) == 9) || ((CPUInfo.uiBrandID) == 0xA)) // P4 Willamette - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Northwood", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - else // Xeon - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood Xeon"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Northwood Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - break; - default: // Silly stupid never used failsave option - strcpy(CPUInfo.strModel, "Unknown Intel Pentium 4"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - break; + } } - break; - default: // *grmpf* - strcpy(CPUInfo.strModel, "Unknown Intel model"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - break; - } - - // After the long processor model block we now come to the processors serial - // number. - // First of all we check if the processor supports the serial number - if (CPUInfo.MaxSupportedLevel >= 3) - { - // If it supports the serial number CPUID level 0x00000003 we read the data - unsigned long sig1, sig2, sig3; - __asm - { - mov eax, 1 - cpuid - mov sig1, eax - mov eax, 3 - cpuid - mov sig2, ecx - mov sig3, edx } - // Then we convert the data to a readable string - snprintf( /* Flawfinder: ignore */ - CPUInfo.strProcessorSerial, - sizeof(CPUInfo.strProcessorSerial), - "%04lX-%04lX-%04lX-%04lX-%04lX-%04lX", - sig1 >> 16, - sig1 & 0xFFFF, - sig3 >> 16, - sig3 & 0xFFFF, - sig2 >> 16, sig2 & 0xFFFF); - } - else - { - // If there's no serial number support we just put "No serial number" - snprintf( /* Flawfinder: ignore */ - CPUInfo.strProcessorSerial, - sizeof(CPUInfo.strProcessorSerial), - "No Processor Serial Number"); - } - - // Now we get the standard processor extensions - GetStandardProcessorExtensions(); - // And finally the processor configuration (caches, TLBs, ...) and translate - // the data to readable strings - GetStandardProcessorConfiguration(); - TranslateProcessorConfiguration(); + // Calling __cpuid with 0x80000000 as the InfoType argument + // gets the number of valid extended IDs. + __cpuid(cpu_info, 0x80000000); + unsigned int ext_ids = cpu_info[0]; + setConfig(eMaxExtID, 0); - // At last... - return true; -#else - return FALSE; -#endif -} + char cpu_brand_string[0x40]; + memset(cpu_brand_string, 0, sizeof(cpu_brand_string)); -// bool CProcessor::AnalyzeAMDProcessor() -// ====================================== -// Private class function for analyzing an AMD processor -//////////////////////////////////////////////////////// -bool CProcessor::AnalyzeAMDProcessor() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, ecxreg, edxreg; - - // First of all we check if the CPUID command is available - if (!CheckCPUIDPresence()) - return 0; - - // Now we get the CPUID standard level 0x00000001 - __asm - { - mov eax, 1 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov edxreg, edx - } - - // Then we mask the model, family, stepping and type (AMD does not support brand id) - CPUInfo.uiStepping = eaxreg & 0xF; - CPUInfo.uiModel = (eaxreg >> 4) & 0xF; - CPUInfo.uiFamily = (eaxreg >> 8) & 0xF; - CPUInfo.uiType = (eaxreg >> 12) & 0x3; - - // Now we check if the processor supports the brand id string extended CPUID level - if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000004) - { - // If it supports the extended CPUID level 0x80000004 we read the data - char tmp[52]; /* Flawfinder: ignore */ - memset(tmp, 0, sizeof(tmp)); - __asm + // Get the information associated with each extended ID. + for(unsigned int i=0x80000000; i<=ext_ids; ++i) { - mov eax, 0x80000002 - cpuid - mov dword ptr [tmp], eax - mov dword ptr [tmp+4], ebx - mov dword ptr [tmp+8], ecx - mov dword ptr [tmp+12], edx - mov eax, 0x80000003 - cpuid - mov dword ptr [tmp+16], eax - mov dword ptr [tmp+20], ebx - mov dword ptr [tmp+24], ecx - mov dword ptr [tmp+28], edx - mov eax, 0x80000004 - cpuid - mov dword ptr [tmp+32], eax - mov dword ptr [tmp+36], ebx - mov dword ptr [tmp+40], ecx - mov dword ptr [tmp+44], edx - } - // And copy it to the brand id string - strncpy(CPUInfo.strBrandID, tmp,sizeof(CPUInfo.strBrandID)-1); - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; - } - else - { - // Or just tell there is no brand id string support - strcpy(CPUInfo.strBrandID, ""); /* Flawfinder: ignore */ - } - - // After that we translate the processor family - switch(CPUInfo.uiFamily) - { - case 4: // Family = 4: 486 (80486) or 5x86 (80486) processor family - switch (CPUInfo.uiModel) + __cpuid(cpu_info, i); + + // Interpret CPU brand string and cache information. + if (i == 0x80000002) + memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info)); + else if (i == 0x80000003) + memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info)); + else if (i == 0x80000004) { - case 3: // Thanks to AMD for this nice form of family - case 7: // detection.... *grmpf* - case 8: - case 9: - strcpy(CPUInfo.strFamily, "AMD 80486"); /* Flawfinder: ignore */ - break; - case 0xE: - case 0xF: - strcpy(CPUInfo.strFamily, "AMD 5x86"); /* Flawfinder: ignore */ - break; - default: - strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */ - break; + memcpy(cpu_brand_string + 32, cpu_info, sizeof(cpu_info)); + setInfo(eBrandName, cpu_brand_string); } - break; - case 5: // Family = 5: K5 or K6 processor family - switch (CPUInfo.uiModel) + else if (i == 0x80000006) { - case 0: - case 1: - case 2: - case 3: - strcpy(CPUInfo.strFamily, "AMD K5"); /* Flawfinder: ignore */ - break; - case 6: - case 7: - case 8: - case 9: - strcpy(CPUInfo.strFamily, "AMD K6"); /* Flawfinder: ignore */ - break; - default: - strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */ - break; + setConfig(eCacheLineSize, cpu_info[2] & 0xff); + setConfig(eL2Associativity, (cpu_info[2] >> 12) & 0xf); + setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff); } - break; - case 6: // Family = 6: K7 (Athlon, ...) processor family - strcpy(CPUInfo.strFamily, "AMD K7"); /* Flawfinder: ignore */ - break; - default: // For security - strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */ - break; + } } +}; - // After the family detection we come to the specific processor model - // detection - switch (CPUInfo.uiFamily) - { - case 4: // Family = 4: 486 (80486) or 5x85 (80486) processor family - switch (CPUInfo.uiModel) - { - case 3: // Model = 3: 80486 DX2 - strcpy(CPUInfo.strModel, "AMD 80486 DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 7: // Model = 7: 80486 write-back enhanced DX2 - strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 write-back enhanced DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 8: // Model = 8: 80486 DX4 - strcpy(CPUInfo.strModel, "AMD 80486 DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 9: // Model = 9: 80486 write-back enhanced DX4 - strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 write-back enhanced DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 0xE: // Model = 0xE: 5x86 - strcpy(CPUInfo.strModel, "AMD 5x86"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 5x86", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 0xF: // Model = 0xF: 5x86 write-back enhanced (oh my god.....) - strcpy(CPUInfo.strModel, "AMD 5x86 write-back enhanced"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 5x86 write-back enhanced", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD 80486 or 5x86 model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 or 5x86 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - } - break; - case 5: // Family = 5: K5 / K6 processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: K5 SSA 5 (Pentium Rating *ggg* 75, 90 and 100 MHz) - strcpy(CPUInfo.strModel, "AMD K5 SSA5 (PR75, PR90, PR100)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 SSA5 (PR75, PR90, PR100)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 1: // Model = 1: K5 5k86 (PR 120 and 133 MHz) - strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR120, PR133)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 5k86 (PR120, PR133)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 2: // Model = 2: K5 5k86 (PR 166 MHz) - strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR166)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 5k86 (PR166)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 3: // Model = 3: K5 5k86 (PR 200 MHz) - strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR200)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 5k86 (PR200)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 6: // Model = 6: K6 - strcpy(CPUInfo.strModel, "AMD K6 (0.30 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6 (0.30 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 7: // Model = 7: K6 (0.25 micron) - strcpy(CPUInfo.strModel, "AMD K6 (0.25 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6 (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 8: // Model = 8: K6-2 - strcpy(CPUInfo.strModel, "AMD K6-2"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6-2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 9: // Model = 9: K6-III - strcpy(CPUInfo.strModel, "AMD K6-III"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6-III", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 0xD: // Model = 0xD: K6-2+ / K6-III+ - strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 or K6 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - } - break; - case 6: // Family = 6: K7 processor family (AMDs first good processors) - switch (CPUInfo.uiModel) +#elif LL_DARWIN + +#include <mach/machine.h> +#include <sys/sysctl.h> + +class LLProcessorInfoDarwinImpl : public LLProcessorInfoImpl +{ +public: + LLProcessorInfoDarwinImpl() + { + getCPUIDInfo(); + uint64_t frequency = getSysctlInt64("hw.cpufrequency"); + setInfo(eFrequency, (F64)frequency / (F64)1000000); + } + + virtual ~LLProcessorInfoDarwinImpl() {} + +private: + int getSysctlInt(const char* name) + { + int result = 0; + size_t len = sizeof(int); + int error = sysctlbyname(name, (void*)&result, &len, NULL, 0); + return error == -1 ? 0 : result; + } + + uint64_t getSysctlInt64(const char* name) + { + uint64_t value = 0; + size_t size = sizeof(value); + int result = sysctlbyname(name, (void*)&value, &size, NULL, 0); + if ( result == 0 ) + { + if ( size == sizeof( uint64_t ) ) + ; + else if ( size == sizeof( uint32_t ) ) + value = (uint64_t)(( uint32_t *)&value); + else if ( size == sizeof( uint16_t ) ) + value = (uint64_t)(( uint16_t *)&value); + else if ( size == sizeof( uint8_t ) ) + value = (uint64_t)(( uint8_t *)&value); + else { - case 1: // Athlon - strcpy(CPUInfo.strModel, "AMD Athlon (0.25 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 2: // Athlon (0.18 micron) - strcpy(CPUInfo.strModel, "AMD Athlon (0.18 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 3: // Duron (Spitfire core) - strcpy(CPUInfo.strModel, "AMD Duron (Spitfire)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Duron (Spitfire core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 4: // Athlon (Thunderbird core) - strcpy(CPUInfo.strModel, "AMD Athlon (Thunderbird)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon (Thunderbird core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 6: // Athlon MP / Mobile Athlon (Palomino core) - strcpy(CPUInfo.strModel, "AMD Athlon MP/Mobile Athlon (Palomino)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon MP/Mobile Athlon (Palomino core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 7: // Mobile Duron (Morgan core) - strcpy(CPUInfo.strModel, "AMD Mobile Duron (Morgan)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Mobile Duron (Morgan core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD K7 model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K7 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; + LL_WARNS("Unknown type returned from sysctl!") << LL_ENDL; } - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - } - - // Now we read the standard processor extension that are stored in the same - // way the Intel standard extensions are - GetStandardProcessorExtensions(); - - // Then we check if theres an extended CPUID level support - if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000001) - { - // If we can access the extended CPUID level 0x80000001 we get the - // edx register - __asm - { - mov eax, 0x80000001 - cpuid - mov edxreg, edx } - - // Now we can mask some AMD specific cpu extensions - CPUInfo._Ext.EMMX_MultimediaExtensions = CheckBit(edxreg, 22); - CPUInfo._Ext.AA64_AMD64BitArchitecture = CheckBit(edxreg, 29); - CPUInfo._Ext._E3DNOW_InstructionExtensions = CheckBit(edxreg, 30); - CPUInfo._Ext._3DNOW_InstructionExtensions = CheckBit(edxreg, 31); - } - - // After that we check if the processor supports the ext. CPUID level - // 0x80000006 - if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000006) + + return result == -1 ? 0 : value; + } + + void getCPUIDInfo() { - // If it's present, we read it out - __asm - { - mov eax, 0x80000005 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov ecxreg, ecx - mov edxreg, edx - } + size_t len = 0; - // Then we mask the L1 Data TLB information - if ((ebxreg >> 16) && (eaxreg >> 16)) - { - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF; - CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF; - } - else if (eaxreg >> 16) - { - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF; - CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF; - } - else if (ebxreg >> 16) - { - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = (ebxreg >> 24) & 0xFF; - CPUInfo._Data.uiEntries = (ebxreg >> 16) & 0xFF; - } - if (CPUInfo._Data.uiAssociativeWays == 0xFF) - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - - // Now the L1 Instruction/Code TLB information - if ((ebxreg & 0xFFFF) && (eaxreg & 0xFFFF)) - { - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF; - CPUInfo._Instruction.uiEntries = eaxreg & 0xFF; - } - else if (eaxreg & 0xFFFF) - { - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF; - CPUInfo._Instruction.uiEntries = eaxreg & 0xFF; - } - else if (ebxreg & 0xFFFF) - { - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = (ebxreg >> 8) & 0xFF; - CPUInfo._Instruction.uiEntries = ebxreg & 0xFF; - } - if (CPUInfo._Instruction.uiAssociativeWays == 0xFF) - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; + char cpu_brand_string[0x40]; + len = sizeof(cpu_brand_string); + memset(cpu_brand_string, 0, len); + sysctlbyname("machdep.cpu.brand_string", (void*)cpu_brand_string, &len, NULL, 0); + cpu_brand_string[0x3f] = 0; + setInfo(eBrandName, cpu_brand_string); - // Then we read the L1 data cache information - if ((ecxreg >> 24) > 0) - { - CPUInfo._L1.Data.bPresent = true; - snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", ecxreg >> 24); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = (ecxreg >> 15) & 0xFF; - CPUInfo._L1.Data.uiLineSize = ecxreg & 0xFF; - } - // After that we read the L2 instruction/code cache information - if ((edxreg >> 24) > 0) - { - CPUInfo._L1.Instruction.bPresent = true; - snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", edxreg >> 24); /* Flawfinder: ignore */ - CPUInfo._L1.Instruction.uiAssociativeWays = (edxreg >> 15) & 0xFF; - CPUInfo._L1.Instruction.uiLineSize = edxreg & 0xFF; - } - - // Note: I'm not absolutely sure that the L1 page size code (the - // 'if/else if/else if' structs above) really detects the real page - // size for the TLB. Somebody should check it.... - - // Now we read the ext. CPUID level 0x80000006 - __asm - { - mov eax, 0x80000006 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov ecxreg, ecx - } + char cpu_vendor[0x20]; + len = sizeof(cpu_vendor); + memset(cpu_vendor, 0, len); + sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0); + cpu_vendor[0x1f] = 0; + setInfo(eVendor, cpu_vendor); + + setInfo(eStepping, getSysctlInt("machdep.cpu.stepping")); + setInfo(eModel, getSysctlInt("machdep.cpu.model")); + int family = getSysctlInt("machdep.cpu.family"); + int ext_family = getSysctlInt("machdep.cpu.extfamily"); + setInfo(eFamily, family); + setInfo(eExtendedFamily, ext_family); + setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family)); + setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); + setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); + setInfo(eType, 0); // ? where to find this? + + //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize")); + setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity")); + setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size")); + + uint64_t feature_info = getSysctlInt64("machdep.cpu.feature_bits"); + S32 *feature_infos = (S32*)(&feature_info); + + setConfig(eFeatureBits, feature_infos[0]); - // We only mask the unified L2 cache masks (never heard of an - // L2 cache that is divided in data and code parts) - if (((ecxreg >> 12) & 0xF) > 0) + for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) { - CPUInfo._L2.bPresent = true; - snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", ecxreg >> 16); /* Flawfinder: ignore */ - switch ((ecxreg >> 12) & 0xF) + if(feature_info & bit) { - case 1: - CPUInfo._L2.uiAssociativeWays = 1; - break; - case 2: - CPUInfo._L2.uiAssociativeWays = 2; - break; - case 4: - CPUInfo._L2.uiAssociativeWays = 4; - break; - case 6: - CPUInfo._L2.uiAssociativeWays = 8; - break; - case 8: - CPUInfo._L2.uiAssociativeWays = 16; - break; - case 0xF: - CPUInfo._L2.uiAssociativeWays = (unsigned int) -1; - break; - default: - CPUInfo._L2.uiAssociativeWays = 0; - break; + setExtension(cpu_feature_names[index]); } - CPUInfo._L2.uiLineSize = ecxreg & 0xFF; } - } - else - { - // If we could not detect the ext. CPUID level 0x80000006 we - // try to read the standard processor configuration. - GetStandardProcessorConfiguration(); - } - // After reading we translate the configuration to strings - TranslateProcessorConfiguration(); - - // And finally exit - return true; -#else - return FALSE; -#endif -} - -// bool CProcessor::AnalyzeUnknownProcessor() -// ========================================== -// Private class function to analyze an unknown (No Intel or AMD) processor -/////////////////////////////////////////////////////////////////////////// -bool CProcessor::AnalyzeUnknownProcessor() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg; - - // We check if the CPUID command is available - if (!CheckCPUIDPresence()) - return false; - - // First of all we read the standard CPUID level 0x00000001 - // This level should be available on every x86-processor clone - __asm - { - mov eax, 1 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - } - // Then we mask the processor model, family, type and stepping - CPUInfo.uiStepping = eaxreg & 0xF; - CPUInfo.uiModel = (eaxreg >> 4) & 0xF; - CPUInfo.uiFamily = (eaxreg >> 8) & 0xF; - CPUInfo.uiType = (eaxreg >> 12) & 0x3; - - // To have complete information we also mask the brand id - CPUInfo.uiBrandID = ebxreg & 0xF; - - // Then we get the standard processor extensions - GetStandardProcessorExtensions(); - - // Now we mark everything we do not know as unknown - strcpy(strCPUName, "Unknown"); /*Flawfinder: ignore*/ - - strcpy(CPUInfo._Data.strTLB, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._Instruction.strTLB, "Unknown"); /*Flawfinder: ignore*/ - - strcpy(CPUInfo._Trace.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L1.Data.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L1.Instruction.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L2.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L3.strCache, "Unknown"); /*Flawfinder: ignore*/ - - strcpy(CPUInfo.strProcessorSerial, "Unknown / Not supported"); /*Flawfinder: ignore*/ - - // For the family, model and brand id we can only print the numeric value - snprintf(CPUInfo.strBrandID, sizeof(CPUInfo.strBrandID), "Brand-ID number %d", CPUInfo.uiBrandID); /* Flawfinder: ignore */ - snprintf(CPUInfo.strFamily, sizeof(CPUInfo.strFamily), "Family number %d", CPUInfo.uiFamily); /* Flawfinder: ignore */ - snprintf(CPUInfo.strModel, sizeof(CPUInfo.strModel), "Model number %d", CPUInfo.uiModel); /* Flawfinder: ignore */ - - // And thats it - return true; -#else - return FALSE; -#endif -} - -// bool CProcessor::CheckCPUIDPresence() -// ===================================== -// This function checks if the CPUID command is available on the current -// processor -//////////////////////////////////////////////////////////////////////// -bool CProcessor::CheckCPUIDPresence() -{ -#if LL_WINDOWS - unsigned long BitChanged; - - // We've to check if we can toggle the flag register bit 21 - // If we can't the processor does not support the CPUID command - __asm - { - pushfd - pop eax - mov ebx, eax - xor eax, 0x00200000 - push eax - popfd - pushfd - pop eax - xor eax,ebx - mov BitChanged, eax - } - return ((BitChanged) ? true : false); -#else - return FALSE; -#endif -} + // *NOTE:Mani - I didn't find any docs that assure me that machdep.cpu.feature_bits will always be + // The feature bits I think it is. Here's a test: +#ifndef LL_RELEASE_FOR_DOWNLOAD + #if defined(__i386__) && defined(__PIC__) + /* %ebx may be the PIC register. */ + #define __cpuid(level, a, b, c, d) \ + __asm__ ("xchgl\t%%ebx, %1\n\t" \ + "cpuid\n\t" \ + "xchgl\t%%ebx, %1\n\t" \ + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + #else + #define __cpuid(level, a, b, c, d) \ + __asm__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + #endif + + unsigned int eax, ebx, ecx, edx; + __cpuid(0x1, eax, ebx, ecx, edx); + if(feature_infos[0] != (S32)edx) + { + llerrs << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << llendl; + } +#endif // LL_RELEASE_FOR_DOWNLOAD -// void CProcessor::DecodeProcessorConfiguration(unsigned int cfg) -// =============================================================== -// This function (or switch ?!) just translates a one-byte processor configuration -// byte to understandable values -////////////////////////////////////////////////////////////////////////////////// -void CProcessor::DecodeProcessorConfiguration(unsigned int cfg) -{ - // First we ensure that there's only one single byte - cfg &= 0xFF; - // Then we do a big switch - switch(cfg) - { - case 0: // cfg = 0: Unused - break; - case 0x1: // cfg = 0x1: code TLB present, 4 KB pages, 4 ways, 32 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = 4; - CPUInfo._Instruction.uiEntries = 32; - break; - case 0x2: // cfg = 0x2: code TLB present, 4 MB pages, fully associative, 2 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 MB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = 4; - CPUInfo._Instruction.uiEntries = 2; - break; - case 0x3: // cfg = 0x3: data TLB present, 4 KB pages, 4 ways, 64 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = 4; - CPUInfo._Data.uiEntries = 64; - break; - case 0x4: // cfg = 0x4: data TLB present, 4 MB pages, 4 ways, 8 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 MB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = 4; - CPUInfo._Data.uiEntries = 8; - break; - case 0x6: // cfg = 0x6: code L1 cache present, 8 KB, 4 ways, 32 byte lines - CPUInfo._L1.Instruction.bPresent = true; - strcpy(CPUInfo._L1.Instruction.strSize, "8 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Instruction.uiAssociativeWays = 4; - CPUInfo._L1.Instruction.uiLineSize = 32; - break; - case 0x8: // cfg = 0x8: code L1 cache present, 16 KB, 4 ways, 32 byte lines - CPUInfo._L1.Instruction.bPresent = true; - strcpy(CPUInfo._L1.Instruction.strSize, "16 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Instruction.uiAssociativeWays = 4; - CPUInfo._L1.Instruction.uiLineSize = 32; - break; - case 0xA: // cfg = 0xA: data L1 cache present, 8 KB, 2 ways, 32 byte lines - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "8 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Data.uiAssociativeWays = 2; - CPUInfo._L1.Data.uiLineSize = 32; - break; - case 0xC: // cfg = 0xC: data L1 cache present, 16 KB, 4 ways, 32 byte lines - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "16 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 32; - break; - case 0x22: // cfg = 0x22: code and data L3 cache present, 512 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "512 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 4; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x23: // cfg = 0x23: code and data L3 cache present, 1024 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "1024 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 8; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x25: // cfg = 0x25: code and data L3 cache present, 2048 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "2048 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 8; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x29: // cfg = 0x29: code and data L3 cache present, 4096 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "4096 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 8; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x40: // cfg = 0x40: no integrated L2 cache (P6 core) or L3 cache (P4 core) - break; - case 0x41: // cfg = 0x41: code and data L2 cache present, 128 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "128 KB"); /*Flawfinder: ignore*/ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x42: // cfg = 0x42: code and data L2 cache present, 256 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "256 KB"); /*Flawfinder: ignore*/ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x43: // cfg = 0x43: code and data L2 cache present, 512 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x44: // cfg = 0x44: code and data L2 cache present, 1024 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x45: // cfg = 0x45: code and data L2 cache present, 2048 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "2 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x50: // cfg = 0x50: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 64 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Instruction.uiEntries = 64; - break; - case 0x51: // cfg = 0x51: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 128 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Instruction.uiEntries = 128; - break; - case 0x52: // cfg = 0x52: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 256 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Instruction.uiEntries = 256; - break; - case 0x5B: // cfg = 0x5B: data TLB present, 4 KB / 4 MB pages, fully associative, 64 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Data.uiEntries = 64; - break; - case 0x5C: // cfg = 0x5C: data TLB present, 4 KB / 4 MB pages, fully associative, 128 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Data.uiEntries = 128; - break; - case 0x5d: // cfg = 0x5D: data TLB present, 4 KB / 4 MB pages, fully associative, 256 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Data.uiEntries = 256; - break; - case 0x66: // cfg = 0x66: data L1 cache present, 8 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "8 KB"); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 64; - break; - case 0x67: // cfg = 0x67: data L1 cache present, 16 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "16 KB"); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 64; - break; - case 0x68: // cfg = 0x68: data L1 cache present, 32 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "32 KB"); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 64; - break; - case 0x70: // cfg = 0x70: trace L1 cache present, 12 KuOPs, 4 ways - CPUInfo._Trace.bPresent = true; - strcpy(CPUInfo._Trace.strSize, "12 K-micro-ops"); /* Flawfinder: ignore */ - CPUInfo._Trace.uiAssociativeWays = 4; - break; - case 0x71: // cfg = 0x71: trace L1 cache present, 16 KuOPs, 4 ways - CPUInfo._Trace.bPresent = true; - strcpy(CPUInfo._Trace.strSize, "16 K-micro-ops"); /* Flawfinder: ignore */ - CPUInfo._Trace.uiAssociativeWays = 4; - break; - case 0x72: // cfg = 0x72: trace L1 cache present, 32 KuOPs, 4 ways - CPUInfo._Trace.bPresent = true; - strcpy(CPUInfo._Trace.strSize, "32 K-micro-ops"); /* Flawfinder: ignore */ - CPUInfo._Trace.uiAssociativeWays = 4; - break; - case 0x79: // cfg = 0x79: code and data L2 cache present, 128 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "128 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x7A: // cfg = 0x7A: code and data L2 cache present, 256 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "256 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x7B: // cfg = 0x7B: code and data L2 cache present, 512 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x7C: // cfg = 0x7C: code and data L2 cache present, 1024 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x81: // cfg = 0x81: code and data L2 cache present, 128 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "128 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x82: // cfg = 0x82: code and data L2 cache present, 256 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "256 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x83: // cfg = 0x83: code and data L2 cache present, 512 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x84: // cfg = 0x84: code and data L2 cache present, 1024 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x85: // cfg = 0x85: code and data L2 cache present, 2048 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "2 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; + uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits"); + S32 *ext_feature_infos = (S32*)(&ext_feature_info); + setConfig(eExtFeatureBits, ext_feature_infos[0]); } -} +}; -FORCEINLINE static char *TranslateAssociativeWays(unsigned int uiWays, char *buf) -{ - // We define 0xFFFFFFFF (= -1) as fully associative - if (uiWays == ((unsigned int) -1)) - strcpy(buf, "fully associative"); /* Flawfinder: ignore */ - else - { - if (uiWays == 1) // A one way associative cache is just direct mapped - strcpy(buf, "direct mapped"); /* Flawfinder: ignore */ - else if (uiWays == 0) // This should not happen... - strcpy(buf, "unknown associative ways"); /* Flawfinder: ignore */ - else // The x-way associative cache - sprintf(buf, "%d ways associative", uiWays); /* Flawfinder: ignore */ - } - // To ease the function use we return the buffer - return buf; -} -FORCEINLINE static void TranslateTLB(ProcessorTLB *tlb) -{ - char buf[64]; /* Flawfinder: ignore */ +#elif LL_LINUX +const char CPUINFO_FILE[] = "/proc/cpuinfo"; - // We just check if the TLB is present - if (tlb->bPresent) - snprintf(tlb->strTLB,sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries); /* Flawfinder: ignore */ - else - strcpy(tlb->strTLB, "Not present"); /* Flawfinder: ignore */ -} -FORCEINLINE static void TranslateCache(ProcessorCache *cache) +class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl { - char buf[64]; /* Flawfinder: ignore */ - - // We just check if the cache is present - if (cache->bPresent) - { - // If present we construct the string - snprintf(cache->strCache, sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */ - if (cache->bSectored) - strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1); /* Flawfinder: ignore */ - } - else +public: + LLProcessorInfoLinuxImpl() { - // Else we just say "Not present" - strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */ + get_proc_cpuinfo(); } -} - -// void CProcessor::TranslateProcessorConfiguration() -// ================================================== -// Private class function to translate the processor configuration values -// to strings -///////////////////////////////////////////////////////////////////////// -void CProcessor::TranslateProcessorConfiguration() -{ - // We just call the small functions defined above - TranslateTLB(&CPUInfo._Data); - TranslateTLB(&CPUInfo._Instruction); - TranslateCache(&CPUInfo._Trace); + virtual ~LLProcessorInfoLinuxImpl() {} +private: - TranslateCache(&CPUInfo._L1.Instruction); - TranslateCache(&CPUInfo._L1.Data); - TranslateCache(&CPUInfo._L2); - TranslateCache(&CPUInfo._L3); -} - -// void CProcessor::GetStandardProcessorConfiguration() -// ==================================================== -// Private class function to read the standard processor configuration -////////////////////////////////////////////////////////////////////// -void CProcessor::GetStandardProcessorConfiguration() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, ecxreg, edxreg; - - // We check if the CPUID function is available - if (!CheckCPUIDPresence()) - return; - - // First we check if the processor supports the standard - // CPUID level 0x00000002 - if (CPUInfo.MaxSupportedLevel >= 2) + void get_proc_cpuinfo() { - // Now we go read the std. CPUID level 0x00000002 the first time - unsigned long count, num = 255; - for (count = 0; count < num; count++) + std::map< std::string, std::string > cpuinfo; + LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); + if(cpuinfo_fp) { - __asm - { - mov eax, 2 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov ecxreg, ecx - mov edxreg, edx - } - // We have to repeat this reading for 'num' times - num = eaxreg & 0xFF; - - // Then we call the big decode switch function - DecodeProcessorConfiguration(eaxreg >> 8); - DecodeProcessorConfiguration(eaxreg >> 16); - DecodeProcessorConfiguration(eaxreg >> 24); - - // If ebx contains additional data we also decode it - if ((ebxreg & 0x80000000) == 0) + char line[MAX_STRING]; + memset(line, 0, MAX_STRING); + while(fgets(line, MAX_STRING, cpuinfo_fp)) { - DecodeProcessorConfiguration(ebxreg); - DecodeProcessorConfiguration(ebxreg >> 8); - DecodeProcessorConfiguration(ebxreg >> 16); - DecodeProcessorConfiguration(ebxreg >> 24); - } - // And also the ecx register - if ((ecxreg & 0x80000000) == 0) - { - DecodeProcessorConfiguration(ecxreg); - DecodeProcessorConfiguration(ecxreg >> 8); - DecodeProcessorConfiguration(ecxreg >> 16); - DecodeProcessorConfiguration(ecxreg >> 24); - } - // At last the edx processor register - if ((edxreg & 0x80000000) == 0) - { - DecodeProcessorConfiguration(edxreg); - DecodeProcessorConfiguration(edxreg >> 8); - DecodeProcessorConfiguration(edxreg >> 16); - DecodeProcessorConfiguration(edxreg >> 24); + // /proc/cpuinfo on Linux looks like: + // name\t*: value\n + char* tabspot = strchr( line, '\t' ); + if (tabspot == NULL) + continue; + char* colspot = strchr( tabspot, ':' ); + if (colspot == NULL) + continue; + char* spacespot = strchr( colspot, ' ' ); + if (spacespot == NULL) + continue; + char* nlspot = strchr( line, '\n' ); + if (nlspot == NULL) + nlspot = line + strlen( line ); // Fallback to terminating NUL + std::string linename( line, tabspot ); + std::string llinename(linename); + LLStringUtil::toLower(llinename); + std::string lineval( spacespot + 1, nlspot ); + cpuinfo[ llinename ] = lineval; } + fclose(cpuinfo_fp); + } +# if LL_X86 + +// *NOTE:Mani - eww, macros! srry. +#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \ + if (!cpuinfo[cpuinfo_id].empty()) \ + { setInfo(llpi_id, cpuinfo[cpuinfo_id]);} + +#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \ + {\ + S32 result; \ + if (!cpuinfo[cpuinfo_id].empty() \ + && LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result)) \ + { setInfo(llpi_id, result);} \ + } + + F64 mhz; + if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) + && 200.0 < mhz && mhz < 10000.0) + { + setInfo(eFrequency,(F64)(mhz)); } - } -#endif -} -// void CProcessor::GetStandardProcessorExtensions() -// ================================================= -// Private class function to read the standard processor extensions -/////////////////////////////////////////////////////////////////// -void CProcessor::GetStandardProcessorExtensions() -{ -#if LL_WINDOWS - unsigned long ebxreg, edxreg; + LLPI_SET_INFO_STRING(eBrandName, "model name"); + LLPI_SET_INFO_STRING(eVendor, "vendor_id"); - // We check if the CPUID command is available - if (!CheckCPUIDPresence()) - return; - // We just get the standard CPUID level 0x00000001 which should be - // available on every x86 processor - __asm - { - mov eax, 1 - cpuid - mov ebxreg, ebx - mov edxreg, edx - } - - // Then we mask some bits - CPUInfo._Ext.FPU_FloatingPointUnit = CheckBit(edxreg, 0); - CPUInfo._Ext.VME_Virtual8086ModeEnhancements = CheckBit(edxreg, 1); - CPUInfo._Ext.DE_DebuggingExtensions = CheckBit(edxreg, 2); - CPUInfo._Ext.PSE_PageSizeExtensions = CheckBit(edxreg, 3); - CPUInfo._Ext.TSC_TimeStampCounter = CheckBit(edxreg, 4); - CPUInfo._Ext.MSR_ModelSpecificRegisters = CheckBit(edxreg, 5); - CPUInfo._Ext.PAE_PhysicalAddressExtension = CheckBit(edxreg, 6); - CPUInfo._Ext.MCE_MachineCheckException = CheckBit(edxreg, 7); - CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = CheckBit(edxreg, 8); - CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController = CheckBit(edxreg, 9); - CPUInfo._Ext.APIC_ID = (ebxreg >> 24) & 0xFF; - CPUInfo._Ext.SEP_FastSystemCall = CheckBit(edxreg, 11); - CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters = CheckBit(edxreg, 12); - CPUInfo._Ext.PGE_PTE_GlobalFlag = CheckBit(edxreg, 13); - CPUInfo._Ext.MCA_MachineCheckArchitecture = CheckBit(edxreg, 14); - CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions = CheckBit(edxreg, 15); - CPUInfo._Ext.FGPAT_PageAttributeTable = CheckBit(edxreg, 16); - CPUInfo._Ext.PSE36_36bitPageSizeExtension = CheckBit(edxreg, 17); - CPUInfo._Ext.PN_ProcessorSerialNumber = CheckBit(edxreg, 18); - CPUInfo._Ext.CLFSH_CFLUSH_Instruction = CheckBit(edxreg, 19); - CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize = (ebxreg >> 8) & 0xFF; - CPUInfo._Ext.DS_DebugStore = CheckBit(edxreg, 21); - CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl = CheckBit(edxreg, 22); - CPUInfo._Ext.MMX_MultimediaExtensions = CheckBit(edxreg, 23); - CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = CheckBit(edxreg, 24); - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = CheckBit(edxreg, 25); - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = CheckBit(edxreg, 26); - CPUInfo._Ext.Altivec_Extensions = false; - CPUInfo._Ext.SS_SelfSnoop = CheckBit(edxreg, 27); - CPUInfo._Ext.HT_HyperThreading = CheckBit(edxreg, 28); - CPUInfo._Ext.HT_HyterThreadingSiblings = (ebxreg >> 16) & 0xFF; - CPUInfo._Ext.TM_ThermalMonitor = CheckBit(edxreg, 29); - CPUInfo._Ext.IA64_Intel64BitArchitecture = CheckBit(edxreg, 30); -#endif -} + LLPI_SET_INFO_INT(eStepping, "stepping"); + LLPI_SET_INFO_INT(eModel, "model"); -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, ecxreg, edxreg; + + S32 family; + if (!cpuinfo["cpu family"].empty() + && LLStringUtil::convertToS32(cpuinfo["cpu family"], family)) + { + setInfo(eFamily, family); + } - // First of all we check if the CPUID command is available - if (!CheckCPUIDPresence()) - return NULL; + setInfo(eFamilyName, compute_CPUFamilyName(cpuinfo["vendor_id"].c_str(), family)); - // We read the standard CPUID level 0x00000000 which should - // be available on every x86 processor - __asm - { - mov eax, 0 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov edxreg, edx - mov ecxreg, ecx - } - // Then we connect the single register values to the vendor string - *((unsigned long *) CPUInfo.strVendor) = ebxreg; - *((unsigned long *) (CPUInfo.strVendor+4)) = edxreg; - *((unsigned long *) (CPUInfo.strVendor+8)) = ecxreg; - // Null terminate for string comparisons below. - CPUInfo.strVendor[12] = 0; - - // We can also read the max. supported standard CPUID level - CPUInfo.MaxSupportedLevel = eaxreg & 0xFFFF; - - // Then we read the ext. CPUID level 0x80000000 - __asm - { - mov eax, 0x80000000 - cpuid - mov eaxreg, eax - } - // ...to check the max. supportted extended CPUID level - CPUInfo.MaxSupportedExtendedLevel = eaxreg; - - // Then we switch to the specific processor vendors - // See http://www.sandpile.org/ia32/cpuid.htm - if (!strcmp(CPUInfo.strVendor, "GenuineIntel")) - { - AnalyzeIntelProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "AuthenticAMD")) - { - AnalyzeAMDProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "UMC UMC UMC")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "CyrixInstead")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "NexGenDriven")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "CentaurHauls")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "RiseRiseRise")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "SiS SiS SiS")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "GenuineTMx86")) - { - // Transmeta - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "Geode by NSC")) - { - AnalyzeUnknownProcessor(); - } - else - { - AnalyzeUnknownProcessor(); - } -#endif - // After all we return the class CPUInfo member var - return (&CPUInfo); -} + // setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); + // setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); + // setInfo(eType, 0); // ? where to find this? -#elif LL_SOLARIS -#include <kstat.h> - -#if defined(__i386) -#include <sys/auxv.h> -#endif - -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ - uqwFrequency = 0; - strCPUName[0] = 0; - memset(&CPUInfo, 0, sizeof(CPUInfo)); -} - -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to query the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/) -{ - if(uqwFrequency == 0){ - GetCPUInfo(); - } - - return uqwFrequency; -} - -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ - // In Solaris the CPU info is in the kstats - // try "psrinfo" or "kstat cpu_info" to see all - // that's available - int ncpus=0, i; - kstat_ctl_t *kc; - kstat_t *ks; - kstat_named_t *ksinfo, *ksi; - kstat_t *CPU_stats_list; - - kc = kstat_open(); - - if((int)kc == -1){ - llwarns << "kstat_open(0 failed!" << llendl; - return (&CPUInfo); - } - - for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next) { - if (strncmp(ks->ks_module, "cpu_info", 8) == 0 && - strncmp(ks->ks_name, "cpu_info", 8) == 0) - ncpus++; - } - - if(ncpus < 1){ - llwarns << "No cpus found in kstats!" << llendl; - return (&CPUInfo); - } - - for (ks = kc->kc_chain; ks; ks = ks->ks_next) { - if (strncmp(ks->ks_module, "cpu_info", 8) == 0 - && strncmp(ks->ks_name, "cpu_info", 8) == 0 - && kstat_read(kc, ks, NULL) != -1){ - CPU_stats_list = ks; // only looking at the first CPU - - break; - } - } - - if(ncpus > 1) - snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpus); - - kstat_read(kc, CPU_stats_list, NULL); - ksinfo = (kstat_named_t *)CPU_stats_list->ks_data; - for(i=0; i < (int)(CPU_stats_list->ks_ndata); ++i){ // Walk the kstats for this cpu gathering what we need - ksi = ksinfo++; - if(!strcmp(ksi->name, "brand")){ - strncat(strCPUName, (char *)KSTAT_NAMED_STR_PTR(ksi), - sizeof(strCPUName)-strlen(strCPUName)-1); - strncat(CPUInfo.strFamily, (char *)KSTAT_NAMED_STR_PTR(ksi), - sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); - strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1); - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; - // DEBUG llinfos << "CPU brand: " << strCPUName << llendl; - continue; - } + //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + //setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize")); + //setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity")); + //setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size")); + + // Read extensions + std::string flags = " " + cpuinfo["flags"] + " "; + LLStringUtil::toLower(flags); - if(!strcmp(ksi->name, "clock_MHz")){ -#if defined(__sparc) - llinfos << "Raw kstat clock rate is: " << ksi->value.l << llendl; - uqwFrequency = (F64)(ksi->value.l * 1000000); -#else - uqwFrequency = (F64)(ksi->value.i64 * 1000000); -#endif - //DEBUG llinfos << "CPU frequency: " << uqwFrequency << llendl; - continue; + if( flags.find( " sse " ) != std::string::npos ) + { + setExtension(cpu_feature_names[eSSE_Ext]); } -#if defined(__i386) - if(!strcmp(ksi->name, "vendor_id")){ - strncpy(CPUInfo.strVendor, (char *)KSTAT_NAMED_STR_PTR(ksi), sizeof(CPUInfo.strVendor)-1); - // DEBUG llinfos << "CPU vendor: " << CPUInfo.strVendor << llendl; - continue; + if( flags.find( " sse2 " ) != std::string::npos ) + { + setExtension(cpu_feature_names[eSSE2_Ext]); } -#endif - } - - kstat_close(kc); - -#if defined(__sparc) // SPARC does not define a vendor string in kstat - strncpy(CPUInfo.strVendor, "Sun Microsystems, Inc.", sizeof(CPUInfo.strVendor)-1); -#endif - - // DEBUG llinfo << "The system has " << ncpus << " CPUs with a clock rate of " << uqwFrequency << "MHz." << llendl; - -#if defined (__i386) // we really don't care about the CPU extensions on SPARC but on x86... - - // Now get cpu extensions - - uint_t ui; - - (void) getisax(&ui, 1); - if(ui & AV_386_FPU) - CPUInfo._Ext.FPU_FloatingPointUnit = true; - if(ui & AV_386_CX8) - CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = true; - if(ui & AV_386_MMX) - CPUInfo._Ext.MMX_MultimediaExtensions = true; - if(ui & AV_386_AMD_MMX) - CPUInfo._Ext.MMX_MultimediaExtensions = true; - if(ui & AV_386_FXSR) - CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = true; - if(ui & AV_386_SSE) - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = true; - if(ui & AV_386_SSE2) - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = true; -/* Left these here since they may get used later - if(ui & AV_386_SSE3) - CPUInfo._Ext.... = true; - if(ui & AV_386_AMD_3DNow) - CPUInfo._Ext.... = true; - if(ui & AV_386_AMD_3DNowx) - CPUInfo._Ext.... = true; -*/ -#endif - return (&CPUInfo); -} - -#else -// LL_DARWIN - -#include <mach/machine.h> -#include <sys/sysctl.h> - -static char *TranslateAssociativeWays(unsigned int uiWays, char *buf) -{ - // We define 0xFFFFFFFF (= -1) as fully associative - if (uiWays == ((unsigned int) -1)) - strcpy(buf, "fully associative"); /* Flawfinder: ignore */ - else - { - if (uiWays == 1) // A one way associative cache is just direct mapped - strcpy(buf, "direct mapped"); /* Flawfinder: ignore */ - else if (uiWays == 0) // This should not happen... - strcpy(buf, "unknown associative ways"); /* Flawfinder: ignore */ - else // The x-way associative cache - sprintf(buf, "%d ways associative", uiWays); /* Flawfinder: ignore */ +# endif // LL_X86 } - // To ease the function use we return the buffer - return buf; -} -static void TranslateTLB(ProcessorTLB *tlb) -{ - char buf[64]; /* Flawfinder: ignore */ - - // We just check if the TLB is present - if (tlb->bPresent) - snprintf(tlb->strTLB, sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries); /* Flawfinder: ignore */ - else - strcpy(tlb->strTLB, "Not present"); /* Flawfinder: ignore */ -} -static void TranslateCache(ProcessorCache *cache) -{ - char buf[64]; /* Flawfinder: ignore */ - // We just check if the cache is present - if (cache->bPresent) + std::string getCPUFeatureDescription() const { - // If present we construct the string - snprintf(cache->strCache,sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */ - if (cache->bSectored) - strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1); /* Flawfinder: ignore */ - } - else - { - // Else we just say "Not present" - strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */ - } -} - -// void CProcessor::TranslateProcessorConfiguration() -// ================================================== -// Private class function to translate the processor configuration values -// to strings -///////////////////////////////////////////////////////////////////////// -void CProcessor::TranslateProcessorConfiguration() -{ - // We just call the small functions defined above - TranslateTLB(&CPUInfo._Data); - TranslateTLB(&CPUInfo._Instruction); - - TranslateCache(&CPUInfo._Trace); + std::ostringstream s; - TranslateCache(&CPUInfo._L1.Instruction); - TranslateCache(&CPUInfo._L1.Data); - TranslateCache(&CPUInfo._L2); - TranslateCache(&CPUInfo._L3); -} - -// CProcessor::CProcessor -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ - uqwFrequency = 0; - strCPUName[0] = 0; - memset(&CPUInfo, 0, sizeof(CPUInfo)); -} - -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to query the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/) -{ - U64 frequency = 0; - size_t len = sizeof(frequency); - - if(sysctlbyname("hw.cpufrequency", &frequency, &len, NULL, 0) == 0) - { - uqwFrequency = (F64)frequency; - } - - return uqwFrequency; -} - -static bool hasFeature(const char *name) -{ - bool result = false; - int val = 0; - size_t len = sizeof(val); - - if(sysctlbyname(name, &val, &len, NULL, 0) == 0) - { - if(val != 0) - result = true; - } - - return result; -} - -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ - int pagesize = 0; - int cachelinesize = 0; - int l1icachesize = 0; - int l1dcachesize = 0; - int l2settings = 0; - int l2cachesize = 0; - int l3settings = 0; - int l3cachesize = 0; - int ncpu = 0; - int cpusubtype = 0; - - // sysctl knows all. - int mib[2]; - size_t len; - mib[0] = CTL_HW; - - mib[1] = HW_PAGESIZE; - len = sizeof(pagesize); - sysctl(mib, 2, &pagesize, &len, NULL, 0); - - mib[1] = HW_CACHELINE; - len = sizeof(cachelinesize); - sysctl(mib, 2, &cachelinesize, &len, NULL, 0); - - mib[1] = HW_L1ICACHESIZE; - len = sizeof(l1icachesize); - sysctl(mib, 2, &l1icachesize, &len, NULL, 0); - - mib[1] = HW_L1DCACHESIZE; - len = sizeof(l1dcachesize); - sysctl(mib, 2, &l1dcachesize, &len, NULL, 0); - - mib[1] = HW_L2SETTINGS; - len = sizeof(l2settings); - sysctl(mib, 2, &l2settings, &len, NULL, 0); - - mib[1] = HW_L2CACHESIZE; - len = sizeof(l2cachesize); - sysctl(mib, 2, &l2cachesize, &len, NULL, 0); - - mib[1] = HW_L3SETTINGS; - len = sizeof(l3settings); - sysctl(mib, 2, &l3settings, &len, NULL, 0); - - mib[1] = HW_L3CACHESIZE; - len = sizeof(l3cachesize); - sysctl(mib, 2, &l3cachesize, &len, NULL, 0); - - mib[1] = HW_NCPU; - len = sizeof(ncpu); - sysctl(mib, 2, &ncpu, &len, NULL, 0); - - sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0); - - strCPUName[0] = 0; - - if((ncpu == 0) || (ncpu == 1)) - { - // Uhhh... - } - else if(ncpu == 2) - { - strncat(strCPUName, "Dual ", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - } - else - { - snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpu); /* Flawfinder: ignore */ - } - -#if __ppc__ - switch(cpusubtype) - { - case CPU_SUBTYPE_POWERPC_601:// ((cpu_subtype_t) 1) - strncat(strCPUName, "PowerPC 601", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - - break; - case CPU_SUBTYPE_POWERPC_602:// ((cpu_subtype_t) 2) - strncat(strCPUName, "PowerPC 602", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_603:// ((cpu_subtype_t) 3) - strncat(strCPUName, "PowerPC 603", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_603e:// ((cpu_subtype_t) 4) - strncat(strCPUName, "PowerPC 603e", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_603ev:// ((cpu_subtype_t) 5) - strncat(strCPUName, "PowerPC 603ev", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_604:// ((cpu_subtype_t) 6) - strncat(strCPUName, "PowerPC 604", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_604e:// ((cpu_subtype_t) 7) - strncat(strCPUName, "PowerPC 604e", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_620:// ((cpu_subtype_t) 8) - strncat(strCPUName, "PowerPC 620", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_750:// ((cpu_subtype_t) 9) - strncat(strCPUName, "PowerPC 750", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G3", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_7400:// ((cpu_subtype_t) 10) - strncat(strCPUName, "PowerPC 7400", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_7450:// ((cpu_subtype_t) 11) - strncat(strCPUName, "PowerPC 7450", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_970:// ((cpu_subtype_t) 100) - strncat(strCPUName, "PowerPC 970", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G5", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - - default: - strncat(strCPUName, "PowerPC (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - } - - CPUInfo._Ext.EMMX_MultimediaExtensions = - CPUInfo._Ext.MMX_MultimediaExtensions = - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = false; - - CPUInfo._Ext.Altivec_Extensions = hasFeature("hw.optional.altivec"); - -#endif - -#if __i386__ - // MBW -- XXX -- TODO -- make this call AnalyzeIntelProcessor()? - switch(cpusubtype) - { - default: - strncat(strCPUName, "i386 (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - } - - CPUInfo._Ext.EMMX_MultimediaExtensions = hasFeature("hw.optional.mmx"); // MBW -- XXX -- this may be wrong... - CPUInfo._Ext.MMX_MultimediaExtensions = hasFeature("hw.optional.mmx"); - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = hasFeature("hw.optional.sse"); - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = hasFeature("hw.optional.sse2"); - CPUInfo._Ext.Altivec_Extensions = false; - CPUInfo._Ext.AA64_AMD64BitArchitecture = hasFeature("hw.optional.x86_64"); - -#endif - - // Terse CPU info uses this string... - strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1); /* Flawfinder: ignore */ - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; - - // Fun cache config stuff... - - if(l1dcachesize != 0) - { - CPUInfo._L1.Data.bPresent = true; - snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", l1dcachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L1.Data.uiAssociativeWays = ???; - CPUInfo._L1.Data.uiLineSize = cachelinesize; + // *NOTE:Mani - This is for linux only. + LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); + if(cpuinfo) + { + char line[MAX_STRING]; + memset(line, 0, MAX_STRING); + while(fgets(line, MAX_STRING, cpuinfo)) + { + line[strlen(line)-1] = ' '; + s << line; + s << std::endl; + } + fclose(cpuinfo); + s << std::endl; + } + else + { + s << "Unable to collect processor information" << std::endl; + } + return s.str(); } + +}; - if(l1icachesize != 0) - { - CPUInfo._L1.Instruction.bPresent = true; - snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", l1icachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L1.Instruction.uiAssociativeWays = ???; - CPUInfo._L1.Instruction.uiLineSize = cachelinesize; - } - if(l2cachesize != 0) - { - CPUInfo._L2.bPresent = true; - snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l2cachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L2.uiAssociativeWays = ???; - CPUInfo._L2.uiLineSize = cachelinesize; - } +#endif // LL_MSVC elif LL_DARWIN elif LL_LINUX - if(l3cachesize != 0) - { - CPUInfo._L2.bPresent = true; - snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l3cachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L2.uiAssociativeWays = ???; - CPUInfo._L2.uiLineSize = cachelinesize; +////////////////////////////////////////////////////// +// Interface definition +LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) +{ + // *NOTE:Mani - not thread safe. + if(!mImpl) + { +#ifdef LL_MSVC + static LLProcessorInfoWindowsImpl the_impl; + mImpl = &the_impl; +#elif LL_DARWIN + static LLProcessorInfoDarwinImpl the_impl; + mImpl = &the_impl; +#else + static LLProcessorInfoLinuxImpl the_impl; + mImpl = &the_impl; +#endif // LL_MSVC } - - CPUInfo._Ext.FPU_FloatingPointUnit = hasFeature("hw.optional.floatingpoint"); - -// printf("pagesize = 0x%x\n", pagesize); -// printf("cachelinesize = 0x%x\n", cachelinesize); -// printf("l1icachesize = 0x%x\n", l1icachesize); -// printf("l1dcachesize = 0x%x\n", l1dcachesize); -// printf("l2settings = 0x%x\n", l2settings); -// printf("l2cachesize = 0x%x\n", l2cachesize); -// printf("l3settings = 0x%x\n", l3settings); -// printf("l3cachesize = 0x%x\n", l3cachesize); - - // After reading we translate the configuration to strings - TranslateProcessorConfiguration(); - - // After all we return the class CPUInfo member var - return (&CPUInfo); } -#endif // LL_DARWIN -// bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen) -// ====================================================================== -// Gets the frequency and processor information and writes it to a string -///////////////////////////////////////////////////////////////////////// -bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen) -{ -#define LENCHECK len = (unsigned int) strlen(buf); if (len >= uiMaxLen) return false; strcpy(strBuffer, buf); strBuffer += len; /*Flawfinder: ignore*/ -#define COPYADD(str) strcpy(buf, str); LENCHECK; /* Flawfinder: ignore */ -#define FORMATADD(format, var) sprintf(buf, format, var); LENCHECK; /* Flawfinder: ignore */ -#define BOOLADD(str, boolvar) COPYADD(str); if (boolvar) { COPYADD(" Yes\n"); } else { COPYADD(" No\n"); } - - char buf[1024]; /* Flawfinder: ignore */ - unsigned int len; - - // First we have to get the frequency - GetCPUFrequency(50); - - // Then we get the processor information - GetCPUInfo(); - - // Now we construct the string (see the macros at function beginning) - strBuffer[0] = 0; - - COPYADD("// CPU General Information\n//////////////////////////\n"); - FORMATADD("Processor name: %s\n", strCPUName); - FORMATADD("Frequency: %.2f MHz\n\n", (float) uqwFrequency / 1000000.0f); - FORMATADD("Vendor: %s\n", CPUInfo.strVendor); - FORMATADD("Family: %s\n", CPUInfo.strFamily); - FORMATADD("Extended family: %d\n", CPUInfo.uiExtendedFamily); - FORMATADD("Model: %s\n", CPUInfo.strModel); - FORMATADD("Extended model: %d\n", CPUInfo.uiExtendedModel); - FORMATADD("Type: %s\n", CPUInfo.strType); - FORMATADD("Brand ID: %s\n", CPUInfo.strBrandID); - if (CPUInfo._Ext.PN_ProcessorSerialNumber) - { - FORMATADD("Processor Serial: %s\n", CPUInfo.strProcessorSerial); - } - else - { - COPYADD("Processor Serial: Disabled\n"); - } -#if !LL_SOLARIS // NOTE: Why bother printing all this when it's irrelavent - - COPYADD("\n\n// CPU Configuration\n////////////////////\n"); - FORMATADD("L1 instruction cache: %s\n", CPUInfo._L1.Instruction.strCache); - FORMATADD("L1 data cache: %s\n", CPUInfo._L1.Data.strCache); - FORMATADD("L2 cache: %s\n", CPUInfo._L2.strCache); - FORMATADD("L3 cache: %s\n", CPUInfo._L3.strCache); - FORMATADD("Trace cache: %s\n", CPUInfo._Trace.strCache); - FORMATADD("Instruction TLB: %s\n", CPUInfo._Instruction.strTLB); - FORMATADD("Data TLB: %s\n", CPUInfo._Data.strTLB); - FORMATADD("Max Supported CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedLevel); - FORMATADD("Max Supported Ext. CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedExtendedLevel); - - COPYADD("\n\n// CPU Extensions\n/////////////////\n"); - BOOLADD("AA64 AMD 64-bit Architecture: ", CPUInfo._Ext.AA64_AMD64BitArchitecture); - BOOLADD("ACPI Thermal Monitor And Clock Control: ", CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl); - BOOLADD("APIC Advanced Programmable Interrupt Controller: ", CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController); - FORMATADD(" APIC-ID: %d\n", CPUInfo._Ext.APIC_ID); - BOOLADD("CLFSH CLFLUSH Instruction Presence: ", CPUInfo._Ext.CLFSH_CFLUSH_Instruction); - FORMATADD(" CLFLUSH Instruction Cache Line Size: %d\n", CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize); - BOOLADD("CMOV Conditional Move And Compare Instructions: ", CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions); - BOOLADD("CX8 COMPXCHG8B Instruction: ", CPUInfo._Ext.CX8_COMPXCHG8B_Instruction); - BOOLADD("DE Debugging Extensions: ", CPUInfo._Ext.DE_DebuggingExtensions); - BOOLADD("DS Debug Store: ", CPUInfo._Ext.DS_DebugStore); - BOOLADD("FGPAT Page Attribute Table: ", CPUInfo._Ext.FGPAT_PageAttributeTable); - BOOLADD("FPU Floating Point Unit: ", CPUInfo._Ext.FPU_FloatingPointUnit); - BOOLADD("FXSR Fast Streaming SIMD Extensions Save/Restore:", CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore); - BOOLADD("HT Hyper Threading: ", CPUInfo._Ext.HT_HyperThreading); - BOOLADD("IA64 Intel 64-Bit Architecture: ", CPUInfo._Ext.IA64_Intel64BitArchitecture); - BOOLADD("MCA Machine Check Architecture: ", CPUInfo._Ext.MCA_MachineCheckArchitecture); - BOOLADD("MCE Machine Check Exception: ", CPUInfo._Ext.MCE_MachineCheckException); - BOOLADD("MMX Multimedia Extensions: ", CPUInfo._Ext.MMX_MultimediaExtensions); - BOOLADD("MMX+ Multimedia Extensions: ", CPUInfo._Ext.EMMX_MultimediaExtensions); - BOOLADD("MSR Model Specific Registers: ", CPUInfo._Ext.MSR_ModelSpecificRegisters); - BOOLADD("MTRR Memory Type Range Registers: ", CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters); - BOOLADD("PAE Physical Address Extension: ", CPUInfo._Ext.PAE_PhysicalAddressExtension); - BOOLADD("PGE PTE Global Flag: ", CPUInfo._Ext.PGE_PTE_GlobalFlag); - if (CPUInfo._Ext.PN_ProcessorSerialNumber) - { - FORMATADD("PN Processor Serial Number: %s\n", CPUInfo.strProcessorSerial); - } - else - { - COPYADD("PN Processor Serial Number: Disabled\n"); - } - BOOLADD("PSE Page Size Extensions: ", CPUInfo._Ext.PSE_PageSizeExtensions); - BOOLADD("PSE36 36-bit Page Size Extension: ", CPUInfo._Ext.PSE36_36bitPageSizeExtension); - BOOLADD("SEP Fast System Call: ", CPUInfo._Ext.SEP_FastSystemCall); - BOOLADD("SS Self Snoop: ", CPUInfo._Ext.SS_SelfSnoop); - BOOLADD("SSE Streaming SIMD Extensions: ", CPUInfo._Ext.SSE_StreamingSIMD_Extensions); - BOOLADD("SSE2 Streaming SIMD 2 Extensions: ", CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions); - BOOLADD("ALTVEC Altivec Extensions: ", CPUInfo._Ext.Altivec_Extensions); - BOOLADD("TM Thermal Monitor: ", CPUInfo._Ext.TM_ThermalMonitor); - BOOLADD("TSC Time Stamp Counter: ", CPUInfo._Ext.TSC_TimeStampCounter); - BOOLADD("VME Virtual 8086 Mode Enhancements: ", CPUInfo._Ext.VME_Virtual8086ModeEnhancements); - BOOLADD("3DNow! Instructions: ", CPUInfo._Ext._3DNOW_InstructionExtensions); - BOOLADD("Enhanced 3DNow! Instructions: ", CPUInfo._Ext._E3DNOW_InstructionExtensions); -#endif - // Yippie!!! - return true; -} +LLProcessorInfo::~LLProcessorInfo() {} +F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } +bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } +bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); } +bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); } +std::string LLProcessorInfo::getCPUFamilyName() const { return mImpl->getCPUFamilyName(); } +std::string LLProcessorInfo::getCPUBrandName() const { return mImpl->getCPUBrandName(); } +std::string LLProcessorInfo::getCPUFeatureDescription() const { return mImpl->getCPUFeatureDescription(); } -// bool CProcessor::WriteInfoTextFile(const std::string& strFilename) -// =========================================================== -// Takes use of CProcessor::CPUInfoToText and saves the string to a -// file -/////////////////////////////////////////////////////////////////// -bool CProcessor::WriteInfoTextFile(const std::string& strFilename) -{ - char buf[16384]; /* Flawfinder: ignore */ - - // First we get the string - if (!CPUInfoToText(buf, 16383)) - return false; - - // Then we create a new file (CREATE_ALWAYS) - LLFILE *file = LLFile::fopen(strFilename, "w"); /* Flawfinder: ignore */ - if (!file) - return false; - - // After that we write the string to the file - unsigned long dwBytesToWrite, dwBytesWritten; - dwBytesToWrite = (unsigned long) strlen(buf); /*Flawfinder: ignore*/ - dwBytesWritten = (unsigned long) fwrite(buf, 1, dwBytesToWrite, file); - fclose(file); - if (dwBytesToWrite != dwBytesWritten) - return false; - - // Done - return true; -} diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 746d007a7f..fc2c8dacfb 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -30,167 +30,26 @@ * $/LicenseInfo$ */ -// Author: Benjamin Jurke -// File history: 27.02.2002 File created. -/////////////////////////////////////////// - #ifndef LLPROCESSOR_H #define LLPROCESSOR_H +class LLProcessorInfoImpl; -// Options: -/////////// -#if LL_WINDOWS -#define PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -#endif - -#if LL_MSVC && _M_X64 -# define LL_X86_64 1 -# define LL_X86 1 -#elif LL_MSVC && _M_IX86 -# define LL_X86 1 -#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) -# define LL_X86_64 1 -# define LL_X86 1 -#elif LL_GNUC && ( defined(__i386__) ) -# define LL_X86 1 -#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) -# define LL_PPC 1 -#endif - - -struct ProcessorExtensions -{ - bool FPU_FloatingPointUnit; - bool VME_Virtual8086ModeEnhancements; - bool DE_DebuggingExtensions; - bool PSE_PageSizeExtensions; - bool TSC_TimeStampCounter; - bool MSR_ModelSpecificRegisters; - bool PAE_PhysicalAddressExtension; - bool MCE_MachineCheckException; - bool CX8_COMPXCHG8B_Instruction; - bool APIC_AdvancedProgrammableInterruptController; - unsigned int APIC_ID; - bool SEP_FastSystemCall; - bool MTRR_MemoryTypeRangeRegisters; - bool PGE_PTE_GlobalFlag; - bool MCA_MachineCheckArchitecture; - bool CMOV_ConditionalMoveAndCompareInstructions; - bool FGPAT_PageAttributeTable; - bool PSE36_36bitPageSizeExtension; - bool PN_ProcessorSerialNumber; - bool CLFSH_CFLUSH_Instruction; - unsigned int CLFLUSH_InstructionCacheLineSize; - bool DS_DebugStore; - bool ACPI_ThermalMonitorAndClockControl; - bool EMMX_MultimediaExtensions; - bool MMX_MultimediaExtensions; - bool FXSR_FastStreamingSIMD_ExtensionsSaveRestore; - bool SSE_StreamingSIMD_Extensions; - bool SSE2_StreamingSIMD2_Extensions; - bool Altivec_Extensions; - bool SS_SelfSnoop; - bool HT_HyperThreading; - unsigned int HT_HyterThreadingSiblings; - bool TM_ThermalMonitor; - bool IA64_Intel64BitArchitecture; - bool _3DNOW_InstructionExtensions; - bool _E3DNOW_InstructionExtensions; - bool AA64_AMD64BitArchitecture; -}; - -struct ProcessorCache -{ - bool bPresent; - char strSize[32]; /* Flawfinder: ignore */ - unsigned int uiAssociativeWays; - unsigned int uiLineSize; - bool bSectored; - char strCache[128]; /* Flawfinder: ignore */ -}; - -struct ProcessorL1Cache -{ - ProcessorCache Instruction; - ProcessorCache Data; -}; - -struct ProcessorTLB +class LL_COMMON_API LLProcessorInfo { - bool bPresent; - char strPageSize[32]; /* Flawfinder: ignore */ - unsigned int uiAssociativeWays; - unsigned int uiEntries; - char strTLB[128]; /* Flawfinder: ignore */ -}; - -struct ProcessorInfo -{ - char strVendor[16]; /* Flawfinder: ignore */ - unsigned int uiFamily; - unsigned int uiExtendedFamily; - char strFamily[64]; /* Flawfinder: ignore */ - unsigned int uiModel; - unsigned int uiExtendedModel; - char strModel[128]; /* Flawfinder: ignore */ - unsigned int uiStepping; - unsigned int uiType; - char strType[64]; /* Flawfinder: ignore */ - unsigned int uiBrandID; - char strBrandID[64]; /* Flawfinder: ignore */ - char strProcessorSerial[64]; /* Flawfinder: ignore */ - unsigned long MaxSupportedLevel; - unsigned long MaxSupportedExtendedLevel; - ProcessorExtensions _Ext; - ProcessorL1Cache _L1; - ProcessorCache _L2; - ProcessorCache _L3; - ProcessorCache _Trace; - ProcessorTLB _Instruction; - ProcessorTLB _Data; -}; - - -// CProcessor -// ========== -// Class for detecting the processor name, type and available -// extensions as long as it's speed. -///////////////////////////////////////////////////////////// -class CProcessor -{ -// Constructor / Destructor: -//////////////////////////// public: - CProcessor(); - -// Private vars: -//////////////// -public: - F64 uqwFrequency; - char strCPUName[128]; /* Flawfinder: ignore */ - ProcessorInfo CPUInfo; - -// Private functions: -///////////////////// + LLProcessorInfo(); + ~LLProcessorInfo(); + + F64 getCPUFrequency() const; + bool hasSSE() const; + bool hasSSE2() const; + bool hasAltivec() const; + std::string getCPUFamilyName() const; + std::string getCPUBrandName() const; + std::string getCPUFeatureDescription() const; private: - bool AnalyzeIntelProcessor(); - bool AnalyzeAMDProcessor(); - bool AnalyzeUnknownProcessor(); - bool CheckCPUIDPresence(); - void DecodeProcessorConfiguration(unsigned int cfg); - void TranslateProcessorConfiguration(); - void GetStandardProcessorConfiguration(); - void GetStandardProcessorExtensions(); - -// Public functions: -//////////////////// -public: - F64 GetCPUFrequency(unsigned int uiMeasureMSecs); - const ProcessorInfo *GetCPUInfo(); - bool CPUInfoToText(char *strBuffer, unsigned int uiMaxLen); - bool WriteInfoTextFile(const std::string& strFilename); + LLProcessorInfoImpl* mImpl; }; - -#endif +#endif // LLPROCESSOR_H diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 52b1b63209..d41d0c8a3f 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -58,7 +58,6 @@ # include <unistd.h> # include <sys/sysinfo.h> const char MEMINFO_FILE[] = "/proc/meminfo"; -const char CPUINFO_FILE[] = "/proc/cpuinfo"; #elif LL_SOLARIS # include <stdio.h> # include <unistd.h> @@ -513,71 +512,21 @@ U32 LLOSInfo::getProcessResidentSizeKB() LLCPUInfo::LLCPUInfo() { std::ostringstream out; - CProcessor proc; - const ProcessorInfo* info = proc.GetCPUInfo(); + LLProcessorInfo proc; // proc.WriteInfoTextFile("procInfo.txt"); - mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions; - mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions; - mHasAltivec = info->_Ext.Altivec_Extensions; - mCPUMHz = (F64)(proc.GetCPUFrequency(50)/1000000.0F); - mFamily.assign( info->strFamily ); + mHasSSE = proc.hasSSE(); + mHasSSE2 = proc.hasSSE2(); + mHasAltivec = proc.hasAltivec(); + mCPUMHz = (F64)proc.getCPUFrequency(); + mFamily = proc.getCPUFamilyName(); mCPUString = "Unknown"; -#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS - out << proc.strCPUName; + out << proc.getCPUBrandName(); if (200 < mCPUMHz && mCPUMHz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check { out << " (" << mCPUMHz << " MHz)"; } mCPUString = out.str(); - -#elif LL_LINUX - std::map< std::string, std::string > cpuinfo; - LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); - if(cpuinfo_fp) - { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); - while(fgets(line, MAX_STRING, cpuinfo_fp)) - { - // /proc/cpuinfo on Linux looks like: - // name\t*: value\n - char* tabspot = strchr( line, '\t' ); - if (tabspot == NULL) - continue; - char* colspot = strchr( tabspot, ':' ); - if (colspot == NULL) - continue; - char* spacespot = strchr( colspot, ' ' ); - if (spacespot == NULL) - continue; - char* nlspot = strchr( line, '\n' ); - if (nlspot == NULL) - nlspot = line + strlen( line ); // Fallback to terminating NUL - std::string linename( line, tabspot ); - std::string llinename(linename); - LLStringUtil::toLower(llinename); - std::string lineval( spacespot + 1, nlspot ); - cpuinfo[ llinename ] = lineval; - } - fclose(cpuinfo_fp); - } -# if LL_X86 - std::string flags = " " + cpuinfo["flags"] + " "; - LLStringUtil::toLower(flags); - mHasSSE = ( flags.find( " sse " ) != std::string::npos ); - mHasSSE2 = ( flags.find( " sse2 " ) != std::string::npos ); - - F64 mhz; - if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) - && 200.0 < mhz && mhz < 10000.0) - { - mCPUMHz = (F64)(mhz); - } - if (!cpuinfo["model name"].empty()) - mCPUString = cpuinfo["model name"]; -# endif // LL_X86 -#endif // LL_LINUX } bool LLCPUInfo::hasAltivec() const @@ -607,38 +556,9 @@ std::string LLCPUInfo::getCPUString() const void LLCPUInfo::stream(std::ostream& s) const { -#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS // gather machine information. - char proc_buf[CPUINFO_BUFFER_SIZE]; /* Flawfinder: ignore */ - CProcessor proc; - if(proc.CPUInfoToText(proc_buf, CPUINFO_BUFFER_SIZE)) - { - s << proc_buf; - } - else - { - s << "Unable to collect processor information" << std::endl; - } -#else - // *NOTE: This works on linux. What will it do on other systems? - LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); - if(cpuinfo) - { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); - while(fgets(line, MAX_STRING, cpuinfo)) - { - line[strlen(line)-1] = ' '; - s << line; - } - fclose(cpuinfo); - s << std::endl; - } - else - { - s << "Unable to collect processor information" << std::endl; - } -#endif + s << LLProcessorInfo().getCPUFeatureDescription(); + // These are interesting as they reflect our internal view of the // CPU's attributes regardless of platform s << "->mHasSSE: " << (U32)mHasSSE << std::endl; diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 4b6c3df105..0dc3e0b694 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -152,7 +152,7 @@ public: } e_locking_thread; LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex - ~LLMutex(); + virtual ~LLMutex(); void lock(); // blocks void unlock(); diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h index e3663544db..87fe7001e0 100644 --- a/indra/llcommon/llversionserver.h +++ b/indra/llcommon/llversionserver.h @@ -33,10 +33,10 @@ #ifndef LL_LLVERSIONSERVER_H #define LL_LLVERSIONSERVER_H -const S32 LL_VERSION_MAJOR = 1; -const S32 LL_VERSION_MINOR = 31; +const S32 LL_VERSION_MAJOR = 2; +const S32 LL_VERSION_MINOR = 1; const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 203110; +const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Server"; diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index fc3ce6df7e..6e341b83a1 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -34,8 +34,8 @@ #define LL_LLVERSIONVIEWER_H const S32 LL_VERSION_MAJOR = 2; -const S32 LL_VERSION_MINOR = 0; -const S32 LL_VERSION_PATCH = 2; +const S32 LL_VERSION_MINOR = 1; +const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llcommon/tests/llprocessor_test.cpp b/indra/llcommon/tests/llprocessor_test.cpp new file mode 100644 index 0000000000..a9e312b70b --- /dev/null +++ b/indra/llcommon/tests/llprocessor_test.cpp @@ -0,0 +1,67 @@ +/** + * @file llprocessor_test.cpp + * @date 2010-06-01 + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "../test/lltut.h" + +#include "../llprocessor.h" + + +namespace tut +{ + struct processor + { + }; + + typedef test_group<processor> processor_t; + typedef processor_t::object processor_object_t; + tut::processor_t tut_processor("processor"); + + template<> template<> + void processor_object_t::test<1>() + { + set_test_name("LLProcessorInfo regression test"); + + LLProcessorInfo pi; + F64 freq = pi.getCPUFrequency(); + //bool sse = pi.hasSSE(); + //bool sse2 = pi.hasSSE2(); + //bool alitvec = pi.hasAltivec(); + std::string family = pi.getCPUFamilyName(); + std::string brand = pi.getCPUBrandName(); + //std::string steam = pi.getCPUFeatureDescription(); + + ensure_not_equals("Unknown Brand name", brand, "Unknown"); + ensure_not_equals("Unknown Family name", family, "Unknown"); + ensure("Reasonable CPU Frequency > 100 && < 10000", freq > 100 && freq < 10000); + } +} diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 4bda00ed86..792a7f1c3c 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -155,25 +155,6 @@ std::string getStartupStateFromLog(std::string& sllog) void LLCrashLogger::gatherFiles() { - - /* - //TODO:This function needs to be reimplemented somewhere in here... - if(!previous_crash && is_crash_log) - { - // Make sure the file isn't too old. - double age = difftime(gLaunchTime, stat_data.st_mtimespec.tv_sec); - - // llinfos << "age is " << age << llendl; - - if(age > 60.0) - { - // The file was last modified more than 60 seconds before the crash reporter was launched. Assume it's stale. - llwarns << "File " << mFilename << " is too old!" << llendl; - return; - } - } - */ - updateApplication("Gathering logs..."); // Figure out the filename of the debug log @@ -209,11 +190,9 @@ void LLCrashLogger::gatherFiles() mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml"); } -#if !LL_DARWIN if(mCrashInPreviousExec) -#else -#endif { + // Restarting after freeze. // Replace the log file ext with .old, since the // instance that launched this process has overwritten // SecondLife.log @@ -225,7 +204,12 @@ void LLCrashLogger::gatherFiles() gatherPlatformSpecificFiles(); //Use the debug log to reconstruct the URL to send the crash report to - if(mDebugLog.has("CurrentSimHost")) + if(mDebugLog.has("CrashHostUrl")) + { + // Crash log receiver has been manually configured. + mCrashHost = mDebugLog["CrashHostUrl"].asString(); + } + else if(mDebugLog.has("CurrentSimHost")) { mCrashHost = "https://"; mCrashHost += mDebugLog["CurrentSimHost"].asString(); @@ -247,7 +231,6 @@ void LLCrashLogger::gatherFiles() mCrashInfo["DebugLog"] = mDebugLog; mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stats.log"); - mFileMap["StackTrace"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); updateApplication("Encoding files..."); @@ -272,8 +255,30 @@ void LLCrashLogger::gatherFiles() trimSLLog(crash_info); } - mCrashInfo[(*itr).first] = rawstr_to_utf8(crash_info); + mCrashInfo[(*itr).first] = LLStringFn::strip_invalid_xml(rawstr_to_utf8(crash_info)); + } + + // Add minidump as binary. + std::string minidump_path = mDebugLog["MinidumpPath"]; + if(minidump_path != "") + { + std::ifstream minidump_stream(minidump_path.c_str(), std::ios_base::in | std::ios_base::binary); + if(minidump_stream.is_open()) + { + minidump_stream.seekg(0, std::ios::end); + size_t length = minidump_stream.tellg(); + minidump_stream.seekg(0, std::ios::beg); + + LLSD::Binary data; + data.resize(length); + + minidump_stream.read(reinterpret_cast<char *>(&(data[0])),length); + minidump_stream.close(); + + mCrashInfo["Minidump"] = data; + } } + mCrashInfo["DebugLog"].erase("MinidumpPath"); } LLSD LLCrashLogger::constructPostData() diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp index b5de104e61..a6ab246a2c 100644 --- a/indra/llimage/llimagepng.cpp +++ b/indra/llimage/llimagepng.cpp @@ -135,6 +135,7 @@ BOOL LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time) if (! pngWrapper.writePng(raw_image, mTmpWriteBuffer)) { setLastError(pngWrapper.getErrorMessage()); + delete[] mTmpWriteBuffer; return FALSE; } diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 2c767a4857..53830b1a14 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -85,10 +85,7 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid, mType(type), mName(name) { - LLStringUtil::replaceNonstandardASCII(mName, ' '); - LLStringUtil::replaceChar(mName, '|', ' '); - LLStringUtil::trim(mName); - LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN); + correctInventoryName(mName); } LLInventoryObject::LLInventoryObject() : @@ -155,12 +152,8 @@ void LLInventoryObject::setUUID(const LLUUID& new_uuid) void LLInventoryObject::rename(const std::string& n) { std::string new_name(n); - LLStringUtil::replaceNonstandardASCII(new_name, ' '); - LLStringUtil::replaceChar(new_name, '|', ' '); - LLStringUtil::trim(new_name); - LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN); - - if( new_name != mName ) + correctInventoryName(new_name); + if( !new_name.empty() && new_name != mName ) { mName = new_name; } @@ -221,10 +214,7 @@ BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream) " %254s %254[^|]", keyword, valuestr); mName.assign(valuestr); - LLStringUtil::replaceNonstandardASCII(mName, ' '); - LLStringUtil::replaceChar(mName, '|', ' '); - LLStringUtil::trim(mName); - LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN); + correctInventoryName(mName); } else { @@ -284,6 +274,15 @@ void LLInventoryObject::updateServer(BOOL) const llwarns << "LLInventoryObject::updateServer() called. Doesn't do anything." << llendl; } +inline +void LLInventoryObject::correctInventoryName(std::string& name) +{ + LLStringUtil::replaceNonstandardASCII(name, ' '); + LLStringUtil::replaceChar(name, '|', ' '); + LLStringUtil::trim(name); + LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN); +} + ///---------------------------------------------------------------------------- /// Class LLInventoryItem diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index b083e305b1..4c6ac83ab8 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -92,9 +92,13 @@ public: void setParent(const LLUUID& new_parent); void setType(LLAssetType::EType type); +private: + // in place correction for inventory name string + void correctInventoryName(std::string& name); + //-------------------------------------------------------------------- // File Support - // Implemented here so that a minimal information set can be transmitted + // Implemented here so that a minimal information set can be transmitted // between simulator and viewer. //-------------------------------------------------------------------- public: diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index 00e77d20e9..5b7e5138ef 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -108,7 +108,8 @@ LLAres::LLAres() : mInitSuccess(false), mListener(new LLAresListener(this)) { - if (ares_init(&chan_) != ARES_SUCCESS) + if (ares_library_init( ARES_LIB_INIT_ALL ) != ARES_SUCCESS || + ares_init(&chan_) != ARES_SUCCESS) { llwarns << "Could not succesfully initialize ares!" << llendl; return; @@ -120,6 +121,7 @@ LLAres::LLAres() : LLAres::~LLAres() { ares_destroy(chan_); + ares_library_cleanup(); } void LLAres::cancel() @@ -473,7 +475,7 @@ bool LLAres::process(U64 timeout) ll_init_apr(); } - int socks[ARES_GETSOCK_MAXNUM]; + ares_socket_t socks[ARES_GETSOCK_MAXNUM]; apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM]; apr_int32_t nsds = 0; int nactive = 0; diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 6bf1347514..fc93793ed8 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -352,7 +352,7 @@ void LLAccordionCtrl::addCollapsibleCtrl(LLView* view) mAccordionTabs.push_back(accordion_tab); accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, mAccordionTabs.size() - 1) ); - + arrange(); } void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view) @@ -523,6 +523,8 @@ void LLAccordionCtrl::arrangeMultiple() void LLAccordionCtrl::arrange() { + updateNoTabsHelpTextVisibility(); + if( mAccordionTabs.size() == 0) { //We do not arrange if we do not have what should be arranged @@ -541,6 +543,8 @@ void LLAccordionCtrl::arrange() S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN; + if (accordion_tab->getFitParent()) + panel_height = accordion_tab->getRect().getHeight(); ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height); show_hide_scrollbar(getRect().getWidth(),getRect().getHeight()); @@ -816,7 +820,7 @@ void LLAccordionCtrl::setFilterSubString(const std::string& filter_string) { LLStringUtil::format_map_t args; args["[SEARCH_TERM]"] = LLURI::escape(filter_string); - std::string text = mNoVisibleTabsOrigString; + std::string text = filter_string.empty() ? LLStringUtil::null : mNoVisibleTabsOrigString; LLStringUtil::format(text, args); mNoVisibleTabsHelpText->setValue(text); diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 82e0234bfc..480b26e130 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -190,6 +190,7 @@ public: void showAndFocusHeader(); void setFitPanel( bool fit ) { mFitPanel = true; } + bool getFitParent() const { return mFitPanel; } protected: void adjustContainerPanel (const LLRect& child_rect); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 72f3a14822..1a4b804ce4 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2791,7 +2791,7 @@ bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width height = llceil(mStyle->getFont()->getLineHeight());; LLUIImagePtr image = mStyle->getImage(); - if( image.notNull()) + if( num_chars>0 && image.notNull()) { width += image->getWidth() + IMAGE_HPAD; height = llmax(height, image->getHeight() + IMAGE_HPAD ); diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp index 16efa4fe2c..90de39ba27 100644 --- a/indra/mac_crash_logger/llcrashloggermac.cpp +++ b/indra/mac_crash_logger/llcrashloggermac.cpp @@ -211,89 +211,6 @@ bool LLCrashLoggerMac::init(void) void LLCrashLoggerMac::gatherPlatformSpecificFiles() { updateApplication("Gathering hardware information..."); - char path[MAX_PATH]; - FSRef folder; - - if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr) - { - // folder is an FSRef to ~/Library/Logs/ - if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr) - { - struct stat dw_stat; - std::string mBuf; - bool isLeopard = false; - // Try the 10.3 path first... - std::string dw_file_name = std::string(path) + std::string("/CrashReporter/Second Life.crash.log"); - int res = stat(dw_file_name.c_str(), &dw_stat); - - if (res) - { - // Try the 10.2 one next... - dw_file_name = std::string(path) + std::string("/Second Life.crash.log"); - res = stat(dw_file_name.c_str(), &dw_stat); - } - - if(res) - { - //10.5: Like 10.3+, except it puts the crash time in the file instead of dividing it up - //using asterisks. Get a directory listing, search for files starting with second life, - //use the last one found. - std::string old_file_name, current_file_name, pathname, mask; - pathname = std::string(path) + std::string("/CrashReporter/"); - mask = "Second Life*"; - while(gDirUtilp->getNextFileInDir(pathname, mask, current_file_name, false)) - { - old_file_name = current_file_name; - } - if(old_file_name != "") - { - dw_file_name = pathname + old_file_name; - res=stat(dw_file_name.c_str(), &dw_stat); - isLeopard = true; - } - } - - if (!res) - { - std::ifstream fp(dw_file_name.c_str()); - std::stringstream str; - if(!fp.is_open()) return; - str << fp.rdbuf(); - mBuf = str.str(); - - if(!isLeopard) - { - // Crash logs consist of a number of entries, one per crash. - // Each entry is preceeded by "**********" on a line by itself. - // We want only the most recent (i.e. last) one. - const char *sep = "**********"; - const char *start = mBuf.c_str(); - const char *cur = start; - const char *temp = strstr(cur, sep); - - while(temp != NULL) - { - // Skip past the marker we just found - cur = temp + strlen(sep); /* Flawfinder: ignore */ - - // and try to find another - temp = strstr(cur, sep); - } - - // If there's more than one entry in the log file, strip all but the last one. - if(cur != start) - { - mBuf.erase(0, cur - start); - } - } - mCrashInfo["CrashLog"] = mBuf; - } - else - { - llwarns << "Couldn't find any CrashReporter files..." << llendl; - } - } - } } bool LLCrashLoggerMac::mainLoop() diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp index 033c4ba2f3..e6d2ad3edc 100644 --- a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -544,8 +544,12 @@ MediaPluginGStreamer010::pause() { DEBUGMSG("pausing media..."); // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); - return true; + if (mDoneInit && mPlaybin) + { + llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); + return true; + } + return false; } bool @@ -553,8 +557,12 @@ MediaPluginGStreamer010::stop() { DEBUGMSG("stopping media..."); // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_READY); - return true; + if (mDoneInit && mPlaybin) + { + llgst_element_set_state(mPlaybin, GST_STATE_READY); + return true; + } + return false; } bool @@ -564,8 +572,12 @@ MediaPluginGStreamer010::play(double rate) DEBUGMSG("playing media... rate=%f", rate); // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); - return true; + if (mDoneInit && mPlaybin) + { + llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); + return true; + } + return false; } bool @@ -608,7 +620,7 @@ bool MediaPluginGStreamer010::getTimePos(double &sec_out) { bool got_position = false; - if (mPlaybin) + if (mDoneInit && mPlaybin) { gint64 pos; GstFormat timefmt = GST_FORMAT_TIME; @@ -688,6 +700,7 @@ MediaPluginGStreamer010::load() this); llgst_object_unref (bus); +#if 0 // not quite stable/correct yet // get a visualizer element (bonus feature!) char* vis_name = getenv("LL_GST_VIS_NAME"); if (!vis_name || @@ -714,6 +727,7 @@ MediaPluginGStreamer010::load() } } } +#endif if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { // instantiate a custom video sink diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d2ae81180b..e774d12883 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1084,7 +1084,6 @@ set(viewer_HEADER_FILES llwearabletype.h llweb.h llwind.h - llwindebug.h llwlanimator.h llwldaycycle.h llwlparammanager.h @@ -1158,12 +1157,10 @@ endif (LINUX) if (WINDOWS) list(APPEND viewer_SOURCE_FILES llappviewerwin32.cpp - llwindebug.cpp ) list(APPEND viewer_HEADER_FILES llappviewerwin32.h - llwindebug.h ) # precompiled header configuration @@ -1722,6 +1719,29 @@ if (LINUX) add_dependencies(package linux-updater-target) check_message_template(package) endif (NOT INSTALL) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --arch=${ARCH} + --actions=copy + --artwork=${ARTWORK_DIR} + --build=${CMAKE_CURRENT_BINARY_DIR} + --buildtype=${CMAKE_BUILD_TYPE} + --configuration=${CMAKE_CFG_INTDIR} + --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged + --grid=${GRID} + --source=${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ${COPY_INPUT_DEPENDENCIES} + COMMENT "Performing viewer_manifest copy" + ) + + add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched) + add_dependencies(copy_l_viewer_manifest "${VIEWER_BINARY_NAME}" linux-crash-logger-target linux-updater-target) endif (LINUX) if (DARWIN) @@ -1756,12 +1776,11 @@ if (DARWIN) DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit mac-updater mac-crash-logger) if (PACKAGE) add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME}) check_message_template(package) - add_dependencies(package mac-updater mac-crash-logger) add_custom_command( TARGET package POST_BUILD @@ -1809,6 +1828,45 @@ if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) +if (PACKAGE) + if (WINDOWS) + set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-windows.tar.bz2") + set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe") + set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") + set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest) + endif (WINDOWS) + if (DARWIN) + set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-darwin.tar.bz2") + set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin") + set(VIEWER_LIB_GLOB "*.dylib") + endif (DARWIN) + if (LINUX) + set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/packaged") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-linux.tar.bz2") + set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin") + set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") + set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) + endif (LINUX) + + add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" + COMMAND "${PYTHON_EXECUTABLE}" + ARGS + "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" + "${VIEWER_DIST_DIR}" + "${VIEWER_EXE_GLOBS}" + "${VIEWER_LIB_GLOB}" + "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" + "${VIEWER_SYMBOL_FILE}" + DEPENDS generate_breakpad_symbols.py + VERBATIM + ) + add_custom_target(generate_breakpad_symbols ALL DEPENDS "${VIEWER_SYMBOL_FILE}") + add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") + add_dependencies(package generate_breakpad_symbols) +endif (PACKAGE) + if (LL_TESTS) # To add a viewer unit test, just add the test .cpp file below # This creates a separate test project per file listed. diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 4831dc7273..fc531f93d4 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -2,6 +2,6 @@ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 2.0.2.0"; -CFBundleGetInfoString = "Second Life version 2.0.2.0, Copyright 2004-2009 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 2.1.0.0"; +CFBundleGetInfoString = "Second Life version 2.1.0.0, Copyright 2004-2009 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index fa2adac10c..97e24a0bd5 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -60,7 +60,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>2.0.2.0</string> + <string>2.1.0.0</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index df9393c316..50adf56245 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1,6 +1,17 @@ <?xml version="1.0" ?> <llsd> <map> + <key>CrashHostUrl</key> + <map> + <key>Comment</key> + <string>A URL pointing to a crash report handler; overrides cluster negotiation to locate crash handler.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string /> + </map> <key>AFKTimeout</key> <map> <key>Comment</key> @@ -11588,5 +11599,16 @@ <key>Value</key> <integer>180</integer> </map> + <key>HeightUnits</key> + <map> + <key>Comment</key> + <string>Determines which metric units are used: 1(TRUE) for meter and 0(FALSE) for foot.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> </map> </llsd> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index d4000e9253..dc76a4e518 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -1,26 +1,26 @@ <llsd> <map> - <key>BusyModeResponse</key> + <key>BusyResponseChanged</key> <map> <key>Comment</key> - <string>Auto response to instant messages while in busy mode.</string> + <string>Does user's busy mode message differ from default?</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>String</string> + <string>Boolean</string> <key>Value</key> - <string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string> + <integer>0</integer> </map> - <key>BusyModeResponse2</key> + <key>BusyModeResponse</key> <map> <key>Comment</key> - <string>Auto response to instant messages while in busy mode, clean (unencoded) version of BusyModeResponse</string> + <string>Auto response to instant messages while in busy mode.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>String</string> <key>Value</key> - <string>|TOKEN COPY BusyModeResponse|</string> + <string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string> </map> <key>InstantMessageLogPath</key> <map> diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py new file mode 100644 index 0000000000..1f42004bb7 --- /dev/null +++ b/indra/newview/generate_breakpad_symbols.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +# @file generate_breakpad_symbols.py +# @author Brad Kittenbrink <brad@lindenlab.com> +# @brief Simple tool for generating google_breakpad symbol information +# for the crash reporter. +# +# $LicenseInfo:firstyear=2010&license=viewergpl$ +# +# Copyright (c) 2010-2010, Linden Research, Inc. +# +# Second Life Viewer Source Code +# The source code in this file ("Source Code") is provided by Linden Lab +# to you under the terms of the GNU General Public License, version 2.0 +# ("GPL"), unless you have obtained a separate licensing agreement +# ("Other License"), formally executed by you and Linden Lab. Terms of +# the GPL can be found in doc/GPL-license.txt in this distribution, or +# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +# +# There are special exceptions to the terms and conditions of the GPL as +# it is applied to this Source Code. View the full text of the exception +# in the file doc/FLOSS-exception.txt in this software distribution, or +# online at +# http://secondlifegrid.net/programs/open_source/licensing/flossexception +# +# By copying, modifying or distributing this software, you acknowledge +# that you have read and understood your obligations described above, +# and agree to abide by those obligations. +# +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + + +import collections +import fnmatch +import itertools +import operator +import os +import sys +import shlex +import subprocess +import tarfile +import StringIO + +def usage(): + print >>sys.stderr, "usage: %s viewer_dir viewer_exes libs_suffix dump_syms_tool viewer_symbol_file" % sys.argv[0] + +class MissingModuleError(Exception): + def __init__(self, modules): + Exception.__init__(self, "Failed to find required modules: %r" % modules) + self.modules = modules + +def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): + print "generate_breakpad_symbols run with args: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) + + # split up list of viewer_exes + # "'Second Life' SLPlugin" becomes ['Second Life', 'SLPlugin'] + viewer_exes = shlex.split(viewer_exes) + + found_required = dict([(module, False) for module in viewer_exes]) + + def matches(f): + if f in viewer_exes: + found_required[f] = True + return True + return fnmatch.fnmatch(f, libs_suffix) + + def list_files(): + for (dirname, subdirs, filenames) in os.walk(viewer_dir): + #print "scanning '%s' for modules..." % dirname + for f in itertools.ifilter(matches, filenames): + yield os.path.join(dirname, f) + + def dump_module(m): + print "dumping module '%s' with '%s'..." % (m, dump_syms_tool) + child = subprocess.Popen([dump_syms_tool, m] , stdout=subprocess.PIPE) + out, err = child.communicate() + return (m,child.returncode, out, err) + + out = tarfile.open(viewer_symbol_file, 'w:bz2') + + for (filename,status,symbols,err) in itertools.imap(dump_module, list_files()): + if status == 0: + module_line = symbols[:symbols.index('\n')] + module_line = module_line.split() + hash_id = module_line[3] + module = ' '.join(module_line[4:]) + if sys.platform in ['win32', 'cygwin']: + mod_name = module[:module.rindex('.pdb')] + else: + mod_name = module + symbolfile = StringIO.StringIO(symbols) + info = tarfile.TarInfo("%(module)s/%(hash_id)s/%(mod_name)s.sym" % dict(module=module, hash_id=hash_id, mod_name=mod_name)) + info.size = symbolfile.len + out.addfile(info, symbolfile) + else: + print >>sys.stderr, "warning: failed to dump symbols for '%s': %s" % (filename, err) + + out.close() + + missing_modules = [m for (m,_) in + itertools.ifilter(lambda (k,v): not v, found_required.iteritems()) + ] + if missing_modules: + print >> sys.stderr, "failed to generate %s" % viewer_symbol_file + os.remove(viewer_symbol_file) + raise MissingModuleError(missing_modules) + + symbols = tarfile.open(viewer_symbol_file, 'r:bz2') + tarfile_members = symbols.getnames() + symbols.close() + + for required_module in viewer_exes: + def match_module_basename(m): + return os.path.splitext(required_module)[0].lower() \ + == os.path.splitext(os.path.basename(m))[0].lower() + # there must be at least one .sym file in tarfile_members that matches + # each required module (ignoring file extensions) + if not reduce(operator.or_, itertools.imap(match_module_basename, tarfile_members)): + print >> sys.stderr, "failed to find required %s in generated %s" \ + % (required_module, viewer_symbol_file) + os.remove(viewer_symbol_file) + raise MissingModuleError([required_module]) + + print "successfully generated %s including required modules '%s'" % (viewer_symbol_file, viewer_exes) + + return 0 + +if __name__ == "__main__": + if len(sys.argv) != 6: + usage() + sys.exit(1) + sys.exit(main(*sys.argv[1:])) + diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 39b51189d4..e7fbf0120e 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -2314,12 +2314,6 @@ void LLAgentCamera::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL came startCameraAnimation(); } - // Remove any pitch from the avatar - //LLVector3 at = gAgent.getFrameAgent().getAtAxis(); - //at.mV[VZ] = 0.f; - //at.normalize(); - //gAgent.resetAxes(at); - if (mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR) { updateLastCamera(); @@ -2340,9 +2334,11 @@ void LLAgentCamera::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL came if (isAgentAvatarValid()) { if(avatar_animate) - { - // Remove any pitch from the avatar - LLVector3 at = gAgent.getFrameAgent().getAtAxis(); + { + // slamming the avatar's axis to the camera so that when the rotation + // completes it correctly points to the front of the avatar + // Remove any pitch or rotation from the avatar + LLVector3 at = LLViewerCamera::getInstance()->getAtAxis(); at.mV[VZ] = 0.f; at.normalize(); gAgent.resetAxes(at); @@ -2362,6 +2358,10 @@ void LLAgentCamera::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL came mAnimationDuration = gSavedSettings.getF32("ZoomTime"); } } + + // this is what sets the avatar as the mFocusTargetGlobal + setFocusGlobal(LLVector3d::zero); + gAgentAvatarp->updateMeshTextures(); } else diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index acf43dda1e..342f9a5d80 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2006,6 +2006,8 @@ bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool clos // static void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, const LLUUID& parent_id) { + if (type == LLWearableType::WT_INVALID || type == LLWearableType::WT_NONE) return; + LLWearable* wearable = LLWearableList::instance().createNewWearable(type); LLAssetType::EType asset_type = wearable->getAssetType(); LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 12d2752180..3691d731ed 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -965,18 +965,10 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id) return false; } - // Check if the folder contains worn items. - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLFindWorn filter_worn; - gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_worn); - if (!items.empty()) - { - return false; - } - // Check for the folder's non-removable descendants. LLFindNonRemovableObjects filter_non_removable; + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; LLInventoryModel::item_array_t::const_iterator it; gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_non_removable); if (!cats.empty() || !items.empty()) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6978cdf672..64b66cb990 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -106,8 +106,8 @@ // Third party library includes #include <boost/bind.hpp> + #if LL_WINDOWS - #include "llwindebug.h" # include <share.h> // For _SH_DENYWR in initMarkerFile #else # include <sys/file.h> // For initMarkerFile support @@ -334,10 +334,6 @@ const char *VFS_INDEX_FILE_BASE = "index.db2.x."; static std::string gWindowTitle; -std::string gLoginPage; -std::vector<std::string> gLoginURIs; -static std::string gHelperURI; - LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ; void idle_afk_check() @@ -609,6 +605,11 @@ bool LLAppViewer::init() if (!initConfiguration()) return false; + // write Google Breakpad minidump files to our log directory + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + logdir += gDirUtilp->getDirDelimiter(); + setMiniDumpDir(logdir); + // Although initLogging() is the right place to mess with // setFatalFunction(), we can't query gSavedSettings until after // initConfiguration(). @@ -1262,6 +1263,14 @@ bool LLAppViewer::cleanup() // workaround for DEV-35406 crash on shutdown LLEventPumps::instance().reset(); + // remove any old breakpad minidump files from the log directory + if (! isError()) + { + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + logdir += gDirUtilp->getDirDelimiter(); + gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); + } + // *TODO - generalize this and move DSO wrangling to a helper class -brad std::set<struct apr_dso_handle_t *>::const_iterator i; for(i = mPlugins.begin(); i != mPlugins.end(); ++i) @@ -2332,17 +2341,7 @@ void LLAppViewer::checkForCrash(void) { #if LL_SEND_CRASH_REPORTS - //*NOTE:Mani The current state of the crash handler has the MacOSX - // sending all crash reports as freezes, in order to let - // the MacOSX CrashRepoter generate stacks before spawning the - // SL crash logger. - // The Linux and Windows clients generate their own stacks and - // spawn the SL crash logger immediately. This may change in the future. -#if LL_DARWIN - if(gLastExecEvent != LAST_EXEC_NORMAL) -#else if (gLastExecEvent == LAST_EXEC_FROZE) -#endif { llinfos << "Last execution froze, requesting to send crash report." << llendl; // @@ -2553,6 +2552,15 @@ void LLAppViewer::writeSystemInfo() // If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze, // then the value of "CrashNotHandled" will be set to true. gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true; + + // Insert crash host url (url to post crash log to) if configured. This insures + // that the crash report will go to the proper location in the case of a + // prior freeze. + std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl"); + if(crashHostUrl != "") + { + gDebugInfo["CrashHostUrl"] = crashHostUrl; + } // Dump some debugging info LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME") @@ -2574,13 +2582,6 @@ void LLAppViewer::writeSystemInfo() writeDebugInfo(); // Save out debug_info.log early, in case of crash. } -void LLAppViewer::handleSyncViewerCrash() -{ - LLAppViewer* pApp = LLAppViewer::instance(); - // Call to pure virtual, handled by platform specific llappviewer instance. - pApp->handleSyncCrashTrace(); -} - void LLAppViewer::handleViewerCrash() { llinfos << "Handle viewer crash entry." << llendl; @@ -2604,9 +2605,13 @@ void LLAppViewer::handleViewerCrash() return; } pApp->mReportedCrash = TRUE; - - // Make sure the watchdog gets turned off... -// pApp->destroyMainloopTimeout(); // SJB: Bah. This causes the crash handler to hang, not sure why. + + // Insert crash host url (url to post crash log to) if configured. + std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl"); + if(crashHostUrl != "") + { + gDebugInfo["CrashHostUrl"] = crashHostUrl; + } //We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version //to check against no matter what @@ -2638,6 +2643,12 @@ void LLAppViewer::handleViewerCrash() gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); + char *minidump_file = pApp->getMiniDumpFilename(); + if(minidump_file && minidump_file[0] != 0) + { + gDebugInfo["MinidumpPath"] = minidump_file; + } + if(gLogoutInProgress) { gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH; @@ -2715,10 +2726,6 @@ void LLAppViewer::handleViewerCrash() LLError::logToFile(""); -// On Mac, we send the report on the next run, since we need macs crash report -// for a stack trace, so we have to let it the app fail. -#if !LL_DARWIN - // Remove the marker file, since otherwise we'll spawn a process that'll keep it locked if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH) { @@ -2731,8 +2738,6 @@ void LLAppViewer::handleViewerCrash() // Call to pure virtual, handled by platform specific llappviewer instance. pApp->handleCrashReporting(); - -#endif //!LL_DARWIN return; } @@ -3376,13 +3381,6 @@ void LLAppViewer::badNetworkHandler() mPurgeOnExit = TRUE; -#if LL_WINDOWS - // Generates the minidump. - LLWinDebug::generateCrashStacks(NULL); -#endif - LLAppViewer::handleSyncViewerCrash(); - LLAppViewer::handleViewerCrash(); - std::ostringstream message; message << "The viewer has detected mangled network data indicative\n" @@ -3395,6 +3393,8 @@ void LLAppViewer::badNetworkHandler() "If the problem continues, see the Tech Support FAQ at: \n" "www.secondlife.com/support"; forceDisconnect(message.str()); + + LLApp::instance()->writeMiniDump(); } // This routine may get called more than once during the shutdown process. diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 5acd6e11c4..0b862a92a1 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -92,9 +92,7 @@ public: virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism. // return false if the error trap needed restoration. virtual void handleCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report? - virtual void handleSyncCrashTrace() = 0; // any low-level crash-prep that has to happen in the context of the crashing thread before the crash report is delivered. static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon. - static void handleSyncViewerCrash(); // Hey! The viewer crashed. Do this right NOW in the context of the crashing thread. void checkForCrash(); // Thread accessors diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 78b0f7ba83..78afdc8995 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -46,23 +46,6 @@ #include <exception> -#if LL_LINUX -# include <dlfcn.h> // RTLD_LAZY -# include <execinfo.h> // backtrace - glibc only -#elif LL_SOLARIS -# include <sys/types.h> -# include <unistd.h> -# include <fcntl.h> -# include <ucontext.h> -#endif - -#ifdef LL_ELFBIN -# ifdef __GNUC__ -# include <cxxabi.h> // for symbol demangling -# endif -# include "ELFIO/ELFIO.h" // for better backtraces -#endif - #if LL_DBUS_ENABLED # include "llappviewerlinux_api_dbus.h" @@ -86,7 +69,6 @@ static void exceptionTerminateHandler() // reinstall default terminate() handler in case we re-terminate. if (gOldTerminateHandler) std::set_terminate(gOldTerminateHandler); // treat this like a regular viewer crash, with nice stacktrace etc. - LLAppViewer::handleSyncViewerCrash(); LLAppViewer::handleViewerCrash(); // we've probably been killed-off before now, but... gOldTerminateHandler(); // call old terminate() handler @@ -109,7 +91,6 @@ int main( int argc, char **argv ) gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler); // install crash handlers viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); - viewer_app_ptr->setSyncErrorHandler(LLAppViewer::handleSyncViewerCrash); bool ok = viewer_app_ptr->init(); if(!ok) @@ -138,201 +119,6 @@ int main( int argc, char **argv ) return 0; } -#ifdef LL_SOLARIS -static inline BOOL do_basic_glibc_backtrace() -{ - BOOL success = FALSE; - - std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); - llinfos << "Opening stack trace file " << strace_filename << llendl; - LLFILE* StraceFile = LLFile::fopen(strace_filename, "w"); - if (!StraceFile) - { - llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; - StraceFile = stderr; - } - - printstack(fileno(StraceFile)); - - if (StraceFile != stderr) - fclose(StraceFile); - - return success; -} -#else -#define MAX_STACK_TRACE_DEPTH 40 -// This uses glibc's basic built-in stack-trace functions for a not very -// amazing backtrace. -static inline BOOL do_basic_glibc_backtrace() -{ - void *stackarray[MAX_STACK_TRACE_DEPTH]; - size_t size; - char **strings; - size_t i; - BOOL success = FALSE; - - size = backtrace(stackarray, MAX_STACK_TRACE_DEPTH); - strings = backtrace_symbols(stackarray, size); - - std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); - llinfos << "Opening stack trace file " << strace_filename << llendl; - LLFILE* StraceFile = LLFile::fopen(strace_filename, "w"); // Flawfinder: ignore - if (!StraceFile) - { - llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; - StraceFile = stderr; - } - - if (size) - { - for (i = 0; i < size; i++) - { - // the format of the StraceFile is very specific, to allow (kludgy) machine-parsing - fprintf(StraceFile, "%-3lu ", (unsigned long)i); - fprintf(StraceFile, "%-32s\t", "unknown"); - fprintf(StraceFile, "%p ", stackarray[i]); - fprintf(StraceFile, "%s\n", strings[i]); - } - - success = TRUE; - } - - if (StraceFile != stderr) - fclose(StraceFile); - - free (strings); - return success; -} - -#if LL_ELFBIN -// This uses glibc's basic built-in stack-trace functions together with -// ELFIO's ability to parse the .symtab ELF section for better symbol -// extraction without exporting symbols (which'd cause subtle, fatal bugs). -static inline BOOL do_elfio_glibc_backtrace() -{ - void *stackarray[MAX_STACK_TRACE_DEPTH]; - size_t btsize; - char **strings; - BOOL success = FALSE; - - std::string appfilename = gDirUtilp->getExecutablePathAndName(); - - std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); - llinfos << "Opening stack trace file " << strace_filename << llendl; - LLFILE* StraceFile = LLFile::fopen(strace_filename, "w"); // Flawfinder: ignore - if (!StraceFile) - { - llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; - StraceFile = stderr; - } - - // get backtrace address list and basic symbol info - btsize = backtrace(stackarray, MAX_STACK_TRACE_DEPTH); - strings = backtrace_symbols(stackarray, btsize); - - // create ELF reader for our app binary - IELFI* pReader; - const IELFISection* pSec = NULL; - IELFISymbolTable* pSymTbl = 0; - if (ERR_ELFIO_NO_ERROR != ELFIO::GetInstance()->CreateELFI(&pReader) || - ERR_ELFIO_NO_ERROR != pReader->Load(appfilename.c_str()) || - // find symbol table, create reader-object - NULL == (pSec = pReader->GetSection( ".symtab" )) || - ERR_ELFIO_NO_ERROR != pReader->CreateSectionReader(IELFI::ELFI_SYMBOL, pSec, (void**)&pSymTbl) ) - { - // Failed to open our binary and read its symbol table somehow - llinfos << "Could not initialize ELF symbol reading - doing basic backtrace." << llendl; - if (StraceFile != stderr) - fclose(StraceFile); - // note that we may be leaking some of the above ELFIO - // objects now, but it's expected that we'll be dead soon - // and we want to tread delicately until we get *some* kind - // of useful backtrace. - return do_basic_glibc_backtrace(); - } - - // iterate over trace and symtab, looking for plausible symbols - std::string name; - Elf32_Addr value; - Elf32_Word ssize; - unsigned char bind; - unsigned char type; - Elf32_Half section; - int nSymNo = pSymTbl->GetSymbolNum(); - size_t btpos; - for (btpos = 0; btpos < btsize; ++btpos) - { - // the format of the StraceFile is very specific, to allow (kludgy) machine-parsing - fprintf(StraceFile, "%-3ld ", (long)btpos); - int symidx; - for (symidx = 0; symidx < nSymNo; ++symidx) - { - if (ERR_ELFIO_NO_ERROR == - pSymTbl->GetSymbol(symidx, name, value, ssize, - bind, type, section)) - { - // check if trace address within symbol range - if (uintptr_t(stackarray[btpos]) >= value && - uintptr_t(stackarray[btpos]) < value+ssize) - { - // symbol is inside viewer - fprintf(StraceFile, "%-32s\t", "com.secondlife.indra.viewer"); - fprintf(StraceFile, "%p ", stackarray[btpos]); - - char *demangled_str = NULL; - int demangle_result = 1; - demangled_str = - abi::__cxa_demangle - (name.c_str(), NULL, NULL, - &demangle_result); - if (0 == demangle_result && - NULL != demangled_str) { - fprintf(StraceFile, - "%s", demangled_str); - free(demangled_str); - } - else // failed demangle; print it raw - { - fprintf(StraceFile, - "%s", name.c_str()); - } - // print offset from symbol start - fprintf(StraceFile, - " + %lu\n", - uintptr_t(stackarray[btpos]) - - value); - goto got_sym; // early escape - } - } - } - // Fallback: - // Didn't find a suitable symbol in the binary - it's probably - // a symbol in a DSO; use glibc's idea of what it should be. - fprintf(StraceFile, "%-32s\t", "unknown"); - fprintf(StraceFile, "%p ", stackarray[btpos]); - fprintf(StraceFile, "%s\n", strings[btpos]); - got_sym:; - } - - if (StraceFile != stderr) - fclose(StraceFile); - - pSymTbl->Release(); - pSec->Release(); - pReader->Release(); - - free(strings); - - llinfos << "Finished generating stack trace." << llendl; - - success = TRUE; - return success; -} -#endif // LL_ELFBIN - -#endif // LL_SOLARIS - - LLAppViewerLinux::LLAppViewerLinux() { } @@ -541,16 +327,6 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url) } #endif // LL_DBUS_ENABLED -void LLAppViewerLinux::handleSyncCrashTrace() -{ - // This backtrace writes into stack_trace.log -# if LL_ELFBIN - do_elfio_glibc_backtrace(); // more useful backtrace -# else - do_basic_glibc_backtrace(); // only slightly useful backtrace -# endif // LL_ELFBIN -} - void LLAppViewerLinux::handleCrashReporting(bool reportFreeze) { std::string cmd =gDirUtilp->getExecutableDir(); @@ -686,6 +462,8 @@ bool LLAppViewerLinux::beingDebugged() bool LLAppViewerLinux::initLogging() { // Remove the last stack trace, if any + // This file is no longer created, since the move to Google Breakpad + // The code is left here to clean out any old state in the log dir std::string old_stack_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); LLFile::remove(old_stack_file); diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h index 230c0dc24b..b17380d4d8 100644 --- a/indra/newview/llappviewerlinux.h +++ b/indra/newview/llappviewerlinux.h @@ -68,7 +68,6 @@ protected: virtual bool restoreErrorTrap(); virtual void handleCrashReporting(bool reportFreeze); - virtual void handleSyncCrashTrace(); virtual bool initLogging(); virtual bool initParseCommandLine(LLCommandLineParser& clp); diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 0b5f18c330..1e66e55f3d 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -264,11 +264,6 @@ bool LLAppViewerMacOSX::restoreErrorTrap() return reset_count == 0; } -void LLAppViewerMacOSX::handleSyncCrashTrace() -{ - // do nothing -} - static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void* inUserData) @@ -384,38 +379,6 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) } } - - if(!reportFreeze) - { - _exit(1); - } - - // TODO from palmer: Find a better way to handle managing old crash logs - // when this is a separate imbedable module. Ideally just sort crash stack - // logs based on date, and grab the latest one as opposed to deleting them - // for thoughts on what the module would look like. - // See: https://wiki.lindenlab.com/wiki/Viewer_Crash_Reporter_Round_4 - - // Remove the crash stack log from previous executions. - // Since we've started logging a new instance of the app, we can assume - // The old crash stack is invalid for the next crash report. - char path[MAX_PATH]; - FSRef folder; - if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr) - { - // folder is an FSRef to ~/Library/Logs/ - if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr) - { - std::string pathname = std::string(path) + std::string("/CrashReporter/"); - std::string mask = "Second Life*"; - std::string file_name; - while(gDirUtilp->getNextFileInDir(pathname, mask, file_name, false)) - { - LLFile::remove(pathname + file_name); - } - } - } - } std::string LLAppViewerMacOSX::generateSerialNumber() diff --git a/indra/newview/llappviewermacosx.h b/indra/newview/llappviewermacosx.h index cbf7e6c209..3d7bb55556 100644 --- a/indra/newview/llappviewermacosx.h +++ b/indra/newview/llappviewermacosx.h @@ -55,7 +55,6 @@ public: protected: virtual bool restoreErrorTrap(); virtual void handleCrashReporting(bool reportFreeze); - virtual void handleSyncCrashTrace(); std::string generateSerialNumber(); virtual bool initParseCommandLine(LLCommandLineParser& clp); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 60a6d2f072..e3ef04d03d 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -57,8 +57,6 @@ #include "llweb.h" #include "llsecondlifeurls.h" -#include "llwindebug.h" - #include "llviewernetwork.h" #include "llmd5.h" #include "llfindlocale.h" @@ -81,51 +79,6 @@ extern "C" { const std::string LLAppViewerWin32::sWindowClass = "Second Life"; -LONG WINAPI viewer_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop) -{ - // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. - //OSMessageBox("Attach Debugger Now", "Error", OSMB_OK); - // *TODO: Translate the signals/exceptions into cross-platform stuff - // Windows implementation - _tprintf( _T("Entering Windows Exception Handler...\n") ); - llinfos << "Entering Windows Exception Handler..." << llendl; - - // Make sure the user sees something to indicate that the app crashed. - LONG retval; - - if (LLApp::isError()) - { - _tprintf( _T("Got another fatal signal while in the error handler, die now!\n") ); - llwarns << "Got another fatal signal while in the error handler, die now!" << llendl; - - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; - } - - // Generate a minidump if we can. - // Before we wake the error thread... - // Which will start the crash reporting. - LLWinDebug::generateCrashStacks(exception_infop); - - // Flag status to error, so thread_error starts its work - LLApp::setError(); - - // Block in the exception handler until the app has stopped - // This is pretty sketchy, but appears to work just fine - while (!LLApp::isStopped()) - { - ms_sleep(10); - } - - // - // At this point, we always want to exit the app. There's no graceful - // recovery for an unhandled exception. - // - // Just kill the process. - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; -} - // Create app mutex creates a unique global windows object. // If the object can be created it returns true, otherwise // it returns false. The false result can be used to determine @@ -191,8 +144,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, gIconResource = MAKEINTRESOURCE(IDI_LL_ICON); LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine); - - LLWinDebug::initExceptionHandler(viewer_windows_exception_handler); viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); @@ -405,12 +356,6 @@ bool LLAppViewerWin32::cleanup() bool LLAppViewerWin32::initLogging() { - // Remove the crash stack log from previous executions. - // Since we've started logging a new instance of the app, we can assume - // *NOTE: This should happen before the we send a 'previous instance froze' - // crash report, but it must happen after we initialize the DirUtil. - LLWinDebug::clearCrashStacks(); - return LLAppViewer::initLogging(); } @@ -529,13 +474,9 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp) } bool LLAppViewerWin32::restoreErrorTrap() -{ - return LLWinDebug::checkExceptionHandler(); -} - -void LLAppViewerWin32::handleSyncCrashTrace() -{ - // do nothing +{ + return true; + //return LLWinDebug::checkExceptionHandler(); } void LLAppViewerWin32::handleCrashReporting(bool reportFreeze) diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index 13454edeec..52dcc583a4 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -57,7 +57,6 @@ protected: virtual bool restoreErrorTrap(); virtual void handleCrashReporting(bool reportFreeze); - virtual void handleSyncCrashTrace(); virtual bool sendURLToOtherInstance(const std::string& url); diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 01d6c3a8d5..2dafe295fe 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -656,6 +656,8 @@ void LLAvatarActions::shareWithAvatars() LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE); picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable)); + picker->openFriendsTab(); + LLNotificationsUtil::add("ShareNotification"); } // static diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 0bd03571da..18c69b5130 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -243,7 +243,7 @@ public: gCacheName->get(mAvatarID, FALSE, boost::bind(&LLChatHistoryHeader::nameUpdatedCallback, this, _1, _2, _3, _4)); //*TODO overly defensive thing, source type should be maintained out there - if((chat.mFromID.isNull() && chat.mFromName.empty()) || chat.mFromName == SYSTEM_FROM) + if((chat.mFromID.isNull() && chat.mFromName.empty()) || chat.mFromName == SYSTEM_FROM && chat.mFromID.isNull()) { mSourceType = CHAT_SOURCE_SYSTEM; } @@ -667,7 +667,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // (don't let object names with hyperlinks override our objectim Url) LLStyle::Params link_params(style_params); link_params.color.control = "HTMLLinkColor"; - link_params.link_href = url; + link_params.link_href = LLURI::escape(url); mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, false, link_params); } diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 916d53da3c..611396b0e5 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -58,13 +58,19 @@ static const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR; class CofContextMenu : public LLListContextMenu { protected: - static void updateCreateWearableLabel(LLMenuGL* menu, const LLUUID& item_id) + CofContextMenu(LLCOFWearables* cof_wearables) + : mCOFWearables(cof_wearables) + { + llassert(mCOFWearables); + } + + void updateCreateWearableLabel(LLMenuGL* menu, const LLUUID& item_id) { LLMenuItemGL* menu_item = menu->getChild<LLMenuItemGL>("create_new"); + LLWearableType::EType w_type = getWearableType(item_id); // Hide the "Create new <WEARABLE_TYPE>" if it's irrelevant. - LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id); - if (!item || !item->isWearableType()) + if (w_type == LLWearableType::WT_NONE) { menu_item->setVisible(FALSE); return; @@ -72,25 +78,67 @@ protected: // Set proper label for the "Create new <WEARABLE_TYPE>" menu item. LLStringUtil::format_map_t args; - LLWearableType::EType w_type = item->getWearableType(); args["[WEARABLE_TYPE]"] = LLWearableType::getTypeDefaultNewName(w_type); std::string new_label = LLTrans::getString("CreateNewWearable", args); menu_item->setLabel(new_label); } - static void createNew(const LLUUID& item_id) + void createNew(const LLUUID& item_id) { - LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id); - if (!item || !item->isWearableType()) return; + LLAgentWearables::createWearable(getWearableType(item_id), true); + } + + // Get wearable type of the given item. + // + // There is a special case: so-called "dummy items" + // (i.e. the ones that are there just to indicate that you're not wearing + // any wearables of the corresponding type. They are currently grayed out + // and suffixed with "not worn"). + // Those items don't have an UUID, but they do have an associated wearable type. + // If the user has invoked context menu for such item, + // we ignore the passed item_id and retrieve wearable type from the item. + LLWearableType::EType getWearableType(const LLUUID& item_id) + { + if (!isDummyItem(item_id)) + { + LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id); + if (item && item->isWearableType()) + { + return item->getWearableType(); + } + } + else if (mCOFWearables) // dummy item selected + { + LLPanelDummyClothingListItem* item; + + item = dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem()); + if (item) + { + return item->getWearableType(); + } + } + + return LLWearableType::WT_NONE; + } - LLAgentWearables::createWearable(item->getWearableType(), true); + static bool isDummyItem(const LLUUID& item_id) + { + return item_id.isNull(); } + + LLCOFWearables* mCOFWearables; }; ////////////////////////////////////////////////////////////////////////// -class CofAttachmentContextMenu : public LLListContextMenu +class CofAttachmentContextMenu : public CofContextMenu { +public: + CofAttachmentContextMenu(LLCOFWearables* cof_wearables) + : CofContextMenu(cof_wearables) + { + } + protected: /*virtual*/ LLContextMenu* createMenu() @@ -108,8 +156,13 @@ protected: class CofClothingContextMenu : public CofContextMenu { -protected: +public: + CofClothingContextMenu(LLCOFWearables* cof_wearables) + : CofContextMenu(cof_wearables) + { + } +protected: /*virtual*/ LLContextMenu* createMenu() { LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -121,7 +174,7 @@ protected: registrar.add("Clothing.MoveUp", boost::bind(moveWearable, selected_id, false)); registrar.add("Clothing.MoveDown", boost::bind(moveWearable, selected_id, true)); registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id)); - registrar.add("Clothing.Create", boost::bind(createNew, selected_id)); + registrar.add("Clothing.Create", boost::bind(&CofClothingContextMenu::createNew, this, selected_id)); enable_registrar.add("Clothing.OnEnable", boost::bind(&CofClothingContextMenu::onEnable, this, _2)); @@ -171,8 +224,13 @@ protected: class CofBodyPartContextMenu : public CofContextMenu { -protected: +public: + CofBodyPartContextMenu(LLCOFWearables* cof_wearables) + : CofContextMenu(cof_wearables) + { + } +protected: /*virtual*/ LLContextMenu* createMenu() { LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -184,7 +242,7 @@ protected: LLPanelOutfitEdit* panel_oe = dynamic_cast<LLPanelOutfitEdit*>(LLSideTray::getInstance()->getPanel("panel_outfit_edit")); registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked, panel_oe, selected_id)); registrar.add("BodyPart.Edit", boost::bind(LLAgentWearables::editWearable, selected_id)); - registrar.add("BodyPart.Create", boost::bind(createNew, selected_id)); + registrar.add("BodyPart.Create", boost::bind(&CofBodyPartContextMenu::createNew, this, selected_id)); enable_registrar.add("BodyPart.OnEnable", boost::bind(&CofBodyPartContextMenu::onEnable, this, _2)); @@ -219,9 +277,9 @@ LLCOFWearables::LLCOFWearables() : LLPanel(), mBodyParts(NULL), mLastSelectedList(NULL) { - mClothingMenu = new CofClothingContextMenu(); - mAttachmentMenu = new CofAttachmentContextMenu(); - mBodyPartMenu = new CofBodyPartContextMenu(); + mClothingMenu = new CofClothingContextMenu(this); + mAttachmentMenu = new CofAttachmentContextMenu(this); + mBodyPartMenu = new CofBodyPartContextMenu(this); }; LLCOFWearables::~LLCOFWearables() diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 96364f9418..8f6816b845 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -446,6 +446,19 @@ BOOL LLFloaterAvatarPicker::handleDragAndDrop(S32 x, S32 y, MASK mask, return TRUE; } + +void LLFloaterAvatarPicker::openFriendsTab() +{ + LLTabContainer* tab_container = getChild<LLTabContainer>("ResidentChooserTabs"); + if (tab_container == NULL) + { + llassert(tab_container != NULL); + return; + } + + tab_container->selectTabByName("FriendsPanel"); +} + // static void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void**) { diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index e69b814f9f..0af72e85a0 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -66,6 +66,8 @@ public: void *cargo_data, EAcceptance *accept, std::string& tooltip_msg); + void openFriendsTab(); + private: void editKeystroke(class LLLineEditor* caller, void* user_data); diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp index 46b3695511..d359856443 100644 --- a/indra/newview/llfloaterbuy.cpp +++ b/indra/newview/llfloaterbuy.cpp @@ -254,7 +254,6 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj, std::string icon_name = LLInventoryIcon::getIconName(inv_item->getType(), inv_item->getInventoryType(), - inv_item->getIsLinkType(), inv_item->getFlags(), item_is_multi); row["columns"][0]["column"] = "icon"; diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index c35653178a..9bde3b1dac 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -223,7 +223,6 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, std::string icon_name = LLInventoryIcon::getIconName(inv_item->getType(), inv_item->getInventoryType(), - inv_item->getIsLinkType(), inv_item->getFlags(), item_is_multi); row["columns"][0]["column"] = "icon"; diff --git a/indra/newview/llfloaterbuycurrencyhtml.cpp b/indra/newview/llfloaterbuycurrencyhtml.cpp index 5815df36d1..7f41a64064 100644 --- a/indra/newview/llfloaterbuycurrencyhtml.cpp +++ b/indra/newview/llfloaterbuycurrencyhtml.cpp @@ -87,6 +87,9 @@ void LLFloaterBuyCurrencyHTML::navigateToFinalURL() replace[ "[MSG]" ] = LLURI::escape( mMessage ); LLStringUtil::format( buy_currency_url, replace ); + // write final URL to debug console + llinfos << "Buy currency HTML prased URL is " << buy_currency_url << llendl; + // kick off the navigation mBrowser->navigateTo( buy_currency_url ); } @@ -98,6 +101,9 @@ void LLFloaterBuyCurrencyHTML::handleMediaEvent( LLPluginClassMedia* self, EMedi // placeholder for now - just in case we want to catch media events if ( LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE == event ) { + // update currency after we complete a navigation since there are many ways + // this can result in a different L$ balance + LLStatusBar::sendMoneyBalanceRequest(); }; } @@ -105,6 +111,9 @@ void LLFloaterBuyCurrencyHTML::handleMediaEvent( LLPluginClassMedia* self, EMedi // void LLFloaterBuyCurrencyHTML::onClose( bool app_quitting ) { + // update L$ balanace one more time + LLStatusBar::sendMoneyBalanceRequest(); + destroy(); } diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index ca346138fb..d6effb2b21 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -49,6 +49,9 @@ static LLDefaultChildRegistry::Register<LLPanelCameraItem> r("panel_camera_item"); +const F32 NUDGE_TIME = 0.25f; // in seconds +const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed + // Constants const F32 CAMERA_BUTTON_DELAY = 0.0f; @@ -75,6 +78,7 @@ protected: void onZoomPlusHeldDown(); void onZoomMinusHeldDown(); void onSliderValueChanged(); + F32 getOrbitRate(F32 time); private: LLButton* mPlusBtn; @@ -155,8 +159,8 @@ LLPanelCameraZoom::LLPanelCameraZoom() mMinusBtn( NULL ), mSlider( NULL ) { - mCommitCallbackRegistrar.add("Zoom.minus", boost::bind(&LLPanelCameraZoom::onZoomPlusHeldDown, this)); - mCommitCallbackRegistrar.add("Zoom.plus", boost::bind(&LLPanelCameraZoom::onZoomMinusHeldDown, this)); + mCommitCallbackRegistrar.add("Zoom.minus", boost::bind(&LLPanelCameraZoom::onZoomMinusHeldDown, this)); + mCommitCallbackRegistrar.add("Zoom.plus", boost::bind(&LLPanelCameraZoom::onZoomPlusHeldDown, this)); mCommitCallbackRegistrar.add("Slider.value_changed", boost::bind(&LLPanelCameraZoom::onSliderValueChanged, this)); } @@ -179,9 +183,9 @@ void LLPanelCameraZoom::onZoomPlusHeldDown() F32 val = mSlider->getValueF32(); F32 inc = mSlider->getIncrement(); mSlider->setValue(val - inc); - // commit only if value changed - if (val != mSlider->getValueF32()) - mSlider->onCommit(); + F32 time = mPlusBtn->getHeldDownTime(); + gAgentCamera.unlockView(); + gAgentCamera.setOrbitInKey(getOrbitRate(time)); } void LLPanelCameraZoom::onZoomMinusHeldDown() @@ -189,9 +193,22 @@ void LLPanelCameraZoom::onZoomMinusHeldDown() F32 val = mSlider->getValueF32(); F32 inc = mSlider->getIncrement(); mSlider->setValue(val + inc); - // commit only if value changed - if (val != mSlider->getValueF32()) - mSlider->onCommit(); + F32 time = mMinusBtn->getHeldDownTime(); + gAgentCamera.unlockView(); + gAgentCamera.setOrbitOutKey(getOrbitRate(time)); +} + +F32 LLPanelCameraZoom::getOrbitRate(F32 time) +{ + if( time < NUDGE_TIME ) + { + F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME; + return rate; + } + else + { + return 1; + } } void LLPanelCameraZoom::onSliderValueChanged() diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h index 8fa7a53996..564e38d02d 100644 --- a/indra/newview/llfloatercamera.h +++ b/indra/newview/llfloatercamera.h @@ -39,7 +39,6 @@ #include "llflatlistview.h" class LLJoystickCameraRotate; -class LLJoystickCameraZoom; class LLJoystickCameraTrack; class LLFloaterReg; class LLPanelCameraZoom; diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp index c259659083..e74bfae026 100644 --- a/indra/newview/llfloatermap.cpp +++ b/indra/newview/llfloatermap.cpp @@ -54,7 +54,10 @@ // Constants // const F32 MAP_MINOR_DIR_THRESHOLD = 0.08f; - +const S32 MAP_PADDING_LEFT = 0; +const S32 MAP_PADDING_TOP = 2; +const S32 MAP_PADDING_RIGHT = 2; +const S32 MAP_PADDING_BOTTOM = 0; // // Member functions // @@ -106,7 +109,8 @@ BOOL LLFloaterMap::postBuild() mPopupMenu->setItemEnabled ("Stop Tracking", false); } - stretchMiniMap(getRect().getWidth(),getRect().getHeight()); + stretchMiniMap(getRect().getWidth() - MAP_PADDING_LEFT - MAP_PADDING_RIGHT + ,getRect().getHeight() - MAP_PADDING_TOP - MAP_PADDING_BOTTOM); updateMinorDirections(); @@ -238,7 +242,7 @@ void LLFloaterMap::stretchMiniMap(S32 width,S32 height) if(mMap) { LLRect map_rect; - map_rect.setLeftTopAndSize( 0, getRect().getHeight(), width, height); + map_rect.setLeftTopAndSize( MAP_PADDING_LEFT, getRect().getHeight() - MAP_PADDING_TOP, width, height); mMap->reshape( width, height, 1); mMap->setRect(map_rect); } @@ -248,7 +252,8 @@ void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent) { LLFloater::reshape(width, height, called_from_parent); - stretchMiniMap(width, height); + stretchMiniMap(width - MAP_PADDING_LEFT - MAP_PADDING_RIGHT + ,height - MAP_PADDING_TOP - MAP_PADDING_BOTTOM); updateMinorDirections(); } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index a8da0c8b16..32ee9a073c 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -330,9 +330,28 @@ BOOL LLFloaterPreference::postBuild() std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""); childSetText("cache_location", cache_location); + // if floater is opened before login set default localized busy message + if (LLStartUp::getStartupState() < STATE_STARTED) + { + gSavedPerAccountSettings.setString("BusyModeResponse", LLTrans::getString("BusyModeResponseDefault")); + } + return TRUE; } +void LLFloaterPreference::onBusyResponseChanged() +{ + // set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise + if(LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString()) + { + gSavedPerAccountSettings.setBOOL("BusyResponseChanged", TRUE ); + } + else + { + gSavedPerAccountSettings.setBOOL("BusyResponseChanged", FALSE ); + } +} + LLFloaterPreference::~LLFloaterPreference() { // clean up user data @@ -487,6 +506,22 @@ void LLFloaterPreference::cancel() void LLFloaterPreference::onOpen(const LLSD& key) { + // this variable and if that follows it are used to properly handle busy mode response message + static bool initialized = FALSE; + // if user is logged in and we haven't initialized busy_response yet, do it + if (!initialized && LLStartUp::getStartupState() == STATE_STARTED) + { + // Special approach is used for busy response localization, because "BusyModeResponse" is + // in non-localizable xml, and also because it may be changed by user and in this case it shouldn't be localized. + // To keep track of whether busy response is default or changed by user additional setting BusyResponseChanged + // was added into per account settings. + + // initialization should happen once,so setting variable to TRUE + initialized = TRUE; + // this connection is needed to properly set "BusyResponseChanged" setting when user makes changes in + // busy response message. + gSavedPerAccountSettings.getControl("BusyModeResponse")->getSignal()->connect(boost::bind(&LLFloaterPreference::onBusyResponseChanged, this)); + } gAgent.sendAgentUserInfoRequest(); /////////////////////////// From LLPanelGeneral ////////////////////////// @@ -540,6 +575,16 @@ void LLFloaterPreference::onVertexShaderEnable() refreshEnabledGraphics(); } +//static +void LLFloaterPreference::initBusyResponse() + { + if (!gSavedPerAccountSettings.getBOOL("BusyResponseChanged")) + { + //LLTrans::getString("BusyModeResponseDefault") is used here for localization (EXT-5885) + gSavedPerAccountSettings.setString("BusyModeResponse", LLTrans::getString("BusyModeResponseDefault")); + } + } + void LLFloaterPreference::setHardwareDefaults() { LLFeatureManager::getInstance()->applyRecommendedSettings(); @@ -1045,18 +1090,6 @@ void LLFloaterPreference::onChangeQuality(const LLSD& data) refresh(); } -// static -// DEV-24146 - needs to be removed at a later date. jan-2009 -void LLFloaterPreference::cleanupBadSetting() -{ - if (gSavedPerAccountSettings.getString("BusyModeResponse2") == "|TOKEN COPY BusyModeResponse|") - { - llinfos << "cleaning old BusyModeResponse" << llendl; - //LLTrans::getString("BusyModeResponseDefault") is used here for localization (EXT-5885) - gSavedPerAccountSettings.setString("BusyModeResponse2", LLTrans::getString("BusyModeResponseDefault")); - } -} - void LLFloaterPreference::onClickSetKey() { LLVoiceSetKeyDialog* dialog = LLFloaterReg::showTypedInstance<LLVoiceSetKeyDialog>("voice_set_key", LLSD(), TRUE); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 71aa5d3189..b45e09db7d 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -80,6 +80,9 @@ public: // refresh all the graphics preferences menus static void refreshEnabledGraphics(); + // translate user's busy response message according to current locale if message is default, otherwise do nothing + static void initBusyResponse(); + protected: void onBtnOK(); void onBtnCancel(); @@ -87,6 +90,9 @@ protected: void onClickBrowserClearCache(); + // set value of "BusyResponseChanged" in account settings depending on whether busy response + // string differs from default after user changes. + void onBusyResponseChanged(); // if the custom settings box is clicked void onChangeCustom(); void updateMeterText(LLUICtrl* ctrl); @@ -140,7 +146,6 @@ public: void buildPopupLists(); static void refreshSkin(void* data); - static void cleanupBadSetting(); private: static std::string sSkin; bool mGotPersonalInfo; diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 3d833c24cc..468fd685ae 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -164,8 +164,6 @@ public: void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); LLFloaterPostcard* savePostcard(); - void confirmSavingTexture(bool set_as_profile_pic = false); - bool onSavingTextureConfirmed(const LLSD& notification, const LLSD& response, bool set_as_profile_pic); void saveTexture(bool set_as_profile_pic = false); BOOL saveLocal(); void saveWeb(std::string url); @@ -981,27 +979,6 @@ void profile_pic_upload_callback(const LLUUID& uuid, void *user_data, S32 status floater->setAsProfilePic(uuid); } -void LLSnapshotLivePreview::confirmSavingTexture(bool set_as_profile_pic) -{ - LLSD args; - args["AMOUNT"] = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - LLNotificationsUtil::add("UploadConfirmation", args, LLSD(), - boost::bind(&LLSnapshotLivePreview::onSavingTextureConfirmed, this, _1, _2, set_as_profile_pic)); -} - -bool LLSnapshotLivePreview::onSavingTextureConfirmed(const LLSD& notification, const LLSD& response, bool set_as_profile_pic) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - - if (option == 0) - { - saveTexture(set_as_profile_pic); - } - - return false; -} - - void LLSnapshotLivePreview::saveTexture(bool set_as_profile_pic) { // gen a new uuid for this asset @@ -1182,6 +1159,9 @@ public: static void onCommitSnapshotFormat(LLUICtrl* ctrl, void* data); static void onCommitCustomResolution(LLUICtrl *ctrl, void* data); static void onCommitSnapshot(LLFloaterSnapshot* view, LLSnapshotLivePreview::ESnapshotType type); + static void confirmSavingTexture(LLFloaterSnapshot* view, bool set_as_profile_pic = false); + static void onSavingTextureConfirmed(const LLSD& notification, const LLSD& response, LLFloaterSnapshot* view, bool set_as_profile_pic); + static void checkCloseOnKeep(LLFloaterSnapshot* view); static void onCommitProfilePic(LLFloaterSnapshot* view); static void showAdvanced(LLFloaterSnapshot* view, const BOOL visible); static void resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) ; @@ -1721,13 +1701,7 @@ public: void LLFloaterSnapshot::Impl::onCommitProfilePic(LLFloaterSnapshot* view) { - //first save to harddrive - LLSnapshotLivePreview* previewp = getPreviewView(view); - - if(previewp) - { - previewp->confirmSavingTexture(true); - } + confirmSavingTexture(view, true); } void LLFloaterSnapshot::Impl::onCommitSnapshot(LLFloaterSnapshot* view, LLSnapshotLivePreview::ESnapshotType type) @@ -1741,14 +1715,17 @@ void LLFloaterSnapshot::Impl::onCommitSnapshot(LLFloaterSnapshot* view, LLSnapsh if (type == LLSnapshotLivePreview::SNAPSHOT_WEB) { previewp->saveWeb(view->getString("share_to_web_url")); + checkCloseOnKeep(view); } else if (type == LLSnapshotLivePreview::SNAPSHOT_LOCAL) { previewp->saveLocal(); + checkCloseOnKeep(view); } else if (type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) { - previewp->confirmSavingTexture(); + // uploads and then calls checkCloseOnKeep() on confirmation from user + confirmSavingTexture(view); } else if (type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD) { @@ -1761,16 +1738,40 @@ void LLFloaterSnapshot::Impl::onCommitSnapshot(LLFloaterSnapshot* view, LLSnapsh gSnapshotFloaterView->addChild(floater); view->addDependentFloater(floater, FALSE); } + checkCloseOnKeep(view); } + } +} - if (gSavedSettings.getBOOL("CloseSnapshotOnKeep")) - { - view->closeFloater(); - } - else - { - checkAutoSnapshot(previewp); - } +void LLFloaterSnapshot::Impl::confirmSavingTexture(LLFloaterSnapshot* view, bool set_as_profile_pic) +{ + LLSD args; + args["AMOUNT"] = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + LLNotificationsUtil::add("UploadConfirmation", args, LLSD(), + boost::bind(&onSavingTextureConfirmed, _1, _2, view, set_as_profile_pic)); +} + +void LLFloaterSnapshot::Impl::onSavingTextureConfirmed(const LLSD& notification, const LLSD& response, LLFloaterSnapshot* view, bool set_as_profile_pic) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if (option == 0) + { + LLSnapshotLivePreview* previewp = getPreviewView(view); + previewp->saveTexture(set_as_profile_pic); + checkCloseOnKeep(view); + } +} + +void LLFloaterSnapshot::Impl::checkCloseOnKeep(LLFloaterSnapshot* view) +{ + if (gSavedSettings.getBOOL("CloseSnapshotOnKeep")) + { + view->closeFloater(); + } + else + { + checkAutoSnapshot(getPreviewView(view)); } } diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index a87f7288fa..74034cfbf7 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -88,6 +88,10 @@ const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH + /*first few characters*/ 40; const S32 MINIMUM_RENAMER_WIDTH = 80; +// *TODO: move in params in xml if necessary. Requires modification of LLFolderView & LLInventoryPanel Params. +const S32 STATUS_TEXT_HPAD = 6; +const S32 STATUS_TEXT_VPAD = 8; + enum { SIGNAL_NO_KEYBOARD_FOCUS = 1, SIGNAL_KEYBOARD_FOCUS = 2 @@ -246,6 +250,10 @@ LLFolderView::LLFolderView(const Params& p) text_p.font(font); text_p.visible(false); text_p.allow_html(true); + text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 + // set text padding the same as in People panel. EXT-7047, EXT-4837 + text_p.h_pad(STATUS_TEXT_HPAD); + text_p.v_pad(STATUS_TEXT_VPAD); mStatusTextBox = LLUICtrlFactory::create<LLTextBox> (text_p); mStatusTextBox->setFollowsLeft(); mStatusTextBox->setFollowsTop(); @@ -953,6 +961,23 @@ void LLFolderView::draw() } mStatusTextBox->setValue(mStatusText); mStatusTextBox->setVisible( TRUE ); + + // firstly reshape message textbox with current size. This is necessary to + // LLTextBox::getTextPixelHeight works properly + const LLRect local_rect = getLocalRect(); + mStatusTextBox->setShape(local_rect); + + // get preferable text height... + S32 pixel_height = mStatusTextBox->getTextPixelHeight(); + bool height_changed = local_rect.getHeight() != pixel_height; + if (height_changed) + { + // ... if it does not match current height, lets rearrange current view. + // This will indirectly call ::arrange and reshape of the status textbox. + // We should call this method to also notify parent about required rect. + // See EXT-7564, EXT-7047. + arrangeFromRoot(); + } } @@ -2310,7 +2335,7 @@ void LLFolderView::updateRenamerPosition() bool LLFolderView::selectFirstItem() { for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + iter != mFolders.end();++iter) { LLFolderViewFolder* folder = (*iter ); if (folder->getVisible()) @@ -2347,7 +2372,7 @@ bool LLFolderView::selectLastItem() } } for (folders_t::reverse_iterator iter = mFolders.rbegin(); - iter != mFolders.rend();) + iter != mFolders.rend();++iter) { LLFolderViewFolder* folder = (*iter); if (folder->getVisible()) diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 54e9bd5383..0c437cf035 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -96,6 +96,7 @@ void LLFolderViewItem::cleanupClass() LLFolderViewItem::Params::Params() : icon(), icon_open(), + icon_overlay(), root(), listener(), folder_arrow_image("folder_arrow_image"), @@ -133,6 +134,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mCreationDate(p.creation_date), mIcon(p.icon), mIconOpen(p.icon_open), + mIconOverlay(p.icon_overlay), mListener(p.listener), mHidden(false), mShowLoadStatus(false) @@ -617,6 +619,7 @@ const std::string& LLFolderViewItem::getSearchableLabel() const LLViewerInventoryItem * LLFolderViewItem::getInventoryItem(void) { + if (!getListener()) return NULL; return gInventory.getItem(getListener()->getUUID()); } @@ -948,7 +951,8 @@ void LLFolderViewItem::draw() mDragAndDropTarget = FALSE; } - + const LLViewerInventoryItem *item = getInventoryItem(); + const BOOL highlight_link = mIconOverlay && item && item->getIsLinkType(); //--------------------------------------------------------------------------------// // Draw open icon // @@ -962,6 +966,10 @@ void LLFolderViewItem::draw() mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); } + if (highlight_link) + { + mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } //--------------------------------------------------------------------------------// // Exit if no label to draw @@ -972,8 +980,7 @@ void LLFolderViewItem::draw() } LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; - const LLViewerInventoryItem *item = getInventoryItem(); - if (item && item->getIsLinkType()) color = sLinkColor; + if (highlight_link) color = sLinkColor; if (in_library) color = sLibraryColor; F32 right_x = 0; diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 57c722afa4..d6e4b2f556 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -97,6 +97,7 @@ public: { Optional<LLUIImage*> icon; Optional<LLUIImage*> icon_open; // used for folders + Optional<LLUIImage*> icon_overlay; // for links Optional<LLFolderView*> root; Optional<LLFolderViewEventListener*> listener; @@ -147,6 +148,7 @@ protected: LLUIImagePtr mIcon; std::string mStatusText; LLUIImagePtr mIconOpen; + LLUIImagePtr mIconOverlay; BOOL mHasVisibleChildren; S32 mIndentation; S32 mItemHeight; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3999a8ee88..a7d4880664 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -65,6 +65,7 @@ #include "llsidetray.h" #include "lltrans.h" #include "llviewerassettype.h" +#include "llviewerfoldertype.h" #include "llviewermenu.h" #include "llviewermessage.h" #include "llviewerobjectlist.h" @@ -2218,13 +2219,7 @@ void LLFolderBridge::determineFolderType() BOOL LLFolderBridge::isItemRenameable() const { - LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory(); - if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) - && (cat->getOwnerID() == gAgent.getID())) - { - return TRUE; - } - return FALSE; + return get_is_category_renameable(getInventoryModel(), mUUID); } void LLFolderBridge::restoreItem() @@ -2265,61 +2260,17 @@ LLUIImagePtr LLFolderBridge::getIcon() const } // static -LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type, BOOL is_link) +LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) { - // Bypassing LLViewerFolderType::lookup() since - // we aren't using different system folder icons - if (is_link) - { - if (preferred_type == LLFolderType::FT_OUTFIT) - return LLUI::getUIImage("Inv_LookFolderClosed_Link"); - else - return LLUI::getUIImage("Inv_FolderClosed_Link"); - } - - switch (preferred_type) - { - case LLFolderType::FT_OUTFIT: - return LLUI::getUIImage("Inv_LookFolderClosed"); - case LLFolderType::FT_LOST_AND_FOUND: - return LLUI::getUIImage("Inv_LostClosed"); - case LLFolderType::FT_TRASH: - return LLUI::getUIImage("Inv_TrashClosed"); - case LLFolderType::FT_NONE: - return LLUI::getUIImage("Inv_FolderClosed"); + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); /*case LLAssetType::AT_MESH: control = "inv_folder_mesh.tga"; break;*/ - default: - return LLUI::getUIImage("Inv_SysClosed"); - } } LLUIImagePtr LLFolderBridge::getOpenIcon() const { - // Bypassing LLViewerFolderType::lookup() since - // we aren't using different system folder icons - if (isLink()) - { - if (getPreferredType() == LLFolderType::FT_OUTFIT) - return LLUI::getUIImage("Inv_LookFolderOpen_Link"); - else - return LLUI::getUIImage("Inv_FolderOpen_Link"); - } - - switch (getPreferredType()) - { - case LLFolderType::FT_OUTFIT: - return LLUI::getUIImage("Inv_LookFolderOpen"); - case LLFolderType::FT_LOST_AND_FOUND: - return LLUI::getUIImage("Inv_LostOpen"); - case LLFolderType::FT_TRASH: - return LLUI::getUIImage("Inv_TrashOpen"); - case LLFolderType::FT_NONE: - return LLUI::getUIImage("Inv_FolderOpen"); - default: - return LLUI::getUIImage("Inv_SysOpen"); - } + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE)); } @@ -3192,7 +3143,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLUIImagePtr LLTextureBridge::getIcon() const { - return LLInventoryIcon::getIcon(LLAssetType::AT_TEXTURE, mInvType, mIsLink); + return LLInventoryIcon::getIcon(LLAssetType::AT_TEXTURE, mInvType); } void LLTextureBridge::openItem() @@ -3344,7 +3295,7 @@ LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, LLUIImagePtr LLLandmarkBridge::getIcon() const { - return LLInventoryIcon::getIcon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mIsLink, mVisited, FALSE); + return LLInventoryIcon::getIcon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE); } void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) @@ -3536,7 +3487,7 @@ LLUIImagePtr LLCallingCardBridge::getIcon() const { online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()); } - return LLInventoryIcon::getIcon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, mIsLink, online, FALSE); + return LLInventoryIcon::getIcon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE); } std::string LLCallingCardBridge::getLabelSuffix() const @@ -3978,7 +3929,7 @@ LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, LLUIImagePtr LLObjectBridge::getIcon() const { - return LLInventoryIcon::getIcon(LLAssetType::AT_OBJECT, mInvType, mIsLink, mAttachPt, mIsMultiObject); + return LLInventoryIcon::getIcon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject); } LLInventoryObject* LLObjectBridge::getObject() const @@ -4445,7 +4396,7 @@ std::string LLWearableBridge::getLabelSuffix() const LLUIImagePtr LLWearableBridge::getIcon() const { - return LLInventoryIcon::getIcon(mAssetType, mInvType, mIsLink, mWearableType, FALSE); + return LLInventoryIcon::getIcon(mAssetType, mInvType, mWearableType, FALSE); } // virtual @@ -4930,7 +4881,7 @@ LLUIImagePtr LLLinkFolderBridge::getIcon() const } } } - return LLFolderBridge::getIcon(folder_type, TRUE); + return LLFolderBridge::getIcon(folder_type); } void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 8de7d63173..3287f310c3 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -246,7 +246,7 @@ public: virtual LLFolderType::EType getPreferredType() const; virtual LLUIImagePtr getIcon() const; virtual LLUIImagePtr getOpenIcon() const; - static LLUIImagePtr getIcon(LLFolderType::EType preferred_type, BOOL is_link = FALSE); + static LLUIImagePtr getIcon(LLFolderType::EType preferred_type); virtual BOOL renameItem(const std::string& new_name); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 74fd331a06..d2fa8a683e 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -309,6 +309,11 @@ BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id) BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id) { + if (!model) + { + return FALSE; + } + LLViewerInventoryCategory* cat = model->getCategory(id); if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) && diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index c82ebd1439..93c56e1b8a 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -271,6 +271,32 @@ public: // // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFindByMask : public LLInventoryCollectFunctor +{ +public: + LLFindByMask(U64 mask) + : mFilterMask(mask) + {} + + virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) + { + if(item && (mFilterMask & (1LL << item->getInventoryType())) ) + { + return true; + } + + return false; + } + +private: + U64 mFilterMask; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFindNonLinksByMask +// +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLFindNonLinksByMask : public LLInventoryCollectFunctor { public: diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index 2fb55f4c1f..3090371a73 100644 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -40,13 +40,10 @@ struct IconEntry : public LLDictionaryEntry { - IconEntry(const std::string &item_name, - const std::string &link_name) + IconEntry(const std::string &item_name) : - LLDictionaryEntry(item_name), - mLinkName(link_name) + LLDictionaryEntry(item_name) {} - const std::string mLinkName; }; class LLIconDictionary : public LLSingleton<LLIconDictionary>, @@ -58,52 +55,51 @@ public: LLIconDictionary::LLIconDictionary() { - addEntry(LLInventoryIcon::ICONNAME_TEXTURE, new IconEntry("Inv_Texture", "Inv_Texture_Link")); - addEntry(LLInventoryIcon::ICONNAME_SOUND, new IconEntry("Inv_Texture", "Inv_Texture_Link")); - addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_ONLINE, new IconEntry("Inv_CallingCard", "Inv_CallingCard_Link")); - addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_OFFLINE, new IconEntry("Inv_CallingCard", "Inv_CallingCard_Link")); - addEntry(LLInventoryIcon::ICONNAME_LANDMARK, new IconEntry("Inv_Landmark", "Inv_Landmark_Link")); - addEntry(LLInventoryIcon::ICONNAME_LANDMARK_VISITED, new IconEntry("Inv_Landmark", "Inv_Landmark_Link")); - addEntry(LLInventoryIcon::ICONNAME_SCRIPT, new IconEntry("Inv_Script", "Inv_Script_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING, new IconEntry("Inv_Clothing", "Inv_Clothing_Link")); - addEntry(LLInventoryIcon::ICONNAME_OBJECT, new IconEntry("Inv_Object", "Inv_Object_Link")); - addEntry(LLInventoryIcon::ICONNAME_OBJECT_MULTI, new IconEntry("Inv_Object_Multi", "Inv_Object_Multi_Link")); - addEntry(LLInventoryIcon::ICONNAME_NOTECARD, new IconEntry("Inv_Notecard", "Inv_Notecard_Link")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART, new IconEntry("Inv_Skin", "Inv_Skin_Link")); - addEntry(LLInventoryIcon::ICONNAME_SNAPSHOT, new IconEntry("Inv_Snapshot", "Inv_Snapshot_Link")); + addEntry(LLInventoryIcon::ICONNAME_TEXTURE, new IconEntry("Inv_Texture")); + addEntry(LLInventoryIcon::ICONNAME_SOUND, new IconEntry("Inv_Texture")); + addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_ONLINE, new IconEntry("Inv_CallingCard")); + addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_OFFLINE, new IconEntry("Inv_CallingCard")); + addEntry(LLInventoryIcon::ICONNAME_LANDMARK, new IconEntry("Inv_Landmark")); + addEntry(LLInventoryIcon::ICONNAME_LANDMARK_VISITED, new IconEntry("Inv_Landmark")); + addEntry(LLInventoryIcon::ICONNAME_SCRIPT, new IconEntry("Inv_Script")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING, new IconEntry("Inv_Clothing")); + addEntry(LLInventoryIcon::ICONNAME_OBJECT, new IconEntry("Inv_Object")); + addEntry(LLInventoryIcon::ICONNAME_OBJECT_MULTI, new IconEntry("Inv_Object_Multi")); + addEntry(LLInventoryIcon::ICONNAME_NOTECARD, new IconEntry("Inv_Notecard")); + addEntry(LLInventoryIcon::ICONNAME_BODYPART, new IconEntry("Inv_Skin")); + addEntry(LLInventoryIcon::ICONNAME_SNAPSHOT, new IconEntry("Inv_Snapshot")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_SHAPE, new IconEntry("Inv_BodyShape", "Inv_BodyShape_Link")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_SKIN, new IconEntry("Inv_Skin", "Inv_Skin_Link")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_HAIR, new IconEntry("Inv_Hair", "Inv_Hair_Link")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_EYES, new IconEntry("Inv_Eye", "Inv_Eye_Link")); + addEntry(LLInventoryIcon::ICONNAME_BODYPART_SHAPE, new IconEntry("Inv_BodyShape")); + addEntry(LLInventoryIcon::ICONNAME_BODYPART_SKIN, new IconEntry("Inv_Skin")); + addEntry(LLInventoryIcon::ICONNAME_BODYPART_HAIR, new IconEntry("Inv_Hair")); + addEntry(LLInventoryIcon::ICONNAME_BODYPART_EYES, new IconEntry("Inv_Eye")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, new IconEntry("Inv_Shirt", "Inv_Shirt_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PANTS, new IconEntry("Inv_Pants", "Inv_Pants_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHOES, new IconEntry("Inv_Shoe", "Inv_Shoe_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, new IconEntry("Inv_Socks", "Inv_Socks_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_JACKET, new IconEntry("Inv_Jacket", "Inv_Jacket_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, new IconEntry("Inv_Gloves", "Inv_Gloves_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, new IconEntry("Inv_Undershirt", "Inv_Undershirt_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, new IconEntry("Inv_Underpants", "Inv_Underpants_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, new IconEntry("Inv_Skirt", "Inv_Skirt_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, new IconEntry("Inv_Alpha", "Inv_Alpha_Link")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, new IconEntry("Inv_Tattoo", "Inv_Tattoo_Link")); - addEntry(LLInventoryIcon::ICONNAME_ANIMATION, new IconEntry("Inv_Animation", "Inv_Animation_Link")); - addEntry(LLInventoryIcon::ICONNAME_GESTURE, new IconEntry("Inv_Gesture", "Inv_Gesture_Link")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, new IconEntry("Inv_Shirt")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PANTS, new IconEntry("Inv_Pants")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHOES, new IconEntry("Inv_Shoe")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, new IconEntry("Inv_Socks")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_JACKET, new IconEntry("Inv_Jacket")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, new IconEntry("Inv_Gloves")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, new IconEntry("Inv_Undershirt")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, new IconEntry("Inv_Underpants")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, new IconEntry("Inv_Skirt")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, new IconEntry("Inv_Alpha")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, new IconEntry("Inv_Tattoo")); + addEntry(LLInventoryIcon::ICONNAME_ANIMATION, new IconEntry("Inv_Animation")); + addEntry(LLInventoryIcon::ICONNAME_GESTURE, new IconEntry("Inv_Gesture")); - addEntry(LLInventoryIcon::ICONNAME_LINKITEM, new IconEntry("Inv_LinkItem", "Inv_LinkItem")); - addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkItem", "Inv_LinkItem")); + addEntry(LLInventoryIcon::ICONNAME_LINKITEM, new IconEntry("Inv_LinkItem")); + addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkItem")); - addEntry(LLInventoryIcon::ICONNAME_NONE, new IconEntry("NONE", "NONE")); + addEntry(LLInventoryIcon::ICONNAME_NONE, new IconEntry("NONE")); } LLUIImagePtr LLInventoryIcon::getIcon(LLAssetType::EType asset_type, LLInventoryType::EType inventory_type, - BOOL item_is_link, U32 misc_flag, BOOL item_is_multi) { - const std::string& icon_name = getIconName(asset_type, inventory_type, item_is_link, misc_flag, item_is_multi); + const std::string& icon_name = getIconName(asset_type, inventory_type, misc_flag, item_is_multi); return LLUI::getUIImage(icon_name); } @@ -114,7 +110,6 @@ LLUIImagePtr LLInventoryIcon::getIcon(EIconName idx) const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type, LLInventoryType::EType inventory_type, - BOOL item_is_link, U32 misc_flag, BOOL item_is_multi) { @@ -169,14 +164,13 @@ const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type, break; } - return getIconName(idx, item_is_link); + return getIconName(idx); } -const std::string& LLInventoryIcon::getIconName(EIconName idx, BOOL item_is_link) +const std::string& LLInventoryIcon::getIconName(EIconName idx) { const IconEntry *entry = LLIconDictionary::instance().lookup(idx); - if (item_is_link) return entry->mLinkName; return entry->mName; } diff --git a/indra/newview/llinventoryicon.h b/indra/newview/llinventoryicon.h index 4cb7a123c4..6e29012c4c 100644 --- a/indra/newview/llinventoryicon.h +++ b/indra/newview/llinventoryicon.h @@ -86,15 +86,12 @@ public: static const std::string& getIconName(LLAssetType::EType asset_type, LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, - BOOL item_is_link = FALSE, U32 misc_flag = 0, // different meanings depending on item type BOOL item_is_multi = FALSE); - static const std::string& getIconName(EIconName idx, - BOOL item_is_link = FALSE); + static const std::string& getIconName(EIconName idx); static LLUIImagePtr getIcon(LLAssetType::EType asset_type, LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, - BOOL item_is_link = FALSE, U32 misc_flag = 0, // different meanings depending on item type BOOL item_is_multi = FALSE); static LLUIImagePtr getIcon(EIconName idx); diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index cd0e976a79..23ea786484 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -70,16 +70,20 @@ void LLPanelInventoryListItemBase::draw() { if (getNeedsRefresh()) { - updateItem(); + if (mItem) + { + updateItem(mItem->getName()); + } setNeedsRefresh(false); } LLPanel::draw(); } -void LLPanelInventoryListItemBase::updateItem() +// virtual +void LLPanelInventoryListItemBase::updateItem(const std::string& name) { setIconImage(mIconImage); - setTitle(mItem->getName(), mHighlightedText); + setTitle(name, mHighlightedText); } void LLPanelInventoryListItemBase::addWidgetToLeftSide(const std::string& name, bool show_widget/* = true*/) @@ -132,8 +136,11 @@ BOOL LLPanelInventoryListItemBase::postBuild() setIconCtrl(getChild<LLIconCtrl>("item_icon")); setTitleCtrl(getChild<LLTextBox>("item_name")); - BOOL show_links = mForceNoLinksOnIcons ? FALSE : mItem->getIsLinkType(); - mIconImage = LLInventoryIcon::getIcon(mItem->getType(), mItem->getInventoryType(), show_links, mItem->getFlags(), FALSE); + if (mItem) + { + mIconImage = LLInventoryIcon::getIcon(mItem->getType(), mItem->getInventoryType(), mItem->getFlags(), FALSE); + updateItem(mItem->getName()); + } setNeedsRefresh(true); @@ -162,6 +169,42 @@ void LLPanelInventoryListItemBase::onMouseLeave(S32 x, S32 y, MASK mask) LLPanel::onMouseLeave(x, y, mask); } +const std::string& LLPanelInventoryListItemBase::getItemName() const +{ + if (!mItem) + { + return LLStringUtil::null; + } + return mItem->getName(); +} + +LLAssetType::EType LLPanelInventoryListItemBase::getType() const +{ + if (!mItem) + { + return LLAssetType::AT_NONE; + } + return mItem->getType(); +} + +LLWearableType::EType LLPanelInventoryListItemBase::getWearableType() const +{ + if (!mItem) + { + return LLWearableType::WT_NONE; + } + return mItem->getWearableType(); +} + +const std::string& LLPanelInventoryListItemBase::getDescription() const +{ + if (!mItem) + { + return LLStringUtil::null; + } + return mItem->getDescription(); +} + S32 LLPanelInventoryListItemBase::notify(const LLSD& info) { S32 rv = 0; @@ -169,7 +212,7 @@ S32 LLPanelInventoryListItemBase::notify(const LLSD& info) { mHighlightedText = info["match_filter"].asString(); - std::string test(mItem->getName()); + std::string test(mTitleCtrl->getText()); LLStringUtil::toUpper(test); if(mHighlightedText.empty() || std::string::npos != test.find(mHighlightedText)) @@ -199,7 +242,6 @@ LLPanelInventoryListItemBase::LLPanelInventoryListItemBase(LLViewerInventoryItem , mLeftWidgetsWidth(0) , mRightWidgetsWidth(0) , mNeedsRefresh(false) -, mForceNoLinksOnIcons(false) { } diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index 2c60d38cb5..d6132717e8 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -122,16 +122,16 @@ public: /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); /** Get the name of a corresponding inventory item */ - const std::string& getItemName() const { return mItem->getName(); } + const std::string& getItemName() const; /** Get the asset type of a corresponding inventory item */ - LLAssetType::EType getType() const { return mItem->getType(); } + LLAssetType::EType getType() const; /** Get the wearable type of a corresponding inventory item */ - LLWearableType::EType getWearableType() const { return mItem->getWearableType(); } + LLWearableType::EType getWearableType() const; /** Get the description of a corresponding inventory item */ - const std::string& getDescription() const { return mItem->getDescription(); } + const std::string& getDescription() const; /** Get the associated inventory item */ LLViewerInventoryItem* getItem() const { return mItem; } @@ -152,7 +152,7 @@ protected: /** * Called after inventory item was updated, update panel widgets to reflect inventory changes. */ - virtual void updateItem(); + virtual void updateItem(const std::string& name); /** setter for mIconCtrl */ void setIconCtrl(LLIconCtrl* icon) { mIconCtrl = icon; } @@ -182,9 +182,6 @@ protected: LLViewerInventoryItem* mItem; - // force not showing link icon on item's icon - bool mForceNoLinksOnIcons; - private: /** reshape left side widgets diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index bb3f34dde2..6b0103e0de 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -87,6 +87,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mSortOrderSetting(p.sort_order_setting), mInventory(p.inventory), mAllowMultiSelect(p.allow_multi_select), + mShowItemLinkOverlays(p.show_item_link_overlays), mViewsInitialized(false), mStartFolderString(p.start_folder), mBuildDefaultHierarchy(true), @@ -188,6 +189,8 @@ LLInventoryPanel::~LLInventoryPanel() } } + gIdleCallbacks.deleteFunction(onIdle, this); + // LLView destructor will take care of the sub-views. mInventory->removeObserver(mInventoryObserver); delete mInventoryObserver; @@ -522,6 +525,10 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id) params.name = new_listener->getDisplayName(); params.icon = new_listener->getIcon(); params.icon_open = new_listener->getOpenIcon(); + if (mShowItemLinkOverlays) // if false, then links show up just like normal items + { + params.icon_overlay = LLUI::getUIImage("Inv_Link"); + } params.root = mFolderRoot; params.listener = new_listener; params.tool_tip = params.name; @@ -560,6 +567,10 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id) params.name = new_listener->getDisplayName(); params.icon = new_listener->getIcon(); params.icon_open = new_listener->getOpenIcon(); + if (mShowItemLinkOverlays) // if false, then links show up just like normal items + { + params.icon_overlay = LLUI::getUIImage("Inv_Link"); + } params.creation_date = new_listener->getCreationDate(); params.root = mFolderRoot; params.listener = new_listener; diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 4373cedf66..67c8904868 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -84,6 +84,7 @@ public: Optional<std::string> sort_order_setting; Optional<LLInventoryModel*> inventory; Optional<bool> allow_multi_select; + Optional<bool> show_item_link_overlays; Optional<Filter> filter; Optional<std::string> start_folder; @@ -91,6 +92,7 @@ public: : sort_order_setting("sort_order_setting"), inventory("", &gInventory), allow_multi_select("allow_multi_select", true), + show_item_link_overlays("show_item_link_overlays", false), filter("filter"), start_folder("start_folder") {} @@ -177,6 +179,7 @@ protected: LLInventoryModel* mInventory; LLInventoryObserver* mInventoryObserver; BOOL mAllowMultiSelect; + BOOL mShowItemLinkOverlays; // Shows link graphic over inventory item icons LLFolderView* mFolderRoot; LLScrollContainer* mScroller; diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp index 9e1dc3a4b0..c2a1923dfe 100644 --- a/indra/newview/lljoystickbutton.cpp +++ b/indra/newview/lljoystickbutton.cpp @@ -53,7 +53,6 @@ static LLDefaultChildRegistry::Register<LLJoystickAgentSlide> r1("joystick_slide"); static LLDefaultChildRegistry::Register<LLJoystickAgentTurn> r2("joystick_turn"); static LLDefaultChildRegistry::Register<LLJoystickCameraRotate> r3("joystick_rotate"); -static LLDefaultChildRegistry::Register<LLJoystickCameraZoom> r4("joystick_zoom"); static LLDefaultChildRegistry::Register<LLJoystickCameraTrack> r5("joystick_track"); @@ -647,155 +646,3 @@ void LLJoystickCameraTrack::onHeldDown() gAgentCamera.setPanDownKey(getOrbitRate()); } } - - - -//------------------------------------------------------------------------------- -// LLJoystickCameraZoom -//------------------------------------------------------------------------------- - -LLJoystickCameraZoom::LLJoystickCameraZoom(const LLJoystickCameraZoom::Params& p) -: LLJoystick(p), - mInTop( FALSE ), - mInBottom( FALSE ), - mPlusInImage(p.plus_image), - mMinusInImage(p.minus_image) -{ -} - -BOOL LLJoystickCameraZoom::handleMouseDown(S32 x, S32 y, MASK mask) -{ - BOOL handled = LLJoystick::handleMouseDown(x, y, mask); - - if( handled ) - { - if (mFirstMouse.mY > getRect().getHeight() / 2) - { - mInitialQuadrant = JQ_UP; - } - else - { - mInitialQuadrant = JQ_DOWN; - } - } - return handled; -} - - -void LLJoystickCameraZoom::onHeldDown() -{ - updateSlop(); - - const F32 FAST_RATE = 2.5f; // two and a half times the normal rate - - S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY; - - if (dy > mVertSlopFar) - { - // Zoom in fast - gAgentCamera.unlockView(); - gAgentCamera.setOrbitInKey(FAST_RATE); - } - else if (dy > mVertSlopNear) - { - // Zoom in slow - gAgentCamera.unlockView(); - gAgentCamera.setOrbitInKey(getOrbitRate()); - } - else if (dy < -mVertSlopFar) - { - // Zoom out fast - gAgentCamera.unlockView(); - gAgentCamera.setOrbitOutKey(FAST_RATE); - } - else if (dy < -mVertSlopNear) - { - // Zoom out slow - gAgentCamera.unlockView(); - gAgentCamera.setOrbitOutKey(getOrbitRate()); - } -} - -// Only used for drawing -void LLJoystickCameraZoom::setToggleState( BOOL top, BOOL bottom ) -{ - mInTop = top; - mInBottom = bottom; -} - -void LLJoystickCameraZoom::draw() -{ - if( mInTop ) - { - mPlusInImage->draw(0,0); - } - else - if( mInBottom ) - { - mMinusInImage->draw(0,0); - } - else - { - getImageUnselected()->draw( 0, 0 ); - } -} - -void LLJoystickCameraZoom::updateSlop() -{ - mVertSlopNear = getRect().getHeight() / 4; - mVertSlopFar = getRect().getHeight() / 2; - - mHorizSlopNear = getRect().getWidth() / 4; - mHorizSlopFar = getRect().getWidth() / 2; - - // Compute initial mouse offset based on initial quadrant. - // Place the mouse evenly between the near and far zones. - switch (mInitialQuadrant) - { - case JQ_ORIGIN: - mInitialOffset.set(0, 0); - break; - - case JQ_UP: - mInitialOffset.mX = 0; - mInitialOffset.mY = (mVertSlopNear + mVertSlopFar) / 2; - break; - - case JQ_DOWN: - mInitialOffset.mX = 0; - mInitialOffset.mY = - (mVertSlopNear + mVertSlopFar) / 2; - break; - - case JQ_LEFT: - mInitialOffset.mX = - (mHorizSlopNear + mHorizSlopFar) / 2; - mInitialOffset.mY = 0; - break; - - case JQ_RIGHT: - mInitialOffset.mX = (mHorizSlopNear + mHorizSlopFar) / 2; - mInitialOffset.mY = 0; - break; - - default: - llerrs << "LLJoystick::LLJoystick() - bad switch case" << llendl; - break; - } - - return; -} - - -F32 LLJoystickCameraZoom::getOrbitRate() -{ - F32 time = getElapsedHeldDownTime(); - if( time < NUDGE_TIME ) - { - F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME; -// llinfos << "rate " << rate << " time " << time << llendl; - return rate; - } - else - { - return 1; - } -} diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h index 2b071a8999..1dd30036ab 100644 --- a/indra/newview/lljoystickbutton.h +++ b/indra/newview/lljoystickbutton.h @@ -183,44 +183,4 @@ public: virtual void onHeldDown(); }; - -// Zoom the camera in and out -class LLJoystickCameraZoom -: public LLJoystick -{ -public: - struct Params - : public LLInitParam::Block<Params, LLJoystick::Params> - { - Optional<LLUIImage*> plus_image; - Optional<LLUIImage*> minus_image; - - Params() - : plus_image ("plus_image", NULL), - minus_image ("minus_image", NULL) - { - held_down_delay.seconds(0.0); - } - }; - LLJoystickCameraZoom(const Params&); - - virtual void setToggleState( BOOL top, BOOL bottom ); - - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual void onHeldDown(); - virtual void draw(); - -protected: - virtual void updateSlop(); - F32 getOrbitRate(); - -protected: - BOOL mInTop; - BOOL mInBottom; - LLUIImagePtr mPlusInImage; - LLUIImagePtr mMinusInImage; -}; - - - #endif // LL_LLJOYSTICKBUTTON_H diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index f1c13de8bb..1beaaf3cb4 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -49,7 +49,6 @@ #include "llchannelmanager.h" #include "llagent.h" // gAgent -#include "llfloaterscriptdebug.h" #include "llchathistory.h" #include "llstylemap.h" @@ -163,25 +162,6 @@ std::string appendTime() void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) { - if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) - { - if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) - return; - if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat")) - { - - LLColor4 txt_color; - - LLViewerChat::getChatColor(chat,txt_color); - - LLFloaterScriptDebug::addScriptLine(chat.mText, - chat.mFromName, - txt_color, - chat.mFromID); - return; - } - } - LLChat& tmp_chat = const_cast<LLChat&>(chat); if(tmp_chat.mTimeStr.empty()) diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 9824517ed1..1fadb126e4 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -32,10 +32,12 @@ #include "llviewerprecompiledheaders.h" +#include "llagentdata.h" // for gAgentID #include "llnearbychathandler.h" #include "llbottomtray.h" #include "llchatitemscontainerctrl.h" +#include "llfloaterscriptdebug.h" #include "llnearbychat.h" #include "llrecentpeople.h" @@ -287,7 +289,7 @@ void LLNearbyChatScreenChannel::showToastsBottom() toast_rect.setLeftTopAndSize(getRect().mLeft , bottom + toast_rect.getHeight(), toast_rect.getWidth() ,toast_rect.getHeight()); toast->setRect(toast_rect); - bottom += toast_rect.getHeight() + margin; + bottom += toast_rect.getHeight() - toast->getTopPad() + margin; } // use reverse order to provide correct z-order and avoid toast blinking @@ -358,6 +360,36 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args) //if(tmp_chat.mFromName.empty() && tmp_chat.mFromID!= LLUUID::null) // tmp_chat.mFromName = tmp_chat.mFromID.asString(); } + + // don't show toast and add message to chat history on receive debug message + // with disabled setting showing script errors or enabled setting to show script + // errors in separate window. + if (chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG) + { + if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) + return; + + // don't process debug messages from not owned objects, see EXT-7762 + if (gAgentID != chat_msg.mOwnerID) + { + return; + } + + if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat")) + { + + LLColor4 txt_color; + + LLViewerChat::getChatColor(chat_msg,txt_color); + + LLFloaterScriptDebug::addScriptLine(chat_msg.mText, + chat_msg.mFromName, + txt_color, + chat_msg.mFromID); + return; + } + } + nearby_chat->addMessage(chat_msg, true, args); if( nearby_chat->getVisible() || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT diff --git a/indra/newview/lloutfitobserver.cpp b/indra/newview/lloutfitobserver.cpp index 5652a98981..efa01bade9 100644 --- a/indra/newview/lloutfitobserver.cpp +++ b/indra/newview/lloutfitobserver.cpp @@ -74,6 +74,16 @@ S32 LLOutfitObserver::getCategoryVersion(const LLUUID& cat_id) return cat->getVersion(); } +// static +const std::string& LLOutfitObserver::getCategoryName(const LLUUID& cat_id) +{ + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + if (!cat) + return LLStringUtil::null; + + return cat->getName(); +} + bool LLOutfitObserver::checkCOF() { LLUUID cof = LLAppearanceMgr::getInstance()->getCOF(); @@ -105,8 +115,11 @@ void LLOutfitObserver::checkBaseOutfit() return; const S32 baseoutfit_ver = getCategoryVersion(baseoutfit_id); + const std::string& baseoutfit_name = getCategoryName(baseoutfit_id); - if (baseoutfit_ver == mBaseOutfitLastVersion) + if (baseoutfit_ver == mBaseOutfitLastVersion + // renaming category doesn't change version, so it's need to check it + && baseoutfit_name == mLastBaseOutfitName) return; } else @@ -116,10 +129,11 @@ void LLOutfitObserver::checkBaseOutfit() if (baseoutfit_id.isNull()) return; - - mBaseOutfitLastVersion = getCategoryVersion(mBaseOutfitId); } + mBaseOutfitLastVersion = getCategoryVersion(mBaseOutfitId); + mLastBaseOutfitName = getCategoryName(baseoutfit_id); + LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance(); // dirtiness state should be updated before sending signal app_mgr.updateIsDirty(); diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h index a4b5fbe04a..3a66b5ea9f 100644 --- a/indra/newview/lloutfitobserver.h +++ b/indra/newview/lloutfitobserver.h @@ -68,6 +68,8 @@ protected: /** Get a version of an inventory category specified by its UUID */ static S32 getCategoryVersion(const LLUUID& cat_id); + static const std::string& getCategoryName(const LLUUID& cat_id); + bool checkCOF(); void checkBaseOutfit(); @@ -78,6 +80,7 @@ protected: LLUUID mBaseOutfitId; S32 mBaseOutfitLastVersion; + std::string mLastBaseOutfitName; bool mLastOutfitDirtiness; diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index e20b2e26be..03df2d2b20 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -44,6 +44,7 @@ #include "llinventorymodel.h" #include "lllistcontextmenu.h" #include "llnotificationsutil.h" +#include "lloutfitobserver.h" #include "llsidetray.h" #include "lltransutil.h" #include "llviewermenu.h" @@ -89,17 +90,33 @@ protected: registrar.add("Outfit.Delete", boost::bind(deleteOutfit, selected_id)); enable_registrar.add("Outfit.OnEnable", boost::bind(&OutfitContextMenu::onEnable, this, _2)); + enable_registrar.add("Outfit.OnVisible", boost::bind(&OutfitContextMenu::onVisible, this, _2)); return createFromFile("menu_outfit_tab.xml"); } - bool onEnable(const LLSD& data) + bool onEnable(LLSD::String param) + { + LLUUID outfit_cat_id = mUUIDs.back(); + + if ("rename" == param) + { + return get_is_category_renameable(&gInventory, outfit_cat_id); + } + + return true; + } + + bool onVisible(LLSD::String param) { - std::string param = data.asString(); LLUUID outfit_cat_id = mUUIDs.back(); bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id; - if ("wear_replace" == param) + if ("edit" == param) + { + return is_worn; + } + else if ("wear_replace" == param) { return !is_worn; } @@ -111,14 +128,6 @@ protected: { return is_worn; } - else if ("edit" == param) - { - return is_worn; - } - else if ("rename" == param) - { - return get_is_category_renameable(&gInventory, outfit_cat_id); - } else if ("delete" == param) { return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id); @@ -199,6 +208,9 @@ void LLOutfitsList::onOpen(const LLSD& /*info*/) mCategoriesObserver->addCategory(outfits, boost::bind(&LLOutfitsList::refreshList, this, outfits)); + // Start observing changes in Current Outfit to update items worn state. + LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLOutfitsList::onCOFChanged, this)); + // Fetch "My Outfits" contents and refresh the list to display // initially fetched items. If not all items are fetched now // the observer will refresh the list as soon as the new items @@ -322,7 +334,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) // 3. Reset currently selected outfit id if it is being removed. if (outfit_id == mSelectedOutfitUUID) { - mSelectedOutfitUUID = LLUUID(); + setSelectedOutfitUUID(LLUUID()); } // 4. Remove category UUID to accordion tab mapping. @@ -385,6 +397,11 @@ void LLOutfitsList::setFilterSubString(const std::string& string) mFilterSubString = string; } +boost::signals2::connection LLOutfitsList::addSelectionChangeCallback(selection_change_callback_t cb) +{ + return mSelectionChangeSignal.connect(cb); +} + ////////////////////////////////////////////////////////////////////////// // Private methods ////////////////////////////////////////////////////////////////////////// @@ -471,7 +488,12 @@ void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUI } mSelectedListsMap.insert(wearables_lists_map_value_t(category_id, list)); - mSelectedOutfitUUID = category_id; + setSelectedOutfitUUID(category_id); +} + +void LLOutfitsList::setSelectedOutfitUUID(const LLUUID& category_id) +{ + mSelectionChangeSignal(mSelectedOutfitUUID = category_id); } void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl) @@ -645,6 +667,43 @@ void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) LLWearableItemsList::ContextMenu::instance().show(list, selected_uuids, x, y); } +void LLOutfitsList::onCOFChanged() +{ + LLInventoryModel::changed_items_t changed_linked_items; + + const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); + for (LLInventoryModel::changed_items_t::const_iterator iter = changed_items.begin(); + iter != changed_items.end(); + ++iter) + { + LLViewerInventoryItem* item = gInventory.getItem(*iter); + if (item) + { + // From gInventory we get the UUIDs of new links added to COF + // or removed from COF. These links UUIDs are not the same UUIDs + // that we have in each wearable items list. So we collect base items + // UUIDs to find all items or links that point to same base items in wearable + // items lists and update their worn state there. + changed_linked_items.insert(item->getLinkedUUID()); + } + } + + for (outfits_map_t::iterator iter = mOutfitsMap.begin(); + iter != mOutfitsMap.end(); + ++iter) + { + LLAccordionCtrlTab* tab = iter->second; + if (!tab) continue; + + LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView()); + if (!list) continue; + + // Every list updates the labels of changed items or + // the links that point to these items. + list->updateChangedItems(changed_linked_items); + } +} + bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y) { if(!tab || !tab->getHeaderVisible()) return false; diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index bb516446d2..478eaa50b3 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -71,6 +71,9 @@ public: class LLOutfitsList : public LLPanel { public: + typedef boost::function<void (const LLUUID&)> selection_change_callback_t; + typedef boost::signals2::signal<void (const LLUUID&)> selection_change_signal_t; + LLOutfitsList(); virtual ~LLOutfitsList(); @@ -86,6 +89,8 @@ public: const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; } + boost::signals2::connection addSelectionChangeCallback(selection_change_callback_t cb); + private: /** * Reads xml with accordion tab and Flat list from xml file. @@ -110,6 +115,11 @@ private: void changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id); /** + * Saves newly selected outfit ID. + */ + void setSelectedOutfitUUID(const LLUUID& category_id); + + /** * Called upon list refresh event to update tab visibility depending on * the results of applying filter to the title and list items of the tab. */ @@ -123,6 +133,7 @@ private: void onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id); void onAccordionTabDoubleClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id); void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y); + void onCOFChanged(); void onSelectionChange(LLUICtrl* ctrl); @@ -138,6 +149,7 @@ private: wearables_lists_map_t mSelectedListsMap; LLUUID mSelectedOutfitUUID; + selection_change_signal_t mSelectionChangeSignal; std::string mFilterSubString; diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index a1a9300ec2..1aedfec86f 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -61,6 +61,9 @@ #include "llagentcamera.h" #include "llmorphview.h" +#include "llcommandhandler.h" +#include "lltextutil.h" + // register panel with appropriate XML static LLRegisterPanelClassWrapper<LLPanelEditWearable> t_edit_wearable("panel_edit_wearable"); @@ -608,6 +611,36 @@ LLPanelEditWearable::~LLPanelEditWearable() } +bool LLPanelEditWearable::changeHeightUnits(const LLSD& new_value) +{ + updateMetricLayout( new_value.asBoolean() ); + updateTypeSpecificControls(LLWearableType::WT_SHAPE); + return true; +} + +void LLPanelEditWearable::updateMetricLayout(BOOL new_value) +{ + LLUIString current_metric, replacment_metric; + current_metric = new_value ? mMeters : mFeet; + replacment_metric = new_value ? mFeet : mMeters; + mHeigthValue.setArg( "[METRIC1]", current_metric.getString() ); + mReplacementMetricUrl.setArg( "[URL_METRIC2]", std::string("[secondlife:///app/metricsystem ") + replacment_metric.getString() + std::string("]")); +} + +void LLPanelEditWearable::updateAvatarHeightLabel() +{ + mTxtAvatarHeight->setText(LLStringUtil::null); + LLStyle::Params param; + param.color = mAvatarHeigthLabelColor; + mTxtAvatarHeight->appendText(mHeigth, false, param); + param.color = mAvatarHeigthValueLabelColor; + mTxtAvatarHeight->appendText(mHeigthValue, false, param); + param.color = mAvatarHeigthLabelColor; // using mAvatarHeigthLabelColor for '/' separator + mTxtAvatarHeight->appendText(" / ", false, param); + mTxtAvatarHeight->appendText(this->mReplacementMetricUrl, false, param); +} + + // virtual BOOL LLPanelEditWearable::postBuild() { @@ -700,6 +733,20 @@ BOOL LLPanelEditWearable::postBuild() for_each_picker_ctrl_entry <LLTextureCtrl> (getPanel(type), type, boost::bind(init_texture_ctrl, this, _1, _2)); } + // init all strings + mMeters = mPanelShape->getString("meters"); + mFeet = mPanelShape->getString("feet"); + mHeigth = mPanelShape->getString("height") + " "; + mHeigthValue = "[HEIGHT] [METRIC1]"; + mReplacementMetricUrl = "[URL_METRIC2]"; + + std::string color = mPanelShape->getString("heigth_label_color"); + mAvatarHeigthLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green); + color = mPanelShape->getString("heigth_value_label_color"); + mAvatarHeigthValueLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green); + gSavedSettings.getControl("HeightUnits")->getSignal()->connect(boost::bind(&LLPanelEditWearable::changeHeightUnits, this, _2)); + updateMetricLayout(gSavedSettings.getBOOL("HeightUnits")); + return TRUE; } @@ -1107,12 +1154,22 @@ void LLPanelEditWearable::toggleTypeSpecificControls(LLWearableType::EType type) void LLPanelEditWearable::updateTypeSpecificControls(LLWearableType::EType type) { + const F32 ONE_METER = 1.0; + const F32 ONE_FOOT = 0.3048 * ONE_METER; // in meters // Update controls specific to shape editing panel. if (type == LLWearableType::WT_SHAPE) { // Update avatar height - std::string avatar_height_str = llformat("%.2f", gAgentAvatarp->mBodySize.mV[VZ]); - mTxtAvatarHeight->setTextArg("[HEIGHT]", avatar_height_str); + F32 new_size = gAgentAvatarp->mBodySize.mV[VZ]; + if (gSavedSettings.getBOOL("HeightUnits") == FALSE) + { + // convert meters to feet + new_size = new_size / ONE_FOOT; + } + + std::string avatar_height_str = llformat("%.2f", new_size); + mHeigthValue.setArg("[HEIGHT]", avatar_height_str); + updateAvatarHeightLabel(); } if (LLWearableType::WT_ALPHA == type) @@ -1381,4 +1438,21 @@ void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLVOAvatarDefines::EText } } +// handle secondlife:///app/metricsystem +class LLMetricSystemHandler : public LLCommandHandler +{ +public: + LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + // change height units TRUE for meters and FALSE for feet + BOOL new_value = (gSavedSettings.getBOOL("HeightUnits") == FALSE) ? TRUE : FALSE; + gSavedSettings.setBOOL("HeightUnits", new_value); + return true; + } +}; + +LLMetricSystemHandler gMetricSystemHandler; + // EOF diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 54f729fa7a..c63671fcc9 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -104,6 +104,15 @@ private: void initPreviousAlphaTextures(); void initPreviousAlphaTextureEntry(LLVOAvatarDefines::ETextureIndex te); + // callback for HeightUnits parameter. + bool changeHeightUnits(const LLSD& new_value); + + // updates current metric and replacemet metric label text + void updateMetricLayout(BOOL new_value); + + // updates avatar height label + void updateAvatarHeightLabel(); + // the pointer to the wearable we're editing. NULL means we're not editing a wearable. LLWearable *mWearablePtr; LLViewerInventoryItem* mWearableItem; @@ -117,6 +126,18 @@ private: LLTextBox *mTxtAvatarHeight; + // localized and parametrized strings that used to build avatar_height_label + std::string mMeters; + std::string mFeet; + std::string mHeigth; + LLUIString mHeigthValue; + LLUIString mReplacementMetricUrl; + + // color for mHeigth string + LLUIColor mAvatarHeigthLabelColor; + // color for mHeigthValue string + LLUIColor mAvatarHeigthValueLabelColor; + // This text editor reference will change each time we edit a new wearable - // it will be grabbed from the currently visible panel LLTextEditor *mTextEditor; diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index d8cfd4fc5d..91166b0f5b 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -341,7 +341,6 @@ void LLPanelGroupNotices::setItem(LLPointer<LLInventoryItem> inv_item) std::string icon_name = LLInventoryIcon::getIconName(inv_item->getType(), inv_item->getInventoryType(), inv_item->getFlags(), - inv_item->getIsLinkType(), item_is_multi ); mCreateInventoryIcon->setValue(icon_name); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 7fb46fc84f..ce1131f45c 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -334,7 +334,7 @@ void LLLandmarksPanel::updateVerbs() bool landmark_selected = isLandmarkSelected(); mTeleportBtn->setEnabled(landmark_selected && isActionEnabled("teleport")); mShowProfile->setEnabled(landmark_selected && isActionEnabled("more_info")); - mShowOnMapBtn->setEnabled(true); + mShowOnMapBtn->setEnabled(landmark_selected && isActionEnabled("show_on_map")); // TODO: mantipov: Uncomment when mShareBtn is supported // Share button should be enabled when neither a folder nor a landmark is selected diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 58df2746f3..a06b66dab0 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -351,7 +351,7 @@ LLUIImagePtr LLTaskInvFVBridge::getIcon() const { const BOOL item_is_multi = (mFlags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS); - return LLInventoryIcon::getIcon(mAssetType, mInventoryType, FALSE, 0, item_is_multi ); + return LLInventoryIcon::getIcon(mAssetType, mInventoryType, 0, item_is_multi ); } void LLTaskInvFVBridge::openItem() @@ -1239,7 +1239,7 @@ public: LLUIImagePtr LLTaskWearableBridge::getIcon() const { - return LLInventoryIcon::getIcon(mAssetType, mInventoryType, FALSE, mFlags, FALSE ); + return LLInventoryIcon::getIcon(mAssetType, mInventoryType, mFlags, FALSE ); } #if LL_MESH_ENABLED diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index e07d5c064b..1454a2f6af 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -65,6 +65,7 @@ #include "llsaveoutfitcombobtn.h" #include "llscrolllistctrl.h" #include "lltextbox.h" +#include "lltrans.h" #include "lluictrlfactory.h" #include "llsdutil.h" #include "llsidepanelappearance.h" @@ -188,8 +189,8 @@ LLPanelOutfitEdit::LLPanelOutfitEdit() mCOFDragAndDropObserver(NULL), mInitialized(false), mAddWearablesPanel(NULL), - mWearableListMaskCollector(NULL), - mWearableListTypeCollector(NULL) + mFolderViewFilterCmbBox(NULL), + mListViewFilterCmbBox(NULL) { mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(FALSE); @@ -201,12 +202,11 @@ LLPanelOutfitEdit::LLPanelOutfitEdit() observer.addOutfitLockChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this)); observer.addCOFChangedCallback(boost::bind(&LLPanelOutfitEdit::update, this)); - mLookItemTypes.reserve(NUM_LOOK_ITEM_TYPES); - for (U32 i = 0; i < NUM_LOOK_ITEM_TYPES; i++) + mFolderViewItemTypes.reserve(NUM_FOLDER_VIEW_ITEM_TYPES); + for (U32 i = 0; i < NUM_FOLDER_VIEW_ITEM_TYPES; i++) { - mLookItemTypes.push_back(LLLookItemType()); + mFolderViewItemTypes.push_back(LLLookItemType()); } - } @@ -216,17 +216,40 @@ LLPanelOutfitEdit::~LLPanelOutfitEdit() delete mCOFDragAndDropObserver; - delete mWearableListMaskCollector; - delete mWearableListTypeCollector; + while (!mListViewItemTypes.empty()) { + delete mListViewItemTypes.back(); + mListViewItemTypes.pop_back(); + } } BOOL LLPanelOutfitEdit::postBuild() { // gInventory.isInventoryUsable() no longer needs to be tested per Richard's fix for race conditions between inventory and panels - - mLookItemTypes[LIT_ALL] = LLLookItemType(getString("Filter.All"), ALL_ITEMS_MASK); - mLookItemTypes[LIT_WEARABLE] = LLLookItemType(getString("Filter.Clothes/Body"), WEARABLE_MASK); - mLookItemTypes[LIT_ATTACHMENT] = LLLookItemType(getString("Filter.Objects"), ATTACHMENT_MASK); + + mFolderViewItemTypes[FVIT_ALL] = LLLookItemType(getString("Filter.All"), ALL_ITEMS_MASK); + mFolderViewItemTypes[FVIT_WEARABLE] = LLLookItemType(getString("Filter.Clothes/Body"), WEARABLE_MASK); + mFolderViewItemTypes[FVIT_ATTACHMENT] = LLLookItemType(getString("Filter.Objects"), ATTACHMENT_MASK); + + //order is important, see EListViewItemType for order information + mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.All"), new LLFindByMask(ALL_ITEMS_MASK))); + mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Clothing"), new LLIsType(LLAssetType::AT_CLOTHING))); + mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Bodyparts"), new LLIsType(LLAssetType::AT_BODYPART))); + mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Objects"), new LLFindByMask(ATTACHMENT_MASK)));; + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shape"), new LLFindActualWearablesOfType(LLWearableType::WT_SHAPE))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skin"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIN))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("hair"), new LLFindActualWearablesOfType(LLWearableType::WT_HAIR))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("eyes"), new LLFindActualWearablesOfType(LLWearableType::WT_EYES))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shirt"), new LLFindActualWearablesOfType(LLWearableType::WT_SHIRT))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("pants"), new LLFindActualWearablesOfType(LLWearableType::WT_PANTS))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shoes"), new LLFindActualWearablesOfType(LLWearableType::WT_SHOES))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("socks"), new LLFindActualWearablesOfType(LLWearableType::WT_SOCKS))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("jacket"), new LLFindActualWearablesOfType(LLWearableType::WT_JACKET))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("gloves"), new LLFindActualWearablesOfType(LLWearableType::WT_GLOVES))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("undershirt"), new LLFindActualWearablesOfType(LLWearableType::WT_UNDERSHIRT))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("underpants"), new LLFindActualWearablesOfType(LLWearableType::WT_UNDERPANTS))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skirt"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIRT))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("alpha"), new LLFindActualWearablesOfType(LLWearableType::WT_ALPHA))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("tattoo"), new LLFindActualWearablesOfType(LLWearableType::WT_TATTOO))); mCurrentOutfitName = getChild<LLTextBox>("curr_outfit_name"); mStatus = getChild<LLTextBox>("status"); @@ -235,12 +258,13 @@ BOOL LLPanelOutfitEdit::postBuild() mListViewBtn = getChild<LLButton>("list_view_btn"); childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL); - childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredFolderWearablesPanel, this), NULL); - childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredWearablesPanel, this), NULL); + childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesFolderView, this), NULL); + childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL); childSetCommitCallback("wearables_gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL); + childSetCommitCallback("gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL); mCOFWearables = getChild<LLCOFWearables>("cof_wearables_list"); - mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onOutfitItemSelectionChange, this)); + mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::filterWearablesBySelectedItem, this)); mCOFWearables->getCOFCallbacks().mAddWearable = boost::bind(&LLPanelOutfitEdit::onAddWearableClicked, this); mCOFWearables->getCOFCallbacks().mEditWearable = boost::bind(&LLPanelOutfitEdit::onEditWearableClicked, this); @@ -250,7 +274,7 @@ BOOL LLPanelOutfitEdit::postBuild() mAddWearablesPanel = getChild<LLPanel>("add_wearables_panel"); - mInventoryItemsPanel = getChild<LLInventoryPanel>("inventory_items"); + mInventoryItemsPanel = getChild<LLInventoryPanel>("folder_view"); mInventoryItemsPanel->setFilterTypes(ALL_ITEMS_MASK); mInventoryItemsPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); mInventoryItemsPanel->setSelectCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this, _1, _2)); @@ -258,19 +282,29 @@ BOOL LLPanelOutfitEdit::postBuild() mCOFDragAndDropObserver = new LLCOFDragAndDropObserver(mInventoryItemsPanel->getModel()); - LLComboBox* type_filter = getChild<LLComboBox>("filter_wearables_combobox"); - type_filter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onTypeFilterChanged, this, _1)); - type_filter->removeall(); - for (U32 i = 0; i < mLookItemTypes.size(); ++i) + mFolderViewFilterCmbBox = getChild<LLComboBox>("folder_view_filter_combobox"); + mFolderViewFilterCmbBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onFolderViewFilterCommitted, this, _1)); + mFolderViewFilterCmbBox->removeall(); + for (U32 i = 0; i < mFolderViewItemTypes.size(); ++i) { - type_filter->add(mLookItemTypes[i].displayName); + mFolderViewFilterCmbBox->add(mFolderViewItemTypes[i].displayName); } - type_filter->setCurrentByIndex(LIT_ALL); + mFolderViewFilterCmbBox->setCurrentByIndex(FVIT_ALL); + mListViewFilterCmbBox = getChild<LLComboBox>("list_view_filter_combobox"); + mListViewFilterCmbBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onListViewFilterCommitted, this, _1)); + mListViewFilterCmbBox->removeall(); + for (U32 i = 0; i < mListViewItemTypes.size(); ++i) + { + mListViewFilterCmbBox->add(mListViewItemTypes[i]->displayName); + } + mListViewFilterCmbBox->setCurrentByIndex(LVIT_ALL); + mSearchFilter = getChild<LLFilterEditor>("look_item_filter"); mSearchFilter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onSearchEdit, this, _2)); - childSetAction("show_add_wearables_btn", boost::bind(&LLPanelOutfitEdit::toggleAddWearablesPanel, this)); + childSetAction("show_add_wearables_btn", boost::bind(&LLPanelOutfitEdit::onAddMoreButtonClicked, this)); + childSetAction("add_to_outfit_btn", boost::bind(&LLPanelOutfitEdit::onAddToOutfitClicked, this)); mEditWearableBtn = getChild<LLButton>("edit_wearable_btn"); @@ -280,11 +314,8 @@ BOOL LLPanelOutfitEdit::postBuild() childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance())); - mWearableListMaskCollector = new LLFindNonLinksByMask(ALL_ITEMS_MASK); - mWearableListTypeCollector = new LLFindActualWearablesOfType(LLWearableType::WT_NONE); - - mWearableItemsPanel = getChild<LLPanel>("filtered_wearables_panel"); - mWearableItemsList = getChild<LLInventoryItemsList>("filtered_wearables_list"); + mWearablesListViewPanel = getChild<LLPanel>("filtered_wearables_panel"); + mWearableItemsList = getChild<LLInventoryItemsList>("list_view"); mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this)); return TRUE; @@ -297,7 +328,7 @@ void LLPanelOutfitEdit::onOpen(const LLSD& key) { // *TODO: this method is called even panel is not visible to user because its parent layout panel is hidden. // So, we can defer initializing a bit. - mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, mWearableListMaskCollector); + mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, mListViewItemTypes[LVIT_ALL]->collector); mWearableListManager->populateList(); displayCurrentOutfit(); mInitialized = true; @@ -325,13 +356,17 @@ void LLPanelOutfitEdit::showAddWearablesPanel(bool show_add_wearables) childSetValue("show_add_wearables_btn", show_add_wearables); - childSetVisible("filter_wearables_combobox", show_add_wearables); + updateFiltersVisibility(); childSetVisible("filter_button", show_add_wearables); //search filter should be disabled if (!show_add_wearables) { childSetValue("filter_button", false); + + mFolderViewFilterCmbBox->setVisible(false); + mListViewFilterCmbBox->setVisible(false); + showWearablesFilter(); } @@ -353,41 +388,43 @@ void LLPanelOutfitEdit::showWearablesFilter() } } -void LLPanelOutfitEdit::showFilteredWearablesPanel() +void LLPanelOutfitEdit::showWearablesListView() { - if(switchPanels(mInventoryItemsPanel, mWearableItemsPanel)) + if(switchPanels(mInventoryItemsPanel, mWearablesListViewPanel)) { mFolderViewBtn->setToggleState(FALSE); mFolderViewBtn->setImageOverlay(getString("folder_view_off"), mFolderViewBtn->getImageOverlayHAlign()); mListViewBtn->setImageOverlay(getString("list_view_on"), mListViewBtn->getImageOverlayHAlign()); + updateFiltersVisibility(); } mListViewBtn->setToggleState(TRUE); } -void LLPanelOutfitEdit::showFilteredFolderWearablesPanel() +void LLPanelOutfitEdit::showWearablesFolderView() { - if(switchPanels(mWearableItemsPanel, mInventoryItemsPanel)) + if(switchPanels(mWearablesListViewPanel, mInventoryItemsPanel)) { mListViewBtn->setToggleState(FALSE); mListViewBtn->setImageOverlay(getString("list_view_off"), mListViewBtn->getImageOverlayHAlign()); mFolderViewBtn->setImageOverlay(getString("folder_view_on"), mFolderViewBtn->getImageOverlayHAlign()); + updateFiltersVisibility(); } mFolderViewBtn->setToggleState(TRUE); } -void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl) +void LLPanelOutfitEdit::updateFiltersVisibility() { - LLComboBox* type_filter = dynamic_cast<LLComboBox*>(ctrl); - llassert(type_filter); - if (type_filter) - { - U32 curr_filter_type = type_filter->getCurrentIndex(); - mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask); + mListViewFilterCmbBox->setVisible(mWearablesListViewPanel->getVisible()); + mFolderViewFilterCmbBox->setVisible(mInventoryItemsPanel->getVisible()); +} + +void LLPanelOutfitEdit::onFolderViewFilterCommitted(LLUICtrl* ctrl) +{ + S32 curr_filter_type = mFolderViewFilterCmbBox->getCurrentIndex(); + if (curr_filter_type < 0) return; + + mInventoryItemsPanel->setFilterTypes(mFolderViewItemTypes[curr_filter_type].inventoryMask); - mWearableListMaskCollector->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask); - mWearableListManager->setFilterCollector(mWearableListMaskCollector); - } - mSavedFolderState->setApply(TRUE); mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -398,6 +435,14 @@ void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl) LLInventoryModelBackgroundFetch::instance().start(); } +void LLPanelOutfitEdit::onListViewFilterCommitted(LLUICtrl* ctrl) +{ + S32 curr_filter_type = mListViewFilterCmbBox->getCurrentIndex(); + if (curr_filter_type < 0) return; + + mWearableListManager->setFilterCollector(mListViewItemTypes[curr_filter_type]->collector); +} + void LLPanelOutfitEdit::onSearchEdit(const std::string& string) { if (mSearchString != string) @@ -455,7 +500,7 @@ void LLPanelOutfitEdit::onAddToOutfitClicked(void) selected_id = listenerp->getUUID(); } - else if (mWearableItemsPanel->getVisible()) + else if (mWearablesListViewPanel->getVisible()) { selected_id = mWearableItemsList->getSelectedUUID(); } @@ -471,7 +516,7 @@ void LLPanelOutfitEdit::onAddWearableClicked(void) if(item) { - showFilteredWearableItemsList(item->getWearableType()); + showFilteredWearablesListView(item->getWearableType()); } } @@ -481,7 +526,7 @@ void LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id if (item && item->getType() == LLAssetType::AT_BODYPART) { - showFilteredWearableItemsList(item->getWearableType()); + showFilteredWearablesListView(item->getWearableType()); } } @@ -538,24 +583,87 @@ void LLPanelOutfitEdit::onInventorySelectionChange(const std::deque<LLFolderView current_item->addChild(mAddToLookBtn); */ } -void LLPanelOutfitEdit::onOutfitItemSelectionChange(void) -{ - LLUUID item_id = mCOFWearables->getSelectedUUID(); - //*TODO show Edit Wearable Button +void LLPanelOutfitEdit::applyFolderViewFilter(EFolderViewItemType type) +{ + mFolderViewFilterCmbBox->setCurrentByIndex(type); + mFolderViewFilterCmbBox->onCommit(); +} + +void LLPanelOutfitEdit::applyListViewFilter(EListViewItemType type) +{ + mListViewFilterCmbBox->setCurrentByIndex(type); + mListViewFilterCmbBox->onCommit(); +} + +void LLPanelOutfitEdit::filterWearablesBySelectedItem(void) +{ + if (!mAddWearablesPanel->getVisible()) return; + + uuid_vec_t ids; + mCOFWearables->getSelectedUUIDs(ids); - LLViewerInventoryItem* item_to_remove = gInventory.getItem(item_id); - if (!item_to_remove) return; + bool nothing_selected = ids.empty(); + bool one_selected = ids.size() == 1; + bool more_than_one_selected = ids.size() > 1; + bool is_dummy_item = (ids.size() && dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem())); - switch (item_to_remove->getType()) + //resetting selection if no item is selected or than one item is selected + if (nothing_selected || more_than_one_selected) { - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_OBJECT: - default: - break; + if (nothing_selected) + { + showWearablesFolderView(); + applyFolderViewFilter(FVIT_ALL); + } + + if (more_than_one_selected) + { + showWearablesListView(); + applyListViewFilter(LVIT_ALL); + } + + return; + } + + + //filter wearables by a type represented by a dummy item + if (one_selected && is_dummy_item) + { + onAddWearableClicked(); + return; } + + LLViewerInventoryItem* item = gInventory.getItem(ids[0]); + if (!item && ids[0].notNull()) + { + //Inventory misses an item with non-zero id + showWearablesListView(); + applyListViewFilter(LVIT_ALL); + return; + } + + if (one_selected && !is_dummy_item) + { + if (item->isWearableType()) + { + //single clothing or bodypart item is selected + showFilteredWearablesListView(item->getWearableType()); + return; + } + else + { + //attachment is selected + showWearablesListView(); + applyListViewFilter(LVIT_ATTACHMENT); + return; + } + } + } + + void LLPanelOutfitEdit::update() { mCOFWearables->refresh(); @@ -652,6 +760,7 @@ void LLPanelOutfitEdit::updateVerbs() mStatus->setText(outfit_is_dirty ? getString("unsaved_changes") : getString("now_editing")); + updateCurrentOutfitName(); } bool LLPanelOutfitEdit::switchPanels(LLPanel* switch_from_panel, LLPanel* switch_to_panel) @@ -676,12 +785,21 @@ void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button) LLMenuGL::showPopup(clicked_button, mGearMenu, 0, menu_y); } -void LLPanelOutfitEdit::showFilteredWearableItemsList(LLWearableType::EType type) +void LLPanelOutfitEdit::onAddMoreButtonClicked() +{ + toggleAddWearablesPanel(); + filterWearablesBySelectedItem(); +} + +void LLPanelOutfitEdit::showFilteredWearablesListView(LLWearableType::EType type) { - mWearableListTypeCollector->setType(type); - mWearableListManager->setFilterCollector(mWearableListTypeCollector); showAddWearablesPanel(true); - showFilteredWearablesPanel(); + showWearablesListView(); + + //e_list_view_item_type implicitly contains LLWearableType::EType starting from LVIT_SHAPE + applyListViewFilter((EListViewItemType) (LVIT_SHAPE + type)); } + + // EOF diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 24ecf75c18..56c6c6d680 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -42,11 +42,13 @@ #include "llremoteparcelrequest.h" #include "llinventory.h" +#include "llinventoryfunctions.h" #include "llinventoryitemslist.h" #include "llinventorymodel.h" class LLButton; class LLCOFWearables; +class LLComboBox; class LLTextBox; class LLInventoryCategory; class LLOutfitObserver; @@ -68,21 +70,59 @@ class LLPanelOutfitEdit : public LLPanel LOG_CLASS(LLPanelOutfitEdit); public: - // NOTE: initialize mLookItemTypes at the index of any new enum you add in the LLPanelOutfitEdit() constructor - typedef enum e_look_item_type + // NOTE: initialize mFolderViewItemTypes at the index of any new enum you add in the LLPanelOutfitEdit() constructor + typedef enum e_folder_view_item_type { - LIT_ALL = 0, - LIT_WEARABLE, // clothing or shape - LIT_ATTACHMENT, - NUM_LOOK_ITEM_TYPES - } ELookItemType; + FVIT_ALL = 0, + FVIT_WEARABLE, // clothing or shape + FVIT_ATTACHMENT, + NUM_FOLDER_VIEW_ITEM_TYPES + } EFolderViewItemType; + //should reflect order from LLWearableType::EType + typedef enum e_list_view_item_type + { + LVIT_ALL = 0, + LVIT_CLOTHING, + LVIT_BODYPART, + LVIT_ATTACHMENT, + LVIT_SHAPE, + LVIT_SKIN, + LVIT_HAIR, + LVIT_EYES, + LVIT_SHIRT, + LVIT_PANTS, + LVIT_SHOES, + LVIT_SOCKS, + LVIT_JACKET, + LVIT_GLOVES, + LVIT_UNDERSHIRT, + LVIT_UNDERPANTS, + LVIT_SKIRT, + LVIT_ALPHA, + LVIT_TATTOO, + NUM_LIST_VIEW_ITEM_TYPES + } EListViewItemType; + struct LLLookItemType { std::string displayName; U64 inventoryMask; LLLookItemType() : displayName("NONE"), inventoryMask(0) {} LLLookItemType(std::string name, U64 mask) : displayName(name), inventoryMask(mask) {} }; + + struct LLFilterItem { + std::string displayName; + LLInventoryCollectFunctor* collector; + LLFilterItem() : displayName("NONE"), collector(NULL) {} + LLFilterItem(std::string name, LLInventoryCollectFunctor* _collector) : displayName(name), collector(_collector) {} + ~LLFilterItem() { delete collector; } + + //the struct is not supposed to by copied, either way the destructor kills collector + //LLPointer is not used as it requires LLInventoryCollectFunctor to extend LLRefCount what it doesn't do + private: + LLFilterItem(const LLFilterItem& filter_item) {}; + }; LLPanelOutfitEdit(); /*virtual*/ ~LLPanelOutfitEdit(); @@ -94,15 +134,31 @@ public: void toggleAddWearablesPanel(); void showAddWearablesPanel(bool show__add_wearables); + + //following methods operate with "add wearables" panel void showWearablesFilter(); - void showFilteredWearablesPanel(); - void showFilteredFolderWearablesPanel(); + void showWearablesListView(); + void showWearablesFolderView(); - void onTypeFilterChanged(LLUICtrl* ctrl); + void updateFiltersVisibility(); + + void onFolderViewFilterCommitted(LLUICtrl* ctrl); + void onListViewFilterCommitted(LLUICtrl* ctrl); void onSearchEdit(const std::string& string); void onInventorySelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); void onAddToOutfitClicked(void); - void onOutfitItemSelectionChange(void); + + void applyFolderViewFilter(EFolderViewItemType type); + void applyListViewFilter(EListViewItemType type); + + /** + * Filter items in views of Add Wearables Panel and show appropriate view depending on currently selected COF item(s) + * No COF items selected - shows the folder view, reset filter + * 1 COF item selected - shows the list view and filters wearables there by a wearable type of the selected item + * More than 1 COF item selected - shows the list view and filters it by a type of the selected item (attachment or clothing) + */ + void filterWearablesBySelectedItem(void); + void onRemoveFromOutfitClicked(void); void onEditWearableClicked(void); void onAddWearableClicked(void); @@ -132,7 +188,8 @@ public: private: void onGearButtonClick(LLUICtrl* clicked_button); - void showFilteredWearableItemsList(LLWearableType::EType type); + void onAddMoreButtonClicked(); + void showFilteredWearablesListView(LLWearableType::EType type); LLTextBox* mCurrentOutfitName; @@ -145,23 +202,26 @@ private: LLButton* mFolderViewBtn; LLButton* mListViewBtn; LLPanel* mAddWearablesPanel; - - LLFindNonLinksByMask* mWearableListMaskCollector; - LLFindWearablesOfType* mWearableListTypeCollector; + + LLComboBox* mFolderViewFilterCmbBox; + LLComboBox* mListViewFilterCmbBox; LLFilteredWearableListManager* mWearableListManager; LLInventoryItemsList* mWearableItemsList; - LLPanel* mWearableItemsPanel; + LLPanel* mWearablesListViewPanel; LLCOFDragAndDropObserver* mCOFDragAndDropObserver; - std::vector<LLLookItemType> mLookItemTypes; + std::vector<LLLookItemType> mFolderViewItemTypes; + std::vector<LLFilterItem*> mListViewItemTypes; LLCOFWearables* mCOFWearables; LLMenuGL* mGearMenu; bool mInitialized; std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn; + + }; #endif // LL_LLPANELOUTFITEDIT_H diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 8b451c156c..1157c40b39 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -91,6 +91,7 @@ public: registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2)); enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2)); + enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenu::onVisible, this, _2)); mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>( "menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); @@ -99,6 +100,28 @@ public: LLMenuGL* getMenu() { return mMenu; } + void show(LLView* spawning_view) + { + if (!mMenu) return; + + updateItemsVisibility(); + mMenu->buildDrawLabels(); + mMenu->updateParent(LLMenuGL::sMenuContainer); + S32 menu_x = 0; + S32 menu_y = spawning_view->getRect().getHeight() + mMenu->getRect().getHeight(); + LLMenuGL::showPopup(spawning_view, mMenu, menu_x, menu_y); + } + + void updateItemsVisibility() + { + if (!mMenu) return; + + bool have_selection = getSelectedOutfitID().notNull(); + mMenu->setItemVisible("sepatator1", have_selection); + mMenu->setItemVisible("sepatator2", have_selection); + mMenu->arrangeAndClear(); // update menu height + } + private: const LLUUID& getSelectedOutfitID() { @@ -169,6 +192,31 @@ private: bool onEnable(LLSD::String param) { const LLUUID& selected_outfit_id = getSelectedOutfitID(); + if (selected_outfit_id.isNull()) // no selection or invalid outfit selected + { + return false; + } + + if ("rename" == param) + { + return get_is_category_renameable(&gInventory, selected_outfit_id); + } + else if ("delete" == param) + { + return LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit_id); + } + + return true; + } + + bool onVisible(LLSD::String param) + { + const LLUUID& selected_outfit_id = getSelectedOutfitID(); + if (selected_outfit_id.isNull()) // no selection or invalid outfit selected + { + return false; + } + bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id; if ("wear" == param) @@ -179,14 +227,6 @@ private: { return is_worn; } - else if ("rename" == param) - { - return get_is_category_renameable(&gInventory, selected_outfit_id); - } - else if ("delete" == param) - { - return LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit_id); - } return true; } @@ -523,28 +563,21 @@ void LLPanelOutfitsInventory::updateListCommands() { bool trash_enabled = isActionEnabled("delete"); bool wear_enabled = isActionEnabled("wear"); + bool wear_visible = !isCOFPanelActive(); bool make_outfit_enabled = isActionEnabled("save_outfit"); mListCommands->childSetEnabled("trash_btn", trash_enabled); mListCommands->childSetEnabled("wear_btn", wear_enabled); - mListCommands->childSetVisible("wear_btn", wear_enabled); + mListCommands->childSetVisible("wear_btn", wear_visible); mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled); } void LLPanelOutfitsInventory::showGearMenu() { - LLMenuGL* menu = mGearMenu ? mGearMenu->getMenu() : NULL; - if (menu) - { - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLView* spawning_view = getChild<LLView>("options_gear_btn"); - S32 menu_x, menu_y; - //show menu in co-ordinates of panel - spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this); - menu_y += menu->getRect().getHeight(); - LLMenuGL::showPopup(this, menu, menu_x, menu_y); - } + if (!mGearMenu) return; + + LLView* spawning_view = getChild<LLView>("options_gear_btn"); + mGearMenu->show(spawning_view); } void LLPanelOutfitsInventory::onTrashButtonClick() @@ -555,11 +588,25 @@ void LLPanelOutfitsInventory::onTrashButtonClick() void LLPanelOutfitsInventory::onClipboardAction(const LLSD& userdata) { std::string command_name = userdata.asString(); - // TODO: add handling "My Outfits" tab. if (isCOFPanelActive()) { getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name); } + else // "My Outfits" tab active + { + if (command_name == "delete") + { + const LLUUID& selected_outfit_id = mMyOutfitsPanel->getSelectedOutfitUUID(); + if (selected_outfit_id.notNull()) + { + remove_category(&gInventory, selected_outfit_id); + } + } + else + { + llwarns << "Unrecognized action" << llendl; + } + } updateListCommands(); updateVerbs(); } @@ -614,7 +661,6 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) { BOOL can_delete = FALSE; - // TODO: add handling "My Outfits" tab. if (isCOFPanelActive()) { LLFolderView* root = getActivePanel()->getRootFolder(); @@ -630,10 +676,15 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) LLFolderViewItem *item = root->getItemByID(item_id); can_delete &= item->getListener()->isItemRemovable(); } - return can_delete; } } - return FALSE; + else // "My Outfits" tab active + { + const LLUUID& selected_outfit = mMyOutfitsPanel->getSelectedOutfitUUID(); + can_delete = LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit); + } + + return can_delete; } if (command_name == "remove_link") { @@ -668,6 +719,7 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) { return FALSE; } + return hasItemsSelected(); } if (command_name == "save_outfit") { @@ -690,7 +742,6 @@ bool LLPanelOutfitsInventory::hasItemsSelected() { bool has_items_selected = false; - // TODO: add handling "My Outfits" tab. if (isCOFPanelActive()) { LLFolderView* root = getActivePanel()->getRootFolder(); @@ -700,6 +751,10 @@ bool LLPanelOutfitsInventory::hasItemsSelected() has_items_selected = (selection_set.size() > 0); } } + else // My Outfits Tab is active + { + has_items_selected = mMyOutfitsPanel->getSelectedOutfitUUID().notNull(); + } return has_items_selected; } @@ -730,6 +785,7 @@ void LLPanelOutfitsInventory::initTabPanels() mCurrentOutfitPanel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onTabSelectionChange, this, mCurrentOutfitPanel, _1, _2)); mMyOutfitsPanel = getChild<LLOutfitsList>(OUTFITS_TAB_NAME); + mMyOutfitsPanel->addSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); mAppearanceTabs = getChild<LLTabContainer>("appearance_tabs"); mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this)); diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index c8abcc83c4..1f979b0ef1 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -84,7 +84,9 @@ LLPanelPlaceProfile::LLPanelPlaceProfile() // virtual LLPanelPlaceProfile::~LLPanelPlaceProfile() -{} +{ + gIdleCallbacks.deleteFunction(&LLPanelPlaceProfile::updateYouAreHereBanner, this); +} // virtual BOOL LLPanelPlaceProfile::postBuild() diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index e8b6c6bfe5..494cba8c6f 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -564,6 +564,7 @@ void LLTeleportHistoryPanel::updateVerbs() { mTeleportBtn->setEnabled(false); mShowProfile->setEnabled(false); + mShowOnMapBtn->setEnabled(false); return; } @@ -571,7 +572,7 @@ void LLTeleportHistoryPanel::updateVerbs() mTeleportBtn->setEnabled(NULL != itemp); mShowProfile->setEnabled(NULL != itemp); - mShowOnMapBtn->setEnabled(true); + mShowOnMapBtn->setEnabled(NULL != itemp); } void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date) diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index a27afeab7c..8fe78a0f81 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -52,6 +52,18 @@ static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; +// helper function to update AvatarList Item's indicator in the voice participant list +static void update_speaker_indicator(const LLAvatarList* const avatar_list, const LLUUID& avatar_uuid, bool is_muted) +{ + LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(avatar_list->getItemByValue(avatar_uuid)); + if (item) + { + LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator"); + indicator->setIsMuted(is_muted); + } +} + + // See EXT-4301. /** * class LLAvalineUpdater - observe the list of voice participants in session and check @@ -354,6 +366,20 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) } } } + + // update voice mute state of all items. See EXT-7235 + LLSpeakerMgr::speaker_list_t speaker_list; + + // Use also participants which are not in voice session now (the second arg is TRUE). + // They can already have mModeratorMutedVoice set from the previous voice session + // and LLSpeakerVoiceModerationEvent will not be sent when speaker manager is updated next time. + mSpeakerMgr->getSpeakerList(&speaker_list, TRUE); + for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) + { + const LLPointer<LLSpeaker>& speakerp = *it; + + update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); + } } } @@ -506,12 +532,7 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event // update UI on confirmation of moderator mutes if (event->getValue().asString() == "voice") { - LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mAvatarList->getItemByValue(speakerp->mID)); - if (item) - { - LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator"); - indicator->setIsMuted(speakerp->mModeratorMutedVoice); - } + update_speaker_indicator(mAvatarList, speakerp->mID, speakerp->mModeratorMutedVoice); } return true; } diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index e23643da0b..445bde1206 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -352,12 +352,12 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we if (visible) { - mEditWearable->setWearable(wearable); - mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") ) { gAgentCamera.changeCameraToCustomizeAvatar(); } + mEditWearable->setWearable(wearable); + mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency } else { diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index e51e6363dd..9bfcceab2f 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -199,7 +199,6 @@ #include "llstartuplistener.h" #if LL_WINDOWS -#include "llwindebug.h" #include "lldxhardware.h" #endif @@ -781,9 +780,6 @@ bool idle_startup() gViewerWindow->getWindow()->show(); display_startup(); - //DEV-10530. do cleanup. remove at some later date. jan-2009 - LLFloaterPreference::cleanupBadSetting(); - // DEV-16927. The following code removes errant keystrokes that happen while the window is being // first made visible. #ifdef _WIN32 diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 6c6eda2e68..db1f4dc4cb 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -172,6 +172,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal params.tab_stop(false); params.wrap(true); params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); + params.allow_scroll(true); LLTextBox * msg_box = LLUICtrlFactory::create<LLTextBox> (params); // Compute max allowable height for the dialog text, so we can allocate @@ -180,9 +181,16 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal gFloaterView->getRect().getHeight() - LINE_HEIGHT // title bar - 3*VPAD - BTN_HEIGHT; + // reshape to calculate real text width and height msg_box->reshape( MAX_ALLOWED_MSG_WIDTH, max_allowed_msg_height ); msg_box->setValue(msg); - msg_box->reshapeToFitText(); + + S32 pixel_width = msg_box->getTextPixelWidth(); + S32 pixel_height = msg_box->getTextPixelHeight(); + + // We should use some space to prevent set textbox's scroller visible when it is unnecessary. + msg_box->reshape( llmin(MAX_ALLOWED_MSG_WIDTH,pixel_width + 2 * msg_box->getHPad() + HPAD), + llmin(max_allowed_msg_height,pixel_height + 2 * msg_box->getVPad()) ) ; const LLRect& text_rect = msg_box->getRect(); S32 dialog_width = llmax( btn_total_width, text_rect.getWidth() ) + 2 * HPAD; diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index 033d35d80a..56b5d7467c 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -43,13 +43,16 @@ struct ViewerFolderEntry : public LLDictionaryEntry { // Constructor for non-ensembles ViewerFolderEntry(const std::string &new_category_name, // default name when creating a new category of this type - const std::string &icon_name, // name of the folder icon - BOOL is_quiet // folder doesn't need a UI update when changed + const std::string &icon_name_open, // name of the folder icon + const std::string &icon_name_closed, + BOOL is_quiet, // folder doesn't need a UI update when changed + const std::string &dictionary_name = empty_string // no reverse lookup needed on non-ensembles, so in most cases just leave this blank ) : - LLDictionaryEntry(empty_string), // no reverse lookup needed on non-ensembles, so just leave this blank - mIconName(icon_name), + LLDictionaryEntry(dictionary_name), mNewCategoryName(new_category_name), + mIconNameOpen(icon_name_open), + mIconNameClosed(icon_name_closed), mIsQuiet(is_quiet) { mAllowedNames.clear(); @@ -63,7 +66,11 @@ struct ViewerFolderEntry : public LLDictionaryEntry ) : LLDictionaryEntry(xui_name), - mIconName(icon_name), + /* Just use default icons until we actually support ensembles + mIconNameOpen(icon_name), + mIconNameClosed(icon_name), + */ + mIconNameOpen("Inv_FolderOpen"), mIconNameClosed("Inv_FolderClosed"), mNewCategoryName(new_category_name), mIsQuiet(FALSE) { @@ -84,7 +91,8 @@ struct ViewerFolderEntry : public LLDictionaryEntry } return false; } - const std::string mIconName; + const std::string mIconNameOpen; + const std::string mIconNameClosed; const std::string mNewCategoryName; typedef std::vector<std::string> name_vec_t; name_vec_t mAllowedNames; @@ -104,31 +112,31 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() { initEnsemblesFromFile(); - // NEW CATEGORY NAME FOLDER ICON NAME QUIET? - // |-------------------------|-------------------------------|-----------| - addEntry(LLFolderType::FT_TEXTURE, new ViewerFolderEntry("Textures", "inv_folder_texture.tga", FALSE)); - addEntry(LLFolderType::FT_SOUND, new ViewerFolderEntry("Sounds", "inv_folder_sound.tga", FALSE)); - addEntry(LLFolderType::FT_CALLINGCARD, new ViewerFolderEntry("Calling Cards", "inv_folder_callingcard.tga", FALSE)); - addEntry(LLFolderType::FT_LANDMARK, new ViewerFolderEntry("Landmarks", "inv_folder_landmark.tga", FALSE)); - addEntry(LLFolderType::FT_CLOTHING, new ViewerFolderEntry("Clothing", "inv_folder_clothing.tga", FALSE)); - addEntry(LLFolderType::FT_OBJECT, new ViewerFolderEntry("Objects", "inv_folder_object.tga", FALSE)); - addEntry(LLFolderType::FT_NOTECARD, new ViewerFolderEntry("Notecards", "inv_folder_notecard.tga", FALSE)); - addEntry(LLFolderType::FT_ROOT_INVENTORY, new ViewerFolderEntry("My Inventory", "", FALSE)); - addEntry(LLFolderType::FT_LSL_TEXT, new ViewerFolderEntry("Scripts", "inv_folder_script.tga", FALSE)); - addEntry(LLFolderType::FT_BODYPART, new ViewerFolderEntry("Body Parts", "inv_folder_bodypart.tga", FALSE)); - addEntry(LLFolderType::FT_TRASH, new ViewerFolderEntry("Trash", "inv_folder_trash.tga", TRUE)); - addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new ViewerFolderEntry("Photo Album", "inv_folder_snapshot.tga", FALSE)); - addEntry(LLFolderType::FT_LOST_AND_FOUND, new ViewerFolderEntry("Lost And Found", "inv_folder_lostandfound.tga", TRUE)); - addEntry(LLFolderType::FT_ANIMATION, new ViewerFolderEntry("Animations", "inv_folder_animation.tga", FALSE)); - addEntry(LLFolderType::FT_GESTURE, new ViewerFolderEntry("Gestures", "inv_folder_gesture.tga", FALSE)); - addEntry(LLFolderType::FT_FAVORITE, new ViewerFolderEntry("Favorites", "inv_folder_plain_closed.tga", FALSE)); + // NEW CATEGORY NAME FOLDER OPEN FOLDER CLOSED QUIET? + // |-------------------------|-----------------------|----------------------|-----------| + addEntry(LLFolderType::FT_TEXTURE, new ViewerFolderEntry("Textures", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_SOUND, new ViewerFolderEntry("Sounds", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_CALLINGCARD, new ViewerFolderEntry("Calling Cards", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_LANDMARK, new ViewerFolderEntry("Landmarks", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_CLOTHING, new ViewerFolderEntry("Clothing", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_OBJECT, new ViewerFolderEntry("Objects", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_NOTECARD, new ViewerFolderEntry("Notecards", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_ROOT_INVENTORY, new ViewerFolderEntry("My Inventory", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_LSL_TEXT, new ViewerFolderEntry("Scripts", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_BODYPART, new ViewerFolderEntry("Body Parts", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_TRASH, new ViewerFolderEntry("Trash", "Inv_TrashOpen", "Inv_TrashClosed", TRUE)); + addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new ViewerFolderEntry("Photo Album", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_LOST_AND_FOUND, new ViewerFolderEntry("Lost And Found", "Inv_LostOpen", "Inv_LostClosed", TRUE)); + addEntry(LLFolderType::FT_ANIMATION, new ViewerFolderEntry("Animations", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_GESTURE, new ViewerFolderEntry("Gestures", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_FAVORITE, new ViewerFolderEntry("Favorites", "Inv_SysOpen", "Inv_SysClosed", FALSE)); - addEntry(LLFolderType::FT_CURRENT_OUTFIT, new ViewerFolderEntry("Current Outfit", "inv_folder_current_outfit.tga",TRUE)); - addEntry(LLFolderType::FT_OUTFIT, new ViewerFolderEntry("New Outfit", "inv_folder_outfit.tga", TRUE)); - addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "inv_folder_my_outfits.tga", TRUE)); - addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "inv_folder_inbox.tga", FALSE)); + addEntry(LLFolderType::FT_CURRENT_OUTFIT, new ViewerFolderEntry("Current Outfit", "Inv_SysOpen", "Inv_SysClosed", TRUE)); + addEntry(LLFolderType::FT_OUTFIT, new ViewerFolderEntry("New Outfit", "Inv_LookFolderOpen", "Inv_LookFolderClosed", TRUE)); + addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "Inv_SysOpen", "Inv_SysClosed", TRUE)); + addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "Inv_SysOpen", "Inv_SysClosed", FALSE)); - addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "inv_folder_plain_closed.tga", FALSE)); + addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, "default")); } bool LLViewerFolderDictionary::initEnsemblesFromFile() @@ -213,12 +221,15 @@ LLFolderType::EType LLViewerFolderType::lookupTypeFromXUIName(const std::string return LLViewerFolderDictionary::getInstance()->lookup(name); } -const std::string &LLViewerFolderType::lookupIconName(LLFolderType::EType folder_type) +const std::string &LLViewerFolderType::lookupIconName(LLFolderType::EType folder_type, BOOL is_open) { const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type); if (entry) { - return entry->mIconName; + if (is_open) + return entry->mIconNameOpen; + else + return entry->mIconNameClosed; } return badLookup(); } diff --git a/indra/newview/llviewerfoldertype.h b/indra/newview/llviewerfoldertype.h index dd9360da90..3744ac20f8 100644 --- a/indra/newview/llviewerfoldertype.h +++ b/indra/newview/llviewerfoldertype.h @@ -44,7 +44,7 @@ public: static const std::string& lookupXUIName(EType folder_type); // name used by the UI static LLFolderType::EType lookupTypeFromXUIName(const std::string& name); - static const std::string& lookupIconName(EType folder_type); // folder icon name + static const std::string& lookupIconName(EType folder_type, BOOL is_open = FALSE); // folder icon name static BOOL lookupIsQuietType(EType folder_type); // folder doesn't require UI update when changes have occured static const std::string& lookupNewCategoryName(EType folder_type); // default name when creating new category static LLFolderType::EType lookupTypeFromNewCategoryName(const std::string& name); // default name when creating new category diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index abac3d26bf..f9f5bed0a5 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -109,10 +109,6 @@ #include <boost/algorithm/string/split.hpp> // #include <boost/regex.hpp> -#if LL_WINDOWS // For Windows specific error handler -#include "llwindebug.h" // For the invalid message handler -#endif - #include "llnotificationmanager.h" // #if LL_MSVC @@ -2063,7 +2059,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // initiated by the other party) then... std::string my_name; LLAgentUI::buildFullname(my_name); - std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2"); + std::string response = gSavedPerAccountSettings.getString("BusyModeResponse"); pack_instant_message( gMessageSystem, gAgent.getID(), @@ -2736,7 +2732,7 @@ void busy_message (LLMessageSystem* msg, LLUUID from_id) { std::string my_name; LLAgentUI::buildFullname(my_name); - std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2"); + std::string response = gSavedPerAccountSettings.getString("BusyModeResponse"); pack_instant_message( gMessageSystem, gAgent.getID(), diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 9f559331b0..5e5b0afab6 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1641,6 +1641,9 @@ void LLViewerWindow::initBase() gDebugView->init(); gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view"); + // Initialize busy response message when logged in + LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initBusyResponse)); + // Add the progress bar view (startup view), which overrides everything mProgressView = getRootView()->getChild<LLProgressView>("progress_view"); setShowProgress(FALSE); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 39649f0370..4dc9edb247 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -402,19 +402,16 @@ void LLVivoxVoiceClient::init(LLPumpIO *pump) void LLVivoxVoiceClient::terminate() { - -// leaveAudioSession(); - logout(); - // As of SDK version 4885, this should no longer be necessary. It will linger after the socket close if it needs to. - // ms_sleep(2000); - connectorShutdown(); - closeSocket(); // Need to do this now -- bad things happen if the destructor does it later. - - // This will do unpleasant things on windows. -// killGateway(); - - - + if(mConnected) + { + logout(); + connectorShutdown(); + closeSocket(); // Need to do this now -- bad things happen if the destructor does it later. + } + else + { + killGateway(); + } } const LLVoiceVersionInfo& LLVivoxVoiceClient::getVersion() diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 6c410cf7a5..f86838194e 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -38,7 +38,6 @@ #include "llagentwearables.h" #include "llappearancemgr.h" #include "llinventoryfunctions.h" -#include "llinventorymodel.h" #include "llmenugl.h" // for LLContextMenu #include "lltransutil.h" #include "llviewerattachmenu.h" @@ -89,8 +88,6 @@ void LLPanelWearableListItem::onMouseLeave(S32 x, S32 y, MASK mask) LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item) : LLPanelInventoryListItemBase(item) { - // icons should not be shown for this type of items (EXT-7511) - mForceNoLinksOnIcons = true; } ////////////////////////////////////////////////////////////////////////// @@ -129,6 +126,19 @@ BOOL LLPanelWearableOutfitItem::handleDoubleClick(S32 x, S32 y, MASK mask) return LLUICtrl::handleDoubleClick(x, y, mask); } +// virtual +void LLPanelWearableOutfitItem::updateItem(const std::string& name) +{ + std::string search_label = name; + + if (mItem && get_is_item_worn(mItem->getUUID())) + { + search_label += LLTrans::getString("worn"); + } + + LLPanelInventoryListItemBase::updateItem(search_label); +} + LLPanelWearableOutfitItem::LLPanelWearableOutfitItem(LLViewerInventoryItem* item) : LLPanelInventoryListItemBase(item) { @@ -295,22 +305,16 @@ LLPanelDummyClothingListItem* LLPanelDummyClothingListItem::create(LLWearableTyp return list_item; } -void LLPanelDummyClothingListItem::updateItem() -{ - std::string title = wearableTypeToString(mWearableType); - setTitle(title, LLStringUtil::null); -} - BOOL LLPanelDummyClothingListItem::postBuild() { LLIconCtrl* icon = getChild<LLIconCtrl>("item_icon"); setIconCtrl(icon); setTitleCtrl(getChild<LLTextBox>("item_name")); - addWidgetToRightSide("btn_add"); + addWidgetToRightSide("btn_add_panel"); - setIconImage(LLInventoryIcon::getIcon(LLAssetType::AT_CLOTHING, LLInventoryType::IT_NONE, FALSE, mWearableType, FALSE)); - updateItem(); + setIconImage(LLInventoryIcon::getIcon(LLAssetType::AT_CLOTHING, LLInventoryType::IT_NONE, mWearableType, FALSE)); + updateItem(wearableTypeToString(mWearableType)); // Make it look loke clothing item - reserve space for 'delete' button setLeftWidgetsWidth(icon->getRect().mLeft); @@ -455,15 +459,17 @@ static const LLWearableItemTypeNameComparator WEARABLE_TYPE_NAME_COMPARATOR; static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_items_list"); LLWearableItemsList::Params::Params() -: use_internal_context_menu("use_internal_context_menu", true) +: standalone("standalone", true) {} LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) : LLInventoryItemsList(p) { setComparator(&WEARABLE_TYPE_NAME_COMPARATOR); - if (p.use_internal_context_menu) + mIsStandalone = p.standalone; + if (mIsStandalone) { + // Use built-in context menu. setRightMouseDownCallback(boost::bind(&LLWearableItemsList::onRightClick, this, _2, _3)); } } @@ -510,6 +516,37 @@ void LLWearableItemsList::updateList(const LLUUID& category_id) refreshList(item_array); } +void LLWearableItemsList::updateChangedItems(const LLInventoryModel::changed_items_t& changed_items_uuids) +{ + typedef std::vector<LLPanel*> item_panel_list_t; + + item_panel_list_t items; + getItems(items); + + for (item_panel_list_t::iterator items_iter = items.begin(); + items_iter != items.end(); + ++items_iter) + { + LLPanelInventoryListItemBase* item = dynamic_cast<LLPanelInventoryListItemBase*>(*items_iter); + if (!item) continue; + + LLViewerInventoryItem* inv_item = item->getItem(); + if (!inv_item) continue; + + LLUUID linked_uuid = inv_item->getLinkedUUID(); + + for (LLInventoryModel::changed_items_t::const_iterator iter = changed_items_uuids.begin(); + iter != changed_items_uuids.end(); + ++iter) + { + if (linked_uuid == *iter) + { + item->setNeedsRefresh(true); + } + } + } +} + void LLWearableItemsList::onRightClick(S32 x, S32 y) { uuid_vec_t selected_uuids; @@ -527,6 +564,18 @@ void LLWearableItemsList::onRightClick(S32 x, S32 y) /// ContextMenu ////////////////////////////////////////////////////////////////////////// +LLWearableItemsList::ContextMenu::ContextMenu() +: mParent(NULL) +{ +} + +void LLWearableItemsList::ContextMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y) +{ + mParent = dynamic_cast<LLWearableItemsList*>(spawning_view); + LLListContextMenu::show(spawning_view, uuids, x, y); + mParent = NULL; // to avoid dereferencing an invalid pointer +} + // virtual LLContextMenu* LLWearableItemsList::ContextMenu::createMenu() { @@ -614,17 +663,21 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu } } // for + bool standalone = mParent ? mParent->isStandalone() : false; + // *TODO: eliminate multiple traversals over the menu items + setMenuItemVisible(menu, "wear_add", mask == MASK_CLOTHING && n_worn == 0); setMenuItemVisible(menu, "wear", n_worn == 0); - setMenuItemVisible(menu, "edit", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1); - setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1); + setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART)); + setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1 && n_items == 1); setMenuItemVisible(menu, "create_new", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1); + setMenuItemVisible(menu, "show_original", !standalone); setMenuItemEnabled(menu, "show_original", n_items == 1 && n_links == n_items); setMenuItemVisible(menu, "take_off", mask == MASK_CLOTHING && n_worn == n_items); setMenuItemVisible(menu, "detach", mask == MASK_ATTACHMENT && n_worn == n_items); setMenuItemVisible(menu, "take_off_or_detach", mask == (MASK_ATTACHMENT|MASK_CLOTHING)); setMenuItemEnabled(menu, "take_off_or_detach", n_worn == n_items); - setMenuItemVisible(menu, "object_profile", mask & (MASK_ATTACHMENT|MASK_CLOTHING)); + setMenuItemVisible(menu, "object_profile", !standalone); setMenuItemEnabled(menu, "object_profile", n_items == 1); // Populate or hide the "Attach to..." / "Attach to HUD..." submenus. diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index f03336186c..2f95c733aa 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -56,13 +56,13 @@ class LLPanelWearableListItem : public LLPanelInventoryListItemBase public: /** - * Shows buttons when mouse is over - */ + * Shows buttons when mouse is over + */ /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); /** - * Hides buttons when mouse is out - */ + * Hides buttons when mouse is out + */ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); protected: @@ -84,11 +84,16 @@ public: static LLPanelWearableOutfitItem* create(LLViewerInventoryItem* item); /** - * Puts item on if it is not worn by agent - * otherwise takes it off on double click. - */ + * Puts item on if it is not worn by agent + * otherwise takes it off on double click. + */ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + /** + * Updates item name and (worn) suffix. + */ + /*virtual*/ void updateItem(const std::string& name); + protected: LLPanelWearableOutfitItem(LLViewerInventoryItem* item); @@ -198,7 +203,6 @@ class LLPanelDummyClothingListItem : public LLPanelWearableListItem public: static LLPanelDummyClothingListItem* create(LLWearableType::EType w_type); - /*virtual*/ void updateItem(); /*virtual*/ BOOL postBuild(); LLWearableType::EType getWearableType() const; @@ -325,6 +329,10 @@ public: */ class ContextMenu : public LLListContextMenu, public LLSingleton<ContextMenu> { + public: + ContextMenu(); + /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); + protected: enum { MASK_CLOTHING = 0x01, @@ -340,11 +348,13 @@ public: static void setMenuItemEnabled(LLContextMenu* menu, const std::string& name, bool val); static void updateMask(U32& mask, LLAssetType::EType at); static void createNewWearable(const LLUUID& item_id); + + LLWearableItemsList* mParent; }; struct Params : public LLInitParam::Block<Params, LLInventoryItemsList::Params> { - Optional<bool> use_internal_context_menu; + Optional<bool> standalone; Params(); }; @@ -355,11 +365,21 @@ public: void updateList(const LLUUID& category_id); + /** + * Update items that match UUIDs from changed_items_uuids + * or links that point at such items. + */ + void updateChangedItems(const LLInventoryModel::changed_items_t& changed_items_uuids); + + bool isStandalone() const { return mIsStandalone; } + protected: friend class LLUICtrlFactory; LLWearableItemsList(const LLWearableItemsList::Params& p); void onRightClick(S32 x, S32 y); + + bool mIsStandalone; }; #endif //LL_LLWEARABLEITEMSLIST_H diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp deleted file mode 100644 index 59bc9dc62b..0000000000 --- a/indra/newview/llwindebug.cpp +++ /dev/null @@ -1,912 +0,0 @@ -/** - * @file llwindebug.cpp - * @brief Windows debugging functions - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include <tchar.h> -#include <tlhelp32.h> -#include "llwindebug.h" -#include "llviewercontrol.h" -#include "lldir.h" -#include "llsd.h" -#include "llsdserialize.h" - -#pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union -#pragma warning(disable: 4100) //unreferenced formal parameter - - -/* -LLSD Block for Windows Dump Information -<llsd> - <map> - <key>Platform</key> - <string></string> - <key>Process</key> - <string></string> - <key>Module</key> - <string></string> - <key>DateModified</key> - <string></string> - <key>ExceptionCode</key> - <string></string> - <key>ExceptionRead/WriteAddress</key> - <string></string> - <key>Instruction</key> - <string></string> - <key>Registers</key> - <map> - <!-- Continued for all registers --> - <key>EIP</key> - <string>...</string> - <!-- ... --> - </map> - <key>Call Stack</key> - <array> - <!-- One map per stack frame --> - <map> - <key>ModuleName</key> - <string></string> - <key>ModuleBaseAddress</key> - <string></string> - <key>ModuleOffsetAddress</key> - <string></string> - <key>Parameters</key> - <array> - <string></string> - </array> - </map> - <!-- ... --> - </array> - </map> -</llsd> - -*/ - - -extern void (*gCrashCallback)(void); - -// based on dbghelp.h -typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam - ); - -MINIDUMPWRITEDUMP f_mdwp = NULL; - -#undef UNICODE - -static LPTOP_LEVEL_EXCEPTION_FILTER gFilterFunc = NULL; - -HMODULE hDbgHelp; - -// Tool Help functions. -typedef HANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); -typedef BOOL (WINAPI * MODULE32_FIRST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); -typedef BOOL (WINAPI * MODULE32_NEST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); - -CREATE_TOOL_HELP32_SNAPSHOT CreateToolhelp32Snapshot_; -MODULE32_FIRST Module32First_; -MODULE32_NEST Module32Next_; - -#define DUMP_SIZE_MAX 8000 //max size of our dump -#define CALL_TRACE_MAX ((DUMP_SIZE_MAX - 2000) / (MAX_PATH + 40)) //max number of traced calls -#define NL L"\r\n" //new line - - -typedef struct STACK -{ - STACK * Ebp; - PBYTE Ret_Addr; - DWORD Param[0]; -} STACK, * PSTACK; - -BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr); -void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, - const CONTEXT* context_record, - LLSD& info); - -void printError( CHAR* msg ) -{ - DWORD eNum; - TCHAR sysMsg[256]; - TCHAR* p; - - eNum = GetLastError( ); - FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, eNum, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - sysMsg, 256, NULL ); - - // Trim the end of the line and terminate it with a null - p = sysMsg; - while( ( *p > 31 ) || ( *p == 9 ) ) - ++p; - do { *p-- = 0; } while( ( p >= sysMsg ) && - ( ( *p == '.' ) || ( *p < 33 ) ) ); - - // Display the message - printf( "\n WARNING: %s failed with error %d (%s)", msg, eNum, sysMsg ); -} - -BOOL GetProcessThreadIDs(DWORD process_id, std::vector<DWORD>& thread_ids) -{ - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); - if( hThreadSnap == INVALID_HANDLE_VALUE ) - return( FALSE ); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32 ); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if( !Thread32First( hThreadSnap, &te32 ) ) - { - printError( "Thread32First" ); // Show cause of failure - CloseHandle( hThreadSnap ); // Must clean up the snapshot object! - return( FALSE ); - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if( te32.th32OwnerProcessID == process_id ) - { - thread_ids.push_back(te32.th32ThreadID); - } - } while( Thread32Next(hThreadSnap, &te32 ) ); - -// Don't forget to clean up the snapshot object. - CloseHandle( hThreadSnap ); - return( TRUE ); -} - -BOOL GetThreadCallStack(DWORD thread_id, LLSD& info) -{ - if(GetCurrentThreadId() == thread_id) - { - // Early exit for the current thread. - // Suspending the current thread would be a bad idea. - // Plus you can't retrieve a valid current thread context. - return false; - } - - HANDLE thread_handle = INVALID_HANDLE_VALUE; - thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id); - if(INVALID_HANDLE_VALUE == thread_handle) - { - return FALSE; - } - - BOOL result = false; - if(-1 != SuspendThread(thread_handle)) - { - CONTEXT context_struct; - context_struct.ContextFlags = CONTEXT_FULL; - if(GetThreadContext(thread_handle, &context_struct)) - { - Get_Call_Stack(NULL, &context_struct, info); - result = true; - } - ResumeThread(thread_handle); - } - else - { - // Couldn't suspend thread. - } - - CloseHandle(thread_handle); - return result; -} - - -//Windows Call Stack Construction idea from -//http://www.codeproject.com/tools/minidump.asp - -//**************************************************************************************** -BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr) -//**************************************************************************************** -// Find module by Ret_Addr (address in the module). -// Return Module_Name (full path) and Module_Addr (start address). -// Return TRUE if found. -{ - MODULEENTRY32 M = {sizeof(M)}; - HANDLE hSnapshot; - - bool found = false; - - if (CreateToolhelp32Snapshot_) - { - hSnapshot = CreateToolhelp32Snapshot_(TH32CS_SNAPMODULE, 0); - - if ((hSnapshot != INVALID_HANDLE_VALUE) && - Module32First_(hSnapshot, &M)) - { - do - { - if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize) - { - lstrcpyn(Module_Name, M.szExePath, MAX_PATH); - Module_Addr = M.modBaseAddr; - found = true; - break; - } - } while (Module32Next_(hSnapshot, &M)); - } - - CloseHandle(hSnapshot); - } - - return found; -} //Get_Module_By_Ret_Addr - -bool has_valid_call_before(PDWORD cur_stack_loc) -{ - PBYTE p_first_byte = (PBYTE)(*cur_stack_loc - 1); - PBYTE p_second_byte = (PBYTE)(*cur_stack_loc -2); - PBYTE p_fifth_byte = (PBYTE)(*cur_stack_loc - 5); - PBYTE p_sixth_byte = (PBYTE)(*cur_stack_loc - 6); - - // make sure we can read it - if(IsBadReadPtr(p_sixth_byte, 6 * sizeof(BYTE))) - { - return false; - } - - // check for 9a + 4 bytes - if(*p_fifth_byte == 0x9A) - { - return true; - } - - // Check for E8 + 4 bytes and last byte is 00 or FF - if(*p_fifth_byte == 0xE8 && (*p_first_byte == 0x00 || *p_first_byte == 0xFF)) - { - return true; - } - - // the other is six bytes - if(*p_sixth_byte == 0xFF || *p_second_byte == 0xFF) - { - return true; - } - - return false; -} - -PBYTE get_valid_frame(PBYTE esp) -{ - PDWORD cur_stack_loc = NULL; - const int max_search = 400; - WCHAR module_name[MAX_PATH]; - PBYTE module_addr = 0; - - // round to highest multiple of four - esp = (esp + (4 - ((int)esp % 4)) % 4); - - // scroll through stack a few hundred places. - for (cur_stack_loc = (PDWORD) esp; cur_stack_loc < (PDWORD)esp + max_search; cur_stack_loc += 1) - { - // if you can read the pointer, - if (IsBadReadPtr(cur_stack_loc, sizeof(PDWORD))) - { - continue; - } - - // check if it's in a module - if (!Get_Module_By_Ret_Addr((PBYTE)*cur_stack_loc, module_name, module_addr)) - { - continue; - } - - // check if the code before the instruction ptr is a call - if(!has_valid_call_before(cur_stack_loc)) - { - continue; - } - - // if these all pass, return that ebp, otherwise continue till we're dead - return (PBYTE)(cur_stack_loc - 1); - } - - return NULL; -} - -bool shouldUseStackWalker(PSTACK Ebp, int max_depth) -{ - WCHAR Module_Name[MAX_PATH]; - PBYTE Module_Addr = 0; - int depth = 0; - - while (depth < max_depth) - { - if (IsBadReadPtr(Ebp, sizeof(PSTACK)) || - IsBadReadPtr(Ebp->Ebp, sizeof(PSTACK)) || - Ebp->Ebp < Ebp || - Ebp->Ebp - Ebp > 0xFFFFFF || - IsBadCodePtr(FARPROC(Ebp->Ebp->Ret_Addr)) || - !Get_Module_By_Ret_Addr(Ebp->Ebp->Ret_Addr, Module_Name, Module_Addr)) - { - return true; - } - depth++; - Ebp = Ebp->Ebp; - } - - return false; -} - -//****************************************************************** -void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, - const CONTEXT* context_record, - LLSD& info) -//****************************************************************** -// Fill Str with call stack info. -// pException can be either GetExceptionInformation() or NULL. -// If pException = NULL - get current call stack. -{ - LPWSTR Module_Name = new WCHAR[MAX_PATH]; - PBYTE Module_Addr = 0; - LLSD params; - PBYTE Esp = NULL; - LLSD tmp_info; - - bool fake_frame = false; - bool ebp_used = false; - const int HEURISTIC_MAX_WALK = 20; - int heuristic_walk_i = 0; - int Ret_Addr_I = 0; - - STACK Stack = {0, 0}; - PSTACK Ebp; - - if (exception_record && context_record) //fake frame for exception address - { - Stack.Ebp = (PSTACK)(context_record->Ebp); - Stack.Ret_Addr = (PBYTE)exception_record->ExceptionAddress; - Ebp = &Stack; - Esp = (PBYTE) context_record->Esp; - fake_frame = true; - } - else if(context_record) - { - Ebp = (PSTACK)(context_record->Ebp); - Esp = (PBYTE)(context_record->Esp); - } - else - { - Ebp = (PSTACK)&exception_record - 1; //frame addr of Get_Call_Stack() - Esp = (PBYTE)&exception_record; - - // Skip frame of Get_Call_Stack(). - if (!IsBadReadPtr(Ebp, sizeof(PSTACK))) - Ebp = Ebp->Ebp; //caller ebp - } - - // Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX. - // Break trace on wrong stack frame. - for (Ret_Addr_I = 0; - heuristic_walk_i < HEURISTIC_MAX_WALK && - Ret_Addr_I < CALL_TRACE_MAX && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr)); - Ret_Addr_I++) - { - // If module with Ebp->Ret_Addr found. - if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr)) - { - // Save module's address and full path. - tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name); - tmp_info["CallStack"][Ret_Addr_I]["ModuleAddress"] = (int)Module_Addr; - tmp_info["CallStack"][Ret_Addr_I]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr); - - // Save 5 params of the call. We don't know the real number of params. - if (fake_frame && !Ret_Addr_I) //fake frame for exception address - params[0] = "Exception Offset"; - else if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD))) - { - for(int j = 0; j < 5; ++j) - { - params[j] = (int)Ebp->Param[j]; - } - } - tmp_info["CallStack"][Ret_Addr_I]["Parameters"] = params; - } - - tmp_info["CallStack"][Ret_Addr_I]["ReturnAddress"] = (int)Ebp->Ret_Addr; - - // get ready for next frame - // Set ESP to just after return address. Not the real esp, but just enough after the return address - if(!fake_frame) { - Esp = (PBYTE)Ebp + 8; - } - else - { - fake_frame = false; - } - - // is next ebp valid? - // only run if we've never found a good ebp - // and make sure the one after is valid as well - if( !ebp_used && - shouldUseStackWalker(Ebp, 2)) - { - heuristic_walk_i++; - PBYTE new_ebp = get_valid_frame(Esp); - if (new_ebp != NULL) - { - Ebp = (PSTACK)new_ebp; - } - } - else - { - ebp_used = true; - Ebp = Ebp->Ebp; - } - } -/* TODO remove or turn this code back on to edit the stack after i see a few raw ones. -Palmer - // Now go back through and edit out heuristic stacks that could very well be bogus. - // Leave the top and the last 3 stack chosen by the heuristic, however. - if(heuristic_walk_i > 2) - { - info["CallStack"][0] = tmp_info["CallStack"][0]; - std::string ttest = info["CallStack"][0]["ModuleName"]; - for(int cur_frame = 1; - (cur_frame + heuristic_walk_i - 2 < Ret_Addr_I); - ++cur_frame) - { - // edit out the middle heuristic found frames - info["CallStack"][cur_frame] = tmp_info["CallStack"][cur_frame + heuristic_walk_i - 2]; - } - } - else - { - info = tmp_info; - } -*/ - info = tmp_info; - info["HeuristicWalkI"] = heuristic_walk_i; - info["EbpUsed"] = ebp_used; - -} //Get_Call_Stack - -//*********************************** -void WINAPI Get_Version_Str(LLSD& info) -//*********************************** -// Fill Str with Windows version. -{ - OSVERSIONINFOEX V = {sizeof(OSVERSIONINFOEX)}; //EX for NT 5.0 and later - - if (!GetVersionEx((POSVERSIONINFO)&V)) - { - ZeroMemory(&V, sizeof(V)); - V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx((POSVERSIONINFO)&V); - } - - if (V.dwPlatformId != VER_PLATFORM_WIN32_NT) - V.dwBuildNumber = LOWORD(V.dwBuildNumber); //for 9x HIWORD(dwBuildNumber) = 0x04xx - - info["Platform"] = llformat("Windows: %d.%d.%d, SP %d.%d, Product Type %d", //SP - service pack, Product Type - VER_NT_WORKSTATION,... - V.dwMajorVersion, V.dwMinorVersion, V.dwBuildNumber, V.wServicePackMajor, V.wServicePackMinor, V.wProductType); -} //Get_Version_Str - -//************************************************************* -LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) -//************************************************************* -// Allocate Str[DUMP_SIZE_MAX] and return Str with dump, if !pException - just return call stack in Str. -{ - LLSD info; - LPWSTR Str; - int Str_Len; -// int i; - LPWSTR Module_Name = new WCHAR[MAX_PATH]; - PBYTE Module_Addr; - HANDLE hFile; - FILETIME Last_Write_Time; - FILETIME Local_File_Time; - SYSTEMTIME T; - - Str = new WCHAR[DUMP_SIZE_MAX]; - Str_Len = 0; - if (!Str) - return NULL; - - Get_Version_Str(info); - - GetModuleFileName(NULL, Str, MAX_PATH); - info["Process"] = ll_convert_wide_to_string(Str); - info["ThreadID"] = (S32)GetCurrentThreadId(); - - // If exception occurred. - if (pException) - { - EXCEPTION_RECORD & E = *pException->ExceptionRecord; - CONTEXT & C = *pException->ContextRecord; - - // If module with E.ExceptionAddress found - save its path and date. - if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr)) - { - info["Module"] = ll_convert_wide_to_string(Module_Name); - - if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) - { - if (GetFileTime(hFile, NULL, NULL, &Last_Write_Time)) - { - FileTimeToLocalFileTime(&Last_Write_Time, &Local_File_Time); - FileTimeToSystemTime(&Local_File_Time, &T); - - info["DateModified"] = llformat("%02d/%02d/%d", T.wMonth, T.wDay, T.wYear); - } - CloseHandle(hFile); - } - } - else - { - info["ExceptionAddr"] = (int)E.ExceptionAddress; - } - - info["ExceptionCode"] = (int)E.ExceptionCode; - - /* - //TODO: Fix this - if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) - { - // Access violation type - Write/Read. - LLSD exception_info; - exception_info["Type"] = E.ExceptionInformation[0] ? "Write" : "Read"; - exception_info["Address"] = llformat("%08x", E.ExceptionInformation[1]); - info["Exception Information"] = exception_info; - } - */ - - - // Save instruction that caused exception. - /* - std::string str; - for (i = 0; i < 16; i++) - str += llformat(" %02X", PBYTE(E.ExceptionAddress)[i]); - info["Instruction"] = str; - */ - LLSD registers; - registers["EAX"] = (int)C.Eax; - registers["EBX"] = (int)C.Ebx; - registers["ECX"] = (int)C.Ecx; - registers["EDX"] = (int)C.Edx; - registers["ESI"] = (int)C.Esi; - registers["EDI"] = (int)C.Edi; - registers["ESP"] = (int)C.Esp; - registers["EBP"] = (int)C.Ebp; - registers["EIP"] = (int)C.Eip; - registers["EFlags"] = (int)C.EFlags; - info["Registers"] = registers; - } //if (pException) - - // Save call stack info. - Get_Call_Stack(pException->ExceptionRecord, pException->ContextRecord, info); - - return info; -} //Get_Exception_Info - -#define UNICODE - - -class LLMemoryReserve { -public: - LLMemoryReserve(); - ~LLMemoryReserve(); - void reserve(); - void release(); -protected: - unsigned char *mReserve; - static const size_t MEMORY_RESERVATION_SIZE; -}; - -LLMemoryReserve::LLMemoryReserve() : - mReserve(NULL) -{ -}; - -LLMemoryReserve::~LLMemoryReserve() -{ - release(); -} - -// I dunno - this just seemed like a pretty good value. -const size_t LLMemoryReserve::MEMORY_RESERVATION_SIZE = 5 * 1024 * 1024; - -void LLMemoryReserve::reserve() -{ - if(NULL == mReserve) - mReserve = new unsigned char[MEMORY_RESERVATION_SIZE]; -}; - -void LLMemoryReserve::release() -{ - delete [] mReserve; - mReserve = NULL; -}; - -static LLMemoryReserve gEmergencyMemoryReserve; - -#ifndef _M_IX86 - #error "The following code only works for x86!" -#endif -LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter( - LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) -{ - if(lpTopLevelExceptionFilter == gFilterFunc) - return gFilterFunc; - - llinfos << "Someone tried to set the exception filter. Listing call stack modules" << llendl; - LLSD cs_info; - Get_Call_Stack(NULL, NULL, cs_info); - - if(cs_info.has("CallStack") && cs_info["CallStack"].isArray()) - { - LLSD cs = cs_info["CallStack"]; - for(LLSD::array_iterator i = cs.beginArray(); - i != cs.endArray(); - ++i) - { - llinfos << "Module: " << (*i)["ModuleName"] << llendl; - } - } - - return gFilterFunc; -} - -BOOL PreventSetUnhandledExceptionFilter() -{ - HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); - if (hKernel32 == NULL) - return FALSE; - - void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter"); - if(pOrgEntry == NULL) - return FALSE; - - unsigned char newJump[ 100 ]; - DWORD dwOrgEntryAddr = (DWORD)pOrgEntry; - dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far - void *pNewFunc = &MyDummySetUnhandledExceptionFilter; - DWORD dwNewEntryAddr = (DWORD) pNewFunc; - DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr; - - newJump[ 0 ] = 0xE9; // JMP absolute - memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc)); - SIZE_T bytesWritten; - BOOL bRet = WriteProcessMemory(GetCurrentProcess(), - pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten); - return bRet; -} - -// static -void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) -{ - - static bool s_first_run = true; - // Load the dbghelp dll now, instead of waiting for the crash. - // Less potential for stack mangling - - if (s_first_run) - { - // First, try loading from the directory that the app resides in. - std::string local_dll_name = gDirUtilp->findFile("dbghelp.dll", gDirUtilp->getWorkingDir(), gDirUtilp->getExecutableDir()); - - HMODULE hDll = NULL; - hDll = LoadLibraryA(local_dll_name.c_str()); - if (!hDll) - { - hDll = LoadLibrary(L"dbghelp.dll"); - } - - if (!hDll) - { - LL_WARNS("AppInit") << "Couldn't find dbghelp.dll!" << LL_ENDL; - } - else - { - f_mdwp = (MINIDUMPWRITEDUMP) GetProcAddress(hDll, "MiniDumpWriteDump"); - - if (!f_mdwp) - { - FreeLibrary(hDll); - hDll = NULL; - } - } - - gEmergencyMemoryReserve.reserve(); - - s_first_run = false; - } - - // Try to get Tool Help library functions. - HMODULE hKernel32; - hKernel32 = GetModuleHandle(_T("KERNEL32")); - CreateToolhelp32Snapshot_ = (CREATE_TOOL_HELP32_SNAPSHOT)GetProcAddress(hKernel32, "CreateToolhelp32Snapshot"); - Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32FirstW"); - Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32NextW"); - - LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - prev_filter = SetUnhandledExceptionFilter(filter_func); - - // *REMOVE:Mani - //PreventSetUnhandledExceptionFilter(); - - if(prev_filter != gFilterFunc) - { - LL_WARNS("AppInit") - << "Replacing unknown exception (" << (void *)prev_filter << ") with (" << (void *)filter_func << ") !" << LL_ENDL; - } - - gFilterFunc = filter_func; -} - -bool LLWinDebug::checkExceptionHandler() -{ - bool ok = true; - LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - prev_filter = SetUnhandledExceptionFilter(gFilterFunc); - - if (prev_filter != gFilterFunc) - { - LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with " << prev_filter << "!" << LL_ENDL; - ok = false; - } - - if (prev_filter == NULL) - { - ok = FALSE; - if (gFilterFunc == NULL) - { - LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL; - } - else - { - LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with NULL!" << LL_ENDL; - } - } - - return ok; -} - -void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename) -{ - if(f_mdwp == NULL || gDirUtilp == NULL) - { - return; - //write_debug("No way to generate a minidump, no MiniDumpWriteDump function!\n"); - } - else - { - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename); - - HANDLE hFile = CreateFileA(dump_path.c_str(), - GENERIC_WRITE, - FILE_SHARE_WRITE, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (hFile != INVALID_HANDLE_VALUE) - { - // Write the dump, ignoring the return value - f_mdwp(GetCurrentProcess(), - GetCurrentProcessId(), - hFile, - type, - ExInfop, - NULL, - NULL); - - CloseHandle(hFile); - } - - } -} - -// static -void LLWinDebug::generateCrashStacks(struct _EXCEPTION_POINTERS *exception_infop) -{ - // *NOTE:Mani - This method is no longer the exception handler. - // Its called from viewer_windows_exception_handler() and other places. - - // - // Let go of a bunch of reserved memory to give library calls etc - // a chance to execute normally in the case that we ran out of - // memory. - // - LLSD info; - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, - "SecondLifeException"); - std::string log_path = dump_path + ".log"; - - if (exception_infop) - { - // Since there is exception info... Release the hounds. - gEmergencyMemoryReserve.release(); - - if(gSavedSettings.getControl("SaveMinidump").notNull() && gSavedSettings.getBOOL("SaveMinidump")) - { - _MINIDUMP_EXCEPTION_INFORMATION ExInfo; - - ExInfo.ThreadId = ::GetCurrentThreadId(); - ExInfo.ExceptionPointers = exception_infop; - ExInfo.ClientPointers = NULL; - - writeDumpToFile(MiniDumpNormal, &ExInfo, "SecondLife.dmp"); - writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLifePlus.dmp"); - } - - info = Get_Exception_Info(exception_infop); - } - - LLSD threads; - std::vector<DWORD> thread_ids; - GetProcessThreadIDs(GetCurrentProcessId(), thread_ids); - - for(std::vector<DWORD>::iterator th_itr = thread_ids.begin(); - th_itr != thread_ids.end(); - ++th_itr) - { - LLSD thread_info; - if(*th_itr != GetCurrentThreadId()) - { - GetThreadCallStack(*th_itr, thread_info); - } - - if(thread_info) - { - threads[llformat("ID %d", *th_itr)] = thread_info; - } - } - - info["Threads"] = threads; - - llofstream out_file(log_path); - LLSDSerialize::toPrettyXML(info, out_file); - out_file.close(); -} - -void LLWinDebug::clearCrashStacks() -{ - LLSD info; - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeException.log"); - LLFile::remove(dump_path); -} diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h deleted file mode 100644 index f4a6a2d54d..0000000000 --- a/indra/newview/llwindebug.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file llwindebug.h - * @brief LLWinDebug class header file - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLWINDEBUG_H -#define LL_LLWINDEBUG_H - -#include "stdtypes.h" -#include <dbghelp.h> - -class LLWinDebug -{ -public: - - /** - * @brief initialize the llwindebug exception filter callback - * - * Hand a windows unhandled exception filter to LLWinDebug - * This method should only be called to change the - * exception filter used by llwindebug. - * - * Setting filter_func to NULL will clear any custom filters. - **/ - static void initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func); - - /** - * @brief check the status of the exception filter. - * - * Resets unhandled exception filter to the filter specified - * w/ initExceptionFilter). - * Returns false if the exception filter was modified. - * - * *NOTE:Mani In the past mozlib has been accused of - * overriding the exception filter. If the mozlib filter - * is required, perhaps we can chain calls from our - * filter to mozlib's. - **/ - static bool checkExceptionHandler(); - - static void generateCrashStacks(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL); - static void clearCrashStacks(); // Delete the crash stack file(s). - - static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename); -private: -}; - -#endif // LL_LLWINDEBUG_H diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index a8ac0c0c90..1d10ec7b28 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -513,7 +513,7 @@ void LLXMLRPCTransaction::Impl::setStatus(EStatus status, // Usually this means that there's a problem with the login server, // not with the client. Direct user to status page. mStatusMessage = LLTrans::getString("server_is_down"); - mStatusURI = "http://secondlife.com/status/"; + mStatusURI = "http://status.secondlifegrid.net/"; } } } diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index 731953f9bb..df2fb2a6ea 100644 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -129,8 +129,8 @@ TOOLSIT CURSOR "toolsit.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,2,0 - PRODUCTVERSION 2,0,2,0 + FILEVERSION 2,1,0,0 + PRODUCTVERSION 2,1,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -147,12 +147,12 @@ BEGIN BEGIN VALUE "CompanyName", "Linden Lab" VALUE "FileDescription", "Second Life" - VALUE "FileVersion", "2.0.2.0" + VALUE "FileVersion", "2.1.0.0" VALUE "InternalName", "Second Life" VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" - VALUE "ProductVersion", "2.0.2.0" + VALUE "ProductVersion", "2.1.0.0" END END BLOCK "VarFileInfo" diff --git a/indra/newview/skins/default/textures/icons/Inv_Link.png b/indra/newview/skins/default/textures/icons/Inv_Link.png Binary files differnew file mode 100644 index 0000000000..c1543dacb5 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_Link.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index e3ca58d10c..ae7f149d69 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -229,39 +229,7 @@ with the same filename but different name <texture name="Inv_TrashOpen" file_name="icons/Inv_TrashOpen.png" preload="false" /> <texture name="Inv_Underpants" file_name="icons/Inv_Underpants.png" preload="false" /> <texture name="Inv_Undershirt" file_name="icons/Inv_Undershirt.png" preload="false" /> - - <texture name="Inv_Alpha_Link" file_name="icons/Inv_Alpha_Link.png" preload="false" /> - <texture name="Inv_Animation_Link" file_name="icons/Inv_Animation_Link.png" preload="false" /> - <texture name="Inv_BodyShape_Link" file_name="icons/Inv_BodyShape_Link.png" preload="false" /> - <texture name="Inv_CallingCard_Link" file_name="icons/Inv_CallingCard_Link.png" preload="false" /> - <texture name="Inv_Clothing_Link" file_name="icons/Inv_Clothing_Link.png" preload="false" /> - <texture name="Inv_Eye_Link" file_name="icons/Inv_Eye_Link.png" preload="false" /> - <texture name="Inv_FolderClosed_Link" file_name="icons/Inv_FolderClosed_Link.png" preload="false" /> - <texture name="Inv_FolderOpen_Link" file_name="icons/Inv_FolderOpen_Link.png" preload="false" /> - <texture name="Inv_Gesture_Link" file_name="icons/Inv_Gesture_Link.png" preload="false" /> - <texture name="Inv_Gloves_Link" file_name="icons/Inv_Gloves_Link.png" preload="false" /> - <texture name="Inv_Hair_Link" file_name="icons/Inv_Hair_Link.png" preload="false" /> - <texture name="Inv_LinkFolder_Link" file_name="icons/Inv_LinkFolder_Link.png" preload="false" /> - <texture name="Inv_Jacket_Link" file_name="icons/Inv_Jacket_Link.png" preload="false" /> - <texture name="Inv_LookFolderOpen_Link" file_name="icons/Inv_LookFolderOpen_Link.png" preload="false" /> - <texture name="Inv_LookFolderClosed_Link" file_name="icons/Inv_LookFolderClosed_Link.png" preload="false" /> - <texture name="Inv_Landmark_Link" file_name="icons/Inv_Landmark_Link.png" preload="false" /> - <texture name="Inv_Notecard_Link" file_name="icons/Inv_Notecard_Link.png" preload="false" /> - <texture name="Inv_Object_Link" file_name="icons/Inv_Object_Link.png" preload="false" /> - <texture name="Inv_Object_Multi_Link" file_name="icons/Inv_Object_Multi_Link.png" preload="false" /> - <texture name="Inv_Pants_Link" file_name="icons/Inv_Pants_Link.png" preload="false" /> - <texture name="Inv_Script_Link" file_name="icons/Inv_Script_Link.png" preload="false" /> - <texture name="Inv_Shirt_Link" file_name="icons/Inv_Shirt_Link.png" preload="false" /> - <texture name="Inv_Shoe_Link" file_name="icons/Inv_Shoe_Link.png" preload="false" /> - <texture name="Inv_Skin_Link" file_name="icons/Inv_Skin_Link.png" preload="false" /> - <texture name="Inv_Skirt_Link" file_name="icons/Inv_Skirt_Link.png" preload="false" /> - <texture name="Inv_Snapshot_Link" file_name="icons/Inv_Snapshot_Link.png" preload="false" /> - <texture name="Inv_Socks_Link" file_name="icons/Inv_Socks_Link.png" preload="false" /> - <texture name="Inv_Sound_Link" file_name="icons/Inv_Sound_Link.png" preload="false" /> - <texture name="Inv_Tattoo_Link" file_name="icons/Inv_Tattoo_Link.png" preload="false" /> - <texture name="Inv_Texture_Link" file_name="icons/Inv_Texture_Link.png" preload="false" /> - <texture name="Inv_Underpants_Link" file_name="icons/Inv_Underpants_Link.png" preload="false" /> - <texture name="Inv_Undershirt_Link" file_name="icons/Inv_Undershirt_Link.png" preload="false" /> + <texture name="Inv_Link" file_name="icons/Inv_Link.png" preload="false" /> <texture name="Linden_Dollar_Alert" file_name="widgets/Linden_Dollar_Alert.png"/> <texture name="Linden_Dollar_Background" file_name="widgets/Linden_Dollar_Background.png"/> diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency_html.xml b/indra/newview/skins/default/xui/en/floater_buy_currency_html.xml index 4643f66bd8..4b990fa566 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_currency_html.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_currency_html.xml @@ -1,27 +1,27 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - legacy_header_height="18" can_resize="false" - height="280" + can_close="true" + width="422" + height="202" layout="topleft" - min_height="280" - min_width="450" name="floater_buy_currency_html" help_topic="floater_buy_currency_html" save_rect="true" single_instance="true" title="BUY CURRENCY" - width="452"> - <floater.string - name="buy_currency_url" translate="false"> - https://quick-buy-www.jeff.ooze.lindenlab.com/en/display - </floater.string> - <web_browser - bottom="278" - follows="left|right|top|bottom" - layout="topleft" - left="2" - name="browser" - top="18" - width="450" /> +> + <floater.string + name="buy_currency_url" translate="false"> + https://quick-buy.secondlife.com/[LANGUAGE]/display/?sa=[SPECIFIC_AMOUNT]&sum=[SUM]&msg=[MSG]&bal=[BAL] + </floater.string> + <web_browser + follows="all" + layout="topleft" + left="1" + right="-1" + top="1" + bottom="-1" + ignore_ui_scale="false" + name="browser"/> </floater> diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml index b5eda8e999..8e7ef7f0b5 100644 --- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml @@ -11,6 +11,9 @@ <on_enable function="Gear.OnEnable" parameter="wear" /> + <on_visible + function="Gear.OnVisible" + parameter="wear" /> </menu_item_call> <menu_item_call label="Take Off - Remove from Current Outfit" @@ -21,9 +24,12 @@ <on_enable function="Gear.OnEnable" parameter="take_off" /> + <on_visible + function="Gear.OnVisible" + parameter="take_off" /> </menu_item_call> - <menu_item_separator /> + <menu_item_separator name="sepatator1" /> <!-- copied (with minor modifications) from menu_inventory_add.xml --> <!-- *TODO: generate dynamically? --> <menu @@ -168,9 +174,9 @@ </menu> <!-- copied from menu_inventory_add.xml --> - <menu_item_separator /> + <menu_item_separator name="sepatator2" /> <menu_item_call - label="Rename" + label="Rename Outfit" layout="topleft" name="rename"> <on_click @@ -178,6 +184,9 @@ <on_enable function="Gear.OnEnable" parameter="rename" /> + <on_visible + function="Gear.OnVisible" + parameter="rename" /> </menu_item_call> <menu_item_call label="Delete Outfit" @@ -188,5 +197,8 @@ <on_enable function="Gear.OnEnable" parameter="delete" /> + <on_visible + function="Gear.OnVisible" + parameter="delete" /> </menu_item_call> </menu> diff --git a/indra/newview/skins/default/xui/en/menu_outfit_tab.xml b/indra/newview/skins/default/xui/en/menu_outfit_tab.xml index 67559638d9..e084216a69 100644 --- a/indra/newview/skins/default/xui/en/menu_outfit_tab.xml +++ b/indra/newview/skins/default/xui/en/menu_outfit_tab.xml @@ -8,8 +8,8 @@ name="wear_replace"> <on_click function="Outfit.WearReplace" /> - <on_enable - function="Outfit.OnEnable" + <on_visible + function="Outfit.OnVisible" parameter="wear_replace" /> </menu_item_call> <menu_item_call @@ -18,8 +18,8 @@ name="wear_add"> <on_click function="Outfit.WearAdd" /> - <on_enable - function="Outfit.OnEnable" + <on_visible + function="Outfit.OnVisible" parameter="wear_add" /> </menu_item_call> <menu_item_call @@ -28,8 +28,8 @@ name="take_off"> <on_click function="Outfit.TakeOff" /> - <on_enable - function="Outfit.OnEnable" + <on_visible + function="Outfit.OnVisible" parameter="take_off" /> </menu_item_call> <menu_item_call @@ -38,8 +38,8 @@ name="edit"> <on_click function="Outfit.Edit" /> - <on_enable - function="Outfit.OnEnable" + <on_visible + function="Outfit.OnVisible" parameter="edit" /> </menu_item_call> <menu_item_separator /> @@ -59,8 +59,8 @@ name="delete"> <on_click function="Outfit.Delete" /> - <on_enable - function="Outfit.OnEnable" + <on_visible + function="Outfit.OnVisible" parameter="delete" /> </menu_item_call> </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml index fa5ca60a19..430a7b6444 100644 --- a/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml +++ b/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml @@ -38,13 +38,6 @@ layout="topleft" name="wearable_attach_to_hud" /> <menu_item_call - label="Object Profile" - layout="topleft" - name="object_profile"> - <on_click - function="Attachment.Profile" /> - </menu_item_call> - <menu_item_call label="Take Off" layout="topleft" name="take_off"> @@ -59,6 +52,13 @@ function="Wearable.Edit" /> </menu_item_call> <menu_item_call + label="Object Profile" + layout="topleft" + name="object_profile"> + <on_click + function="Attachment.Profile" /> + </menu_item_call> + <menu_item_call label="Show Original" layout="topleft" name="show_original"> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 68a929adc4..39457b7e19 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2066,6 +2066,7 @@ Would you be my friend? name="Cancel" text="Cancel"/> </form> + <unique/> </notification> <notification @@ -6218,7 +6219,7 @@ The button will be shown when there is enough space for it. icon="notifytip.tga" name="ShareNotification" type="notifytip"> -Drag items from inventory onto a person in the resident picker +Select residents to share with. </notification> <notification diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml index 44437d01eb..bdfa928b1d 100644 --- a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml @@ -19,6 +19,6 @@ multi_select="true" name="wearable_items_list" translate="false" - use_internal_context_menu="false" + standalone="false" /> </accordion_tab> diff --git a/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml b/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml index 4e5f594ffe..4f989a6f6f 100644 --- a/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml @@ -57,7 +57,8 @@ left="0" height="23" width="23" - tab_stop="false"> + tab_stop="false" + tool_tip="You don't have permission to edit"> <icon name="btn_lock1" layout="topleft" @@ -88,7 +89,8 @@ left="0" height="23" width="23" - tab_stop="false" /> + tab_stop="false" + tool_tip="Edit this shape"/> </panel> <icon follows="left|right|top" diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml index 859cc82e81..976f6d6cd0 100644 --- a/indra/newview/skins/default/xui/en/panel_classified_info.xml +++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml @@ -47,7 +47,7 @@ layout="topleft" name="back_btn" picture_style="true" - left="9" + left="10" tab_stop="false" top="2" width="30" /> @@ -56,7 +56,7 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="4" name="title" text_color="LtGray" top="0" diff --git a/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml index 5d81aebbd5..93d7720c57 100644 --- a/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml @@ -37,7 +37,8 @@ left="0" height="18" width="18" - tab_stop="false" /> + tab_stop="false" + tool_tip="Remove from outfit" /> <icon height="16" follows="top|left" @@ -88,7 +89,8 @@ left="0" height="23" width="23" - tab_stop="false"> + tab_stop="false" + tool_tip="You don't have permission to edit"> <icon name="btn_lock1" layout="topleft" @@ -119,7 +121,8 @@ left="0" height="23" width="23" - tab_stop="false" /> + tab_stop="false" + tool_tip="Edit this wearable"/> </panel> <icon follows="left|right|top" diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml index d36c2a4e6f..f016c27b0a 100644 --- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml +++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml @@ -28,7 +28,7 @@ allow_select="true" follows="all" height="10" - item_pad="2" + item_pad="3" layout="topleft" left="0" multi_select="true" @@ -44,7 +44,7 @@ allow_select="true" follows="all" height="10" - item_pad="2" + item_pad="3" layout="topleft" left="0" multi_select="true" @@ -60,7 +60,7 @@ allow_select="true" follows="all" height="10" - item_pad="2" + item_pad="3" layout="topleft" left="0" multi_select="true" diff --git a/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml b/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml index 45031859f1..75b5fd1532 100644 --- a/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml @@ -37,7 +37,8 @@ left="0" height="18" width="18" - tab_stop="false" /> + tab_stop="false" + tool_tip="Remove from outfit"/> <icon height="16" follows="top|left" diff --git a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml index 20652df918..a5dd34bd22 100644 --- a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml @@ -49,16 +49,27 @@ top="4" value="..." width="359" /> - <button - name="btn_add" + <panel + name="btn_add_panel" layout="topleft" follows="top|right" - image_overlay="AddItem_Off" top="0" left="0" height="23" - width="23" - tab_stop="false" /> + width="26" + tab_stop="false"> + <button + name="btn_add" + layout="topleft" + follows="top|right" + image_overlay="AddItem_Off" + top="0" + left="0" + height="23" + width="23" + tab_stop="false" + tool_tip="Add more items of this type" /> + </panel> <icon follows="left|right|top" height="3" diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml index 1b4f547f9d..6744a7b9c2 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml @@ -31,7 +31,7 @@ layout="topleft" name="back_btn" picture_style="true" - left="7" + left="10" tab_stop="false" top="2" width="30" /> @@ -42,7 +42,7 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="4" name="title" text_color="LtGray" top="0" 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 589ea10e8d..dc83b334b5 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml @@ -24,7 +24,7 @@ image_unselected="BackButton_Off" layout="topleft" name="back_btn" - left="7" + left="10" tab_stop="false" top="2" width="30" /> @@ -35,10 +35,10 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="4" name="title" text_color="LtGray" - top="0" + top="2" width="250"> Edit Pick </text> diff --git a/indra/newview/skins/default/xui/en/panel_edit_shape.xml b/indra/newview/skins/default/xui/en/panel_edit_shape.xml index cf15fb0455..d295f5fe4a 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_shape.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_shape.xml @@ -8,19 +8,22 @@ name="edit_shape_panel" top_pad="10" width="333" > - <text - follows="top|left|right" - font="SansSerifSmallBold" - halign="right" - height="12" - layout="topleft" - left="0" - name="avatar_height" - text_color="EmphasisColor" - top="0" - width="310"> - [HEIGHT] Meters tall - </text> + <string name="meters">Meters</string> + <string name="feet">Feet</string> + <string name="height">Height:</string> + <string name="heigth_label_color" translate="false">White_50</string> + <string name="heigth_value_label_color" translate="false">White</string> + <text + follows="top|left|right" + font="SansSerifSmallBold" + halign="right" + height="12" + layout="topleft" + left="0" + name="avatar_height" + top="0" + width="310"> + </text> <panel border="false" bg_alpha_color="DkGray2" diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 645ee8a435..950c4a5fdb 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -141,15 +141,16 @@ left="0" layout="topleft" name="back_btn" left="11" - top="7" /> + top="3" /> <text follows="top|left" font="SansSerifHugeBold" height="22" layout="topleft" - left_pad="15" + left_pad="8" name="edit_wearable_title" text_color="white" + top="3" value="Editing Shape" width="270" /> <panel diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index 58b78cfa02..e4eb9afb29 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -57,9 +57,9 @@ background_visible="true" font="SansSerifHugeBold" h_pad="0" height="26" - left_pad="10" + left_pad="8" text_color="LtGray" - top="0" + top="1" use_ellipses="true" width="275" follows="top|left|right" 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 19fe2ea874..6523b0d491 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -74,16 +74,14 @@ Maximum 200 per group daily </text> <button follows="top|left" - height="18" - image_selected="AddItem_Press" - image_unselected="AddItem_Off" - image_disabled="AddItem_Disabled" + height="23" + image_overlay="AddItem_Off" layout="topleft" left="5" name="create_new_notice" tool_tip="Create a new notice" - top_delta="-3" - width="18" /> + top_delta="-3" + width="23" /> <button follows="top|left" height="23" diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index bb73360e0b..55fef5aaf7 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -63,7 +63,7 @@ image_pressed="BackButton_Press" image_unselected="BackButton_Off" layout="topleft" - left="8" + left="9" name="back_btn" tool_tip="Back" tab_stop="false" @@ -74,10 +74,10 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="7" name="title" text_color="LtGray" - top="2" + top="3" use_ellipses="true" value="Place Profile" width="280" /> diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index d65b86f007..2a53b3e2fa 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -42,7 +42,7 @@ <filter_editor text_pad_left="10" follows="left|top|right" - height="23" + height="23" label="Filter Inventory" layout="topleft" left="10" @@ -68,10 +68,10 @@ top_pad="10" width="312"> <inventory_panel - bg_opaque_color="DkGray2" - bg_alpha_color="DkGray2" - background_visible="true" - background_opaque="true" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + background_opaque="true" border="false" bevel_style="none" follows="all" @@ -82,13 +82,14 @@ left="0" name="All Items" sort_order_setting="InventorySortOrder" + show_item_link_overlays="true" top="16" width="288" /> <recent_inventory_panel - bg_opaque_color="DkGray2" - bg_alpha_color="DkGray2" - background_visible="true" - background_opaque="true" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + background_opaque="true" border="false" bevel_style="none" follows="all" @@ -98,6 +99,7 @@ layout="topleft" left_delta="0" name="Recent Items" + show_item_link_overlays="true" width="290" /> </tab_container> <layout_stack diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index c9802a269c..ed3b176267 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -51,6 +51,8 @@ <string name="Filter.All" value="All"/> <string name="Filter.Clothes/Body" value="Clothes/Body"/> <string name="Filter.Objects" value="Objects"/> + <string name="Filter.Clothing" value="Clothing"/> + <string name="Filter.Bodyparts" value="Body parts"/> <button @@ -63,14 +65,14 @@ name="back_btn" left="5" tab_stop="false" - top="2" + top="1" width="30" /> <text follows="top|right" font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="20" + left_pad="10" name="title" text_color="LtGray" top="0" @@ -210,6 +212,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap left="2" name="show_add_wearables_btn" top_pad="2" + tool_tip="Open/Close" width="125" /> <combo_box @@ -217,11 +220,20 @@ It is calculated as border_size + 2*UIResizeBarOverlap height="22" layout="topleft" left_pad="5" - name="filter_wearables_combobox" + name="list_view_filter_combobox" top_delta="0" visible="false" width="152"/> - + <combo_box + follows="left|right|bottom" + height="22" + layout="topleft" + left_delta="0" + name="folder_view_filter_combobox" + top_delta="0" + visible="false" + width="152"/> + <button follows="bottom|right" height="22" @@ -299,7 +311,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap layout="topleft" left="0" mouse_opaque="false" - name="inventory_items" + name="folder_view" top_pad="5" width="310" visible="false"/> @@ -318,7 +330,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap visible="true"> <wearable_items_list color="0.107 0.107 0.107 1" - name="filtered_wearables_list" + name="list_view" allow_select="true" layout="topleft" follows="all" @@ -482,6 +494,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap layout="topleft" name="revert_btn" top="0" + tool_tip="Revert to last saved version" width="147" /> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index de1f2cf31b..37eb5eaa98 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -83,18 +83,18 @@ width="241" /> - <dnd_button - follows="bottom|right" - height="25" - image_hover_unselected="Toolbar_Right_Over" - image_overlay="TrashItem_Off" - image_selected="Toolbar_Right_Selected" - image_unselected="Toolbar_Right_Off" - layout="topleft" - left_pad="1" - name="trash_btn" - tool_tip="Remove selected item" - width="31"/> + <dnd_button + follows="bottom|right" + height="25" + image_hover_unselected="Toolbar_Right_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Right_Selected" + image_unselected="Toolbar_Right_Off" + layout="topleft" + left_pad="1" + name="trash_btn" + tool_tip="Delete selected outfit" + width="31"/> <button follows="bottom|left" height="23" diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml index 49e1d16f6a..1d01bcb8a5 100644 --- a/indra/newview/skins/default/xui/en/panel_pick_info.xml +++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml @@ -18,7 +18,7 @@ image_unselected="BackButton_Off" layout="topleft" name="back_btn" - left="7" + left="10" tab_stop="false" top="2" width="30" /> @@ -27,10 +27,10 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="4" name="title" text_color="LtGray" - top="0" + top="2" value="Pick Info" use_ellipses="true" width="275" /> diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index 59f1f6d638..55e0184282 100644 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -160,7 +160,7 @@ image_pressed="BackButton_Press" image_unselected="BackButton_Off" layout="topleft" - left="7" + left="8" name="back_btn" tool_tip="Back" tab_stop="false" @@ -174,7 +174,7 @@ left_pad="10" name="title" text_color="LtGray" - top="2" + top="4" use_ellipses="true" value="Place Profile" width="280" /> diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index 33f895e13a..638e190e8f 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -37,6 +37,7 @@ background_visible="true" left="6" name="Places Tabs" tab_min_width="80" + tab_max_width="157" tab_height="30" tab_group="1" tab_position="top" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index 1c68d59993..a69e8d29b0 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -348,7 +348,7 @@ Busy mode response: </text> <text_editor - control_name="BusyModeResponse2" + control_name="BusyModeResponse" text_readonly_color="LabelDisabledColor" bg_writeable_color="LtGray" use_ellipses="false" diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml index cc5ba334d6..d9030fc0d6 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml @@ -24,7 +24,7 @@ image_unselected="BackButton_Off" layout="topleft" name="back" - left="9" + left="10" tab_stop="false" top="2" width="30" /> @@ -38,10 +38,10 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="5" name="user_name" text_color="LtGray" - top="0" + top="2" value="(Loading...)" use_ellipses="true" width="275" /> diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index ae08a13793..e189d11d35 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -92,6 +92,7 @@ width="333"> layout="topleft" left="265" name="edit_outfit_btn" + tool_tip="Edit this outfit" top="7" width="30" /> <loading_indicator @@ -144,7 +145,7 @@ width="333"> left="5" min_height="410" name="panel_outfit_edit" - top="5" + top="2" visible="false" width="320"/> <panel diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml index c816fd1479..e2bd6f375e 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -55,10 +55,10 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="3" name="title" text_color="LtGray" - top="0" + top="2" use_ellipses="true" value="Object Profile" width="275" /> @@ -395,7 +395,7 @@ top_pad="10" label_width="75" left="120" width="170" - min_val="1" + min_val="0" height="23" max_val="999999999" top_pad="10"/> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index d73f11c4e0..d270e14914 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3182,12 +3182,12 @@ Abuse Report</string> <!-- language specific white-space characters, delimiters, spacers, item separation symbols --> <string name="sentences_separator" value=" "></string> - <string name="words_separator">, </string> + <string name="words_separator" value=", "/> <string name="server_is_down"> Despite our best efforts, something unexpected has gone wrong. - Please check secondlife.com/status to see if there is a known problem with the service. + Please check status.secondlifegrid.net to see if there is a known problem with the service. If you continue to experience problems, please check your network and firewall setup. </string> diff --git a/indra/newview/skins/default/xui/en/widgets/accordion.xml b/indra/newview/skins/default/xui/en/widgets/accordion.xml index b817ba56ca..05d7447a6f 100644 --- a/indra/newview/skins/default/xui/en/widgets/accordion.xml +++ b/indra/newview/skins/default/xui/en/widgets/accordion.xml @@ -8,7 +8,6 @@ height="100" h_pad="10" name="no_visible_items_msg" - value="There are no visible content here." v_pad="15" width="200" wrap="true "/> diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml index 55e699612c..026b7b7616 100644 --- a/indra/newview/skins/default/xui/it/floater_about.xml +++ b/indra/newview/skins/default/xui/it/floater_about.xml @@ -27,9 +27,9 @@ Scheda grafica: [GRAPHICS_CARD] Versione libcurl: [LIBCURL_VERSION] Versione J2C Decoder: [J2C_VERSION] -Versione Audio Driver: [AUDIO_DRIVER_VERSION] +Versione Driver audio: [AUDIO_DRIVER_VERSION] Versione Qt Webkit: [QT_WEBKIT_VERSION] -Versione Vivox: [VIVOX_VERSION] +Versione Server voice: [VOICE_VERSION] </floater.string> <floater.string name="none"> (nessuno) diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml index c55f79738e..942b79b7d3 100644 --- a/indra/newview/skins/default/xui/it/floater_about_land.xml +++ b/indra/newview/skins/default/xui/it/floater_about_land.xml @@ -63,6 +63,9 @@ Nessun appezzamento selezionato. Vai al menu Mondo > Informazioni sul terreno oppure seleziona un altro appezzamento per vederne i dettagli. </panel.string> + <panel.string name="time_stamp_template"> + [wkday,datetime,local] [day,datetime,local] [mth,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] + </panel.string> <text name="Name:"> Nome: </text> diff --git a/indra/newview/skins/default/xui/it/floater_avatar_textures.xml b/indra/newview/skins/default/xui/it/floater_avatar_textures.xml index 2935f0fdb6..b6376973cd 100644 --- a/indra/newview/skins/default/xui/it/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/it/floater_avatar_textures.xml @@ -3,41 +3,48 @@ <floater.string name="InvalidAvatar"> AVATAR NON VALIDO </floater.string> - <text name="composite_label"> - Texture Composite - </text> - <button label="Deposito" label_selected="Deposito" name="Dump"/> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> - <texture_picker label="Capigliature" name="hair-baked"/> - <texture_picker label="Capigliature" name="hair_grain"/> - <texture_picker label="Alpha dei capelli" name="hair_alpha"/> - <texture_picker label="Testa" name="head-baked"/> - <texture_picker label="Makeup" name="head_bodypaint"/> - <texture_picker label="Alpha della testa" name="head_alpha"/> - <texture_picker label="Tatuaggio della testa" name="head_tattoo"/> - <texture_picker label="Occhi" name="eyes-baked"/> - <texture_picker label="Occhio" name="eyes_iris"/> - <texture_picker label="Alpha degli occhi" name="eyes_alpha"/> - <texture_picker label="Parte superiore del corpo" name="upper-baked"/> - <texture_picker label="Bodypaint parte superiore del corpo" name="upper_bodypaint"/> - <texture_picker label="Maglietta intima" name="upper_undershirt"/> - <texture_picker label="Guanti" name="upper_gloves"/> - <texture_picker label="Camicia" name="upper_shirt"/> - <texture_picker label="Parte superiore della giacca" name="upper_jacket"/> - <texture_picker label="Alpha superiore" name="upper_alpha"/> - <texture_picker label="Tatuaggio superiore" name="upper_tattoo"/> - <texture_picker label="Parte inferiore del corpo" name="lower-baked"/> - <texture_picker label="Bodypaint parte inferiore del corpo" name="lower_bodypaint"/> - <texture_picker label="Slip" name="lower_underpants"/> - <texture_picker label="Calzini" name="lower_socks"/> - <texture_picker label="Scarpe" name="lower_shoes"/> - <texture_picker label="Pantaloni" name="lower_pants"/> - <texture_picker label="Giacca" name="lower_jacket"/> - <texture_picker label="Alpha inferiore" name="lower_alpha"/> - <texture_picker label="Tattuaggio inferiore" name="lower_tattoo"/> - <texture_picker label="Gonna" name="skirt-baked"/> - <texture_picker label="Gonna" name="skirt"/> + <text name="label"> + Baking delle +texture + </text> + <text name="composite_label"> + Composito +Texture + </text> + <button label="Memorizza gli ID sulla console" label_selected="Dump" name="Dump"/> + <panel name="scroll_content_panel"> + <texture_picker label="Capigliature" name="hair-baked"/> + <texture_picker label="Capigliature" name="hair_grain"/> + <texture_picker label="Alpha dei capelli" name="hair_alpha"/> + <texture_picker label="Testa" name="head-baked"/> + <texture_picker label="Makeup" name="head_bodypaint"/> + <texture_picker label="Alpha della testa" name="head_alpha"/> + <texture_picker label="Tatuaggio della testa" name="head_tattoo"/> + <texture_picker label="Occhi" name="eyes-baked"/> + <texture_picker label="Occhio" name="eyes_iris"/> + <texture_picker label="Alpha degli occhi" name="eyes_alpha"/> + <texture_picker label="Parte superiore del corpo" name="upper-baked"/> + <texture_picker label="Bodypaint parte superiore del corpo" name="upper_bodypaint"/> + <texture_picker label="Maglietta intima" name="upper_undershirt"/> + <texture_picker label="Guanti" name="upper_gloves"/> + <texture_picker label="Camicia" name="upper_shirt"/> + <texture_picker label="Parte superiore della giacca" name="upper_jacket"/> + <texture_picker label="Alpha superiore" name="upper_alpha"/> + <texture_picker label="Tatuaggio superiore" name="upper_tattoo"/> + <texture_picker label="Parte inferiore del corpo" name="lower-baked"/> + <texture_picker label="BodyPaint parte inferiore del corpo" name="lower_bodypaint"/> + <texture_picker label="Slip" name="lower_underpants"/> + <texture_picker label="Calzini" name="lower_socks"/> + <texture_picker label="Scarpe" name="lower_shoes"/> + <texture_picker label="Pantaloni" name="lower_pants"/> + <texture_picker label="Giacca" name="lower_jacket"/> + <texture_picker label="Alpha inferiore" name="lower_alpha"/> + <texture_picker label="Tattuaggio inferiore" name="lower_tattoo"/> + <texture_picker label="Gonna" name="skirt-baked"/> + <texture_picker label="Gonna" name="skirt"/> + </panel> </panel> </scroll_container> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency_html.xml b/indra/newview/skins/default/xui/it/floater_buy_currency_html.xml new file mode 100644 index 0000000000..4a1bf33403 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_buy_currency_html.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_buy_currency_html" title="ACQUISTA VALUTA"/> diff --git a/indra/newview/skins/default/xui/it/floater_map.xml b/indra/newview/skins/default/xui/it/floater_map.xml index 70ab8dcb5a..d1e9c98e79 100644 --- a/indra/newview/skins/default/xui/it/floater_map.xml +++ b/indra/newview/skins/default/xui/it/floater_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Map" title="Mini mappa"> +<floater name="Map" title=""> <floater.string name="mini_map_north"> N </floater.string> diff --git a/indra/newview/skins/default/xui/it/floater_moveview.xml b/indra/newview/skins/default/xui/it/floater_moveview.xml index 26d861c566..cdafdb0089 100644 --- a/indra/newview/skins/default/xui/it/floater_moveview.xml +++ b/indra/newview/skins/default/xui/it/floater_moveview.xml @@ -6,18 +6,48 @@ <string name="walk_back_tooltip"> Cammina indietro (premi freccia giù o S) </string> + <string name="walk_left_tooltip"> + Cammina a sinistra (premi Maiusc + freccia sinistra o A) + </string> + <string name="walk_right_tooltip"> + Cammina a destra (premi Maiusc + freccia destra o D) + </string> <string name="run_forward_tooltip"> Corri in avanti (premi freccia su o W) </string> <string name="run_back_tooltip"> Corri indietro (premi freccia giù o S) </string> + <string name="run_left_tooltip"> + Corri a sinistra (premi Maiusc + freccia sinistra o A) + </string> + <string name="run_right_tooltip"> + Corri a destra (premi Maiusc + freccia destra o D) + </string> <string name="fly_forward_tooltip"> Vola in avanti (premi freccia su o W) </string> <string name="fly_back_tooltip"> Vola indietro (premi freccia giù o S) </string> + <string name="fly_left_tooltip"> + Vola a sinistra (premi Maiusc + freccia sinistra o A) + </string> + <string name="fly_right_tooltip"> + Vola a destra (premi Maiusc + freccia destra o D) + </string> + <string name="fly_up_tooltip"> + Vola in alto (premi E) + </string> + <string name="fly_down_tooltip"> + Vola in basso (premi C) + </string> + <string name="jump_tooltip"> + Salta (premi E) + </string> + <string name="crouch_tooltip"> + Accovacciarsi (premi C) + </string> <string name="walk_title"> Cammina </string> @@ -28,10 +58,12 @@ Vola </string> <panel name="panel_actions"> + <button label="" label_selected="" name="move up btn" tool_tip="Vola in alto (premi E)"/> <button label="" label_selected="" name="turn left btn" tool_tip="Gira a sinistra (premi freccia sinistra o A)"/> + <joystick_slide name="move left btn" tool_tip="Cammina a sinistra (premi Maiusc + freccia sinistra o A)"/> + <button label="" label_selected="" name="move down btn" tool_tip="Vola in basso (premi C)"/> <button label="" label_selected="" name="turn right btn" tool_tip="Gira a destra (premi freccia destra o D)"/> - <button label="" label_selected="" name="move up btn" tool_tip="Vola in alto, premi E"/> - <button label="" label_selected="" name="move down btn" tool_tip="Vola in basso, premi C"/> + <joystick_slide name="move right btn" tool_tip="Cammina a destra (premi Maiusc + freccia destra o D)"/> <joystick_turn name="forward btn" tool_tip="Cammina in avanti (premi freccia su o W)"/> <joystick_turn name="backward btn" tool_tip="Cammina indietro (premi freccia giù o S)"/> </panel> diff --git a/indra/newview/skins/default/xui/it/floater_preview_notecard.xml b/indra/newview/skins/default/xui/it/floater_preview_notecard.xml index 70e28dde35..7ec229f9d3 100644 --- a/indra/newview/skins/default/xui/it/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/it/floater_preview_notecard.xml @@ -9,9 +9,6 @@ <floater.string name="Title"> Biglietto: [NAME] </floater.string> - <floater.string label="Salva" label_selected="Salva" name="Save"> - Salva - </floater.string> <text name="desc txt"> Descrizione: </text> @@ -19,4 +16,5 @@ In caricamento... </text_editor> <button label="Salva" label_selected="Salva" name="Save"/> + <button label="Elimina" label_selected="Elimina" name="Delete"/> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_tools.xml b/indra/newview/skins/default/xui/it/floater_tools.xml index 04d61b97ff..68d193ff33 100644 --- a/indra/newview/skins/default/xui/it/floater_tools.xml +++ b/indra/newview/skins/default/xui/it/floater_tools.xml @@ -67,9 +67,9 @@ <text name="RenderingCost" tool_tip="Mostra il costo di rendering calcolato per questo oggetto"> þ: [COUNT] </text> - <check_box name="checkbox uniform"/> - <text name="checkbox uniform label"> - Ridimens. simmetricamente + <check_box label="" name="checkbox uniform"/> + <text label="Allunga entrambi i lati" name="checkbox uniform label"> + Allunga entrambi i lati </text> <check_box initial_value="true" label="Ridimensiona le texture" name="checkbox stretch textures"/> <check_box initial_value="true" label="Posiziona nella griglia" name="checkbox snap to grid"/> @@ -445,8 +445,8 @@ <check_box label="Inverti" name="checkbox flip s"/> <spinner label="Verticale (V)" name="TexScaleV"/> <check_box label="Inverti" name="checkbox flip t"/> - <spinner label="RotazioneËš" name="TexRot" /> - <spinner label="Ripetizioni / Metro" name="rptctrl" /> + <spinner label="RotazioneËš" name="TexRot"/> + <spinner label="Ripetizioni / Metro" name="rptctrl"/> <button label="Applica" label_selected="Applica" name="button apply"/> <text name="tex offset"> Bilanciamento della texture diff --git a/indra/newview/skins/default/xui/it/menu_attachment_self.xml b/indra/newview/skins/default/xui/it/menu_attachment_self.xml index 054f4802e6..c480a2fe0e 100644 --- a/indra/newview/skins/default/xui/it/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/it/menu_attachment_self.xml @@ -5,7 +5,7 @@ <menu_item_call label="Stacca" name="Detach"/> <menu_item_call label="Lascia" name="Drop"/> <menu_item_call label="Alzati" name="Stand Up"/> - <menu_item_call label="Il mio aspetto" name="Appearance..."/> + <menu_item_call label="Cambia vestiario" name="Change Outfit"/> <menu_item_call label="I miei amici..." name="Friends..."/> <menu_item_call label="I miei gruppi" name="Groups..."/> <menu_item_call label="Il mio profilo" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/it/menu_avatar_self.xml b/indra/newview/skins/default/xui/it/menu_avatar_self.xml index d73d97d499..7796d41286 100644 --- a/indra/newview/skins/default/xui/it/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/it/menu_avatar_self.xml @@ -20,7 +20,9 @@ <context_menu label="Stacca â–¶" name="Object Detach"/> <menu_item_call label="Stacca tutto" name="Detach All"/> </context_menu> - <menu_item_call label="Il mio aspetto" name="Appearance..."/> + <menu_item_call label="Cambia vestiario" name="Chenge Outfit"/> + <menu_item_call label="Modifica il mio vestiario" name="Edit Outfit"/> + <menu_item_call label="Modifica la figura corporea" name="Edit My Shape"/> <menu_item_call label="I miei amici..." name="Friends..."/> <menu_item_call label="I miei gruppi" name="Groups..."/> <menu_item_call label="Il mio profilo" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/it/menu_bottomtray.xml b/indra/newview/skins/default/xui/it/menu_bottomtray.xml index 7203d002d2..8ca5b24b48 100644 --- a/indra/newview/skins/default/xui/it/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/it/menu_bottomtray.xml @@ -4,6 +4,11 @@ <menu_item_check label="Tasto Movimento" name="ShowMoveButton"/> <menu_item_check label="Tasto Visuale" name="ShowCameraButton"/> <menu_item_check label="Tasto Foto" name="ShowSnapshotButton"/> + <menu_item_check label="Pulsante barra laterale" name="ShowSidebarButton"/> + <menu_item_check label="Pulsante Costruisci" name="ShowBuildButton"/> + <menu_item_check label="Pulsante Cerca" name="ShowSearchButton"/> + <menu_item_check label="Pulsante Mappa" name="ShowWorldMapButton"/> + <menu_item_check label="Pulsante Mini mappa" name="ShowMiniMapButton"/> <menu_item_call label="Taglia" name="NearbyChatBar_Cut"/> <menu_item_call label="Copia" name="NearbyChatBar_Copy"/> <menu_item_call label="Incolla" name="NearbyChatBar_Paste"/> diff --git a/indra/newview/skins/default/xui/it/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/it/menu_inspect_self_gear.xml index 33229bb7c0..80edae8a2b 100644 --- a/indra/newview/skins/default/xui/it/menu_inspect_self_gear.xml +++ b/indra/newview/skins/default/xui/it/menu_inspect_self_gear.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <menu name="Gear Menu"> <menu_item_call label="Alzati" name="stand_up"/> - <menu_item_call label="Il mio aspetto" name="my_appearance"/> + <menu_item_call label="Cambia vestiario" name="change_outfit"/> <menu_item_call label="Il mio profilo" name="my_profile"/> <menu_item_call label="I miei amici..." name="my_friends"/> <menu_item_call label="I miei gruppi" name="my_groups"/> diff --git a/indra/newview/skins/default/xui/it/menu_inventory.xml b/indra/newview/skins/default/xui/it/menu_inventory.xml index 3b36198774..b127f8b816 100644 --- a/indra/newview/skins/default/xui/it/menu_inventory.xml +++ b/indra/newview/skins/default/xui/it/menu_inventory.xml @@ -54,6 +54,7 @@ <menu_item_call label="Elimina oggetto" name="Purge Item"/> <menu_item_call label="Ripristina oggetto" name="Restore Item"/> <menu_item_call label="Apri" name="Open"/> + <menu_item_call label="Apri originale" name="Open Original"/> <menu_item_call label="Proprietà " name="Properties"/> <menu_item_call label="Rinomina" name="Rename"/> <menu_item_call label="Copia UUID dell'oggetto" name="Copy Asset UUID"/> diff --git a/indra/newview/skins/default/xui/it/menu_login.xml b/indra/newview/skins/default/xui/it/menu_login.xml index 904b819198..0a6d803058 100644 --- a/indra/newview/skins/default/xui/it/menu_login.xml +++ b/indra/newview/skins/default/xui/it/menu_login.xml @@ -2,7 +2,7 @@ <menu_bar name="Login Menu"> <menu label="Io" name="File"> <menu_item_call label="Preferenze" name="Preferences..."/> - <menu_item_call label="Chiudi" name="Quit"/> + <menu_item_call label="Esci da [APP_NAME]" name="Quit"/> </menu> <menu label="Aiuto" name="Help"> <menu_item_call label="Aiuto di [SECOND_LIFE]" name="Second Life Help"/> diff --git a/indra/newview/skins/default/xui/it/menu_participant_list.xml b/indra/newview/skins/default/xui/it/menu_participant_list.xml index 71f1a9a0da..f70b886a1e 100644 --- a/indra/newview/skins/default/xui/it/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/it/menu_participant_list.xml @@ -14,8 +14,8 @@ <context_menu label="Opzioni moderatore >" name="Moderator Options"> <menu_item_check label="Consenti chat di testo" name="AllowTextChat"/> <menu_item_call label="Disattiva audio di questo participante" name="ModerateVoiceMuteSelected"/> - <menu_item_call label="Disattiva audio di tutti gli altri" name="ModerateVoiceMuteOthers"/> <menu_item_call label="Riattiva audio di questo participante" name="ModerateVoiceUnMuteSelected"/> - <menu_item_call label="Riattiva audio di tutti gli altri" name="ModerateVoiceUnMuteOthers"/> + <menu_item_call label="Disattiva audio di tutti" name="ModerateVoiceMute"/> + <menu_item_call label="Riattiva audio di tutti" name="ModerateVoiceUnmute"/> </context_menu> </context_menu> diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml index a5923ac42b..999f89a80d 100644 --- a/indra/newview/skins/default/xui/it/menu_viewer.xml +++ b/indra/newview/skins/default/xui/it/menu_viewer.xml @@ -7,7 +7,7 @@ </menu_item_call> <menu_item_call label="Compra L$" name="Buy and Sell L$"/> <menu_item_call label="Il mio profilo" name="Profile"/> - <menu_item_call label="Il mio aspetto" name="Appearance"/> + <menu_item_call label="Cambia vestiario" name="ChangeOutfit"/> <menu_item_check label="Il mio inventario" name="Inventory"/> <menu_item_check label="Il mio inventario" name="ShowSidetrayInventory"/> <menu_item_check label="Le mie gesture" name="Gestures"/> @@ -162,6 +162,7 @@ <menu_item_check label="Oggetti flessibili" name="Flexible Objects"/> </menu> <menu_item_check label="Esegui thread multipli" name="Run Multiple Threads"/> + <menu_item_check label="Usa thread lettura plugin" name="Use Plugin Read Thread"/> <menu_item_call label="Pulisci cache di gruppo" name="ClearGroupCache"/> <menu_item_check label="Fluidità mouse" name="Mouse Smoothing"/> <menu label="Scorciatoie" name="Shortcuts"> @@ -188,7 +189,6 @@ <menu_item_call label="Zoom avanti" name="Zoom In"/> <menu_item_call label="Zoom predefinito" name="Zoom Default"/> <menu_item_call label="Zoom indietro" name="Zoom Out"/> - <menu_item_call label="Alterna schermo intero" name="Toggle Fullscreen"/> </menu> <menu_item_call label="Mostra impostazioni di debug" name="Debug Settings"/> <menu_item_check label="Mostra menu sviluppo" name="Debug Mode"/> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 4739e5cce9..058353da38 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -326,6 +326,9 @@ Hai bisogno di un account per entrare in [SECOND_LIFE]. Ne vuoi creare uno adess </url> <usetemplate name="okcancelbuttons" notext="Riprova" yestext="Crea un nuovo account"/> </notification> + <notification name="InvalidCredentialFormat"> + Immetti sia il nome che il cognome del tuo avatar nel campo del nome utente, quindi effettua l'accesso. + </notification> <notification name="AddClassified"> L'inserzione comparirà nella sezione 'Annunci' della Ricerca e su [http://secondlife.com/community/classifieds secondlife.com] per una settimana. Compila la tua inserzione, quindi clicca 'Pubblica...' per aggiungerla all'elenco degli annunci. @@ -608,6 +611,11 @@ Attese [VALIDS] <notification name="CannotEncodeFile"> Impossibile codificare il file: [FILE] </notification> + <notification name="CorruptedProtectedDataStore"> + Poiché non è possibile leggere i dati protetti, ora verranno ripristinati. + Ciò può succedere alla modifica delle impostazioni di rete. + <usetemplate name="okbutton" yestext="OK"/> + </notification> <notification name="CorruptResourceFile"> File risorsa corrotto: [FILE] </notification> @@ -968,6 +976,12 @@ su TUTTI I TERRENI di questa sim? Introduci un prezzo più alto. </notification> + <notification name="ConfirmItemDeleteHasLinks"> + Almeno uno degli oggetti selezionati è collegato tramite link ad altri oggetti. Se elimini l'oggetto, i relativi link non funzioneranno più. Pertanto si consiglia vivamente di eliminare prima i link. + +Sei sicuro di volere eliminare gli oggetti? + <usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/> + </notification> <notification name="ConfirmObjectDeleteLock"> Almeno uno degli elementi selezionati è bloccato. @@ -1117,6 +1131,42 @@ Premi F1 in qualunque momento per la guida o per apprendere altre cose di [SECON Scegli un avatar maschile o femminile. Puoi sempre cambiare idea più tardi. <usetemplate name="okcancelbuttons" notext="Femminile" yestext="Maschile"/> </notification> + <notification name="CantTeleportToGrid"> + Impossibile effettuare il teleport su [SLURL], in quanto si trova su una griglia ([GRID]) diversa da quella attuale ([CURRENT_GRID]). Chiudi il viewer e prova nuovamente. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="GeneralCertificateError"> + Impossibile collegarsi al server. +[REASON] + +Nome oggetto: [SUBJECT_NAME_STRING] +Nome emittente: [ISSUER_NAME_STRING] +Valido da: [VALID_FROM] +Valido fino a: [VALID_TO] +Impronta MD5: [SHA1_DIGEST] +Impronta SHA1: [MD5_DIGEST] +Uso chiave: [KEYUSAGE] +Uso chiave estesa: [EXTENDEDKEYUSAGE] +Identificatore chiave oggetto: [SUBJECTKEYIDENTIFIER] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="TrustCertificateError"> + Autorità di certificazione di questo server sconosciuta. + +Informazioni sul certificato: +Nome oggetto: [SUBJECT_NAME_STRING] +Nome emittente: [ISSUER_NAME_STRING] +Valido da: [VALID_FROM] +Valido fino a: [VALID_TO] +Impronta MD5: [SHA1_DIGEST] +Impronta SHA1: [MD5_DIGEST] +Uso chiave: [KEYUSAGE] +Uso chiave estesa: [EXTENDEDKEYUSAGE] +Identificatore chiave oggetto: [SUBJECTKEYIDENTIFIER] + +Accettare questa autorità ? + <usetemplate name="okcancelbuttons" notext="Annulla" yestext="Accetta"/> + </notification> <notification name="NotEnoughCurrency"> [NAME] [PRICE]L$ Non hai abbastanza L$ per farlo. </notification> @@ -1512,7 +1562,7 @@ Vuoi andare alla Knowledge Base per ulteriori informazioni sulle categorie di ac <notification name="RegionEntryAccessBlocked_Change"> Non ti è consentito entrare in quella regione a causa della tua categoria di accesso impostata nelle preferenze. -Puoi cliccare su Cambia preferenze per modificare la categoria di accesso e quindi riuscire ad entrare. Da adesso potrai accedere ai contenuti [REGIONMATURITY] ed effettuare ricerche in questa categoria. Se in seguito tu volessi cambiare di nuovo le tue impostazioni, apri la finestra di dialogo da Io > Preferenze > Generale. +Clicca su Cambia preferenze per modificare la categoria di accesso e potere entrare subito. Ciò ti consentirà di effettuare ricerche di contenuti di categoria [REGIONMATURITY]. Potrai modificare queste impostazioni in un secondo momento da Io > Preferenze > Generali. <form name="form"> <button name="OK" text="Cambia preferenza"/> <button default="true" name="Cancel" text="Chiudi"/> @@ -2283,15 +2333,6 @@ Riprova tra qualche istante. <button name="Mute" text="Blocca"/> </form> </notification> - <notification name="ObjectGiveItemUnknownUser"> - Un oggetto chiamato [OBJECTFROMNAME] di proprietà di (residente sconosciuto) ti ha dato questo [OBJECTTYPE]: -[ITEM_SLURL] - <form name="form"> - <button name="Keep" text="Prendi"/> - <button name="Discard" text="Rifiuta"/> - <button name="Mute" text="Blocca"/> - </form> - </notification> <notification name="UserGiveItem"> [NAME_SLURL] ti ha dato questo [OBJECTTYPE]: [ITEM_SLURL] @@ -2604,8 +2645,52 @@ Il pulsante verrà visualizzato quando lo spazio sarà sufficiente. <notification name="ShareNotification"> Trascina articoli dell'inventario su una persona nel selettore residenti </notification> + <notification name="DeedToGroupFail"> + Cessione al gruppo non riuscita. + </notification> <notification name="AvatarRezNotification"> - Avatar '[NAME]' rezzato in [TIME] secondi. + ( presente da [EXISTENCE] secondi ) +Nuvola avatar '[NAME]' risolta in [TIME] secondi. + </notification> + <notification name="AvatarRezSelfNotification"> + ( presente da [EXISTENCE] secondi ) +Baking dei vestiti eseguito in [TIME] secondi. + </notification> + <notification name="AvatarRezCloudNotification"> + ( presente da [EXISTENCE] secondi ) +Avatar '[NAME]' trasformato in nuvola. + </notification> + <notification name="AvatarRezArrivedNotification"> + ( presente da [EXISTENCE] secondi ) +È comparso l'avatar '[NAME]'. + </notification> + <notification name="AvatarRezLeftCloudNotification"> + ( presente da [EXISTENCE] secondi ) +Avatar '[NAME]' partito dopo [TIME] secondi sotto forma di nuvola. + </notification> + <notification name="AvatarRezEnteredAppearanceNotification"> + ( presente da [EXISTENCE] secondi ) +Avatar '[NAME]' è entrato nella modalità aspetto. + </notification> + <notification name="AvatarRezLeftAppearanceNotification"> + ( presente da [EXISTENCE] secondi ) +Avatar '[NAME]' ha lasciato la modalità aspetto. + </notification> + <notification name="AvatarRezLeftNotification"> + ( presente da [EXISTENCE] secondi ) +Avatar '[NAME]' è partito completamente caricato. + </notification> + <notification name="ConfirmLeaveCall"> + Sei sicuro di volere uscire dalla chiamata? + <usetemplate ignoretext="Conferma prima di uscire dalla chiamata" name="okcancelignore" notext="No" yestext="Sì"/> + </notification> + <notification name="ConfirmMuteAll"> + Hai scelto di disattivare l'audio di tutti i partecipanti alla chiamata di gruppo. +In questo modo verrà disattivato l'audio anche di tutti i residenti che si +uniscono alla chiamata in un secondo momento, anche dopo che tu ti fossi scollegato. + +Disattiva audio di tutti? + <usetemplate ignoretext="Conferma prima di disattivare l'audio di tutti i partecipanti alla chiamata di gruppo" name="okcancelignore" notext="Ok" yestext="Annulla"/> </notification> <global name="UnsupportedCPU"> - La velocità della tua CPU non soddisfa i requisiti minimi. diff --git a/indra/newview/skins/default/xui/it/panel_body_parts_list_item.xml b/indra/newview/skins/default/xui/it/panel_body_parts_list_item.xml new file mode 100644 index 0000000000..de764d8025 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_body_parts_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="wearable_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_bodyparts_list_button_bar.xml b/indra/newview/skins/default/xui/it/panel_bodyparts_list_button_bar.xml new file mode 100644 index 0000000000..8fc23d34f1 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_bodyparts_list_button_bar.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="clothing_list_button_bar_panel"> + <button label="Cambia" name="switch_btn"/> + <button label="Acquista >" name="bodyparts_shop_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_bottomtray.xml b/indra/newview/skins/default/xui/it/panel_bottomtray.xml index c0218fad5e..e4d99cc402 100644 --- a/indra/newview/skins/default/xui/it/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/it/panel_bottomtray.xml @@ -1,11 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="bottom_tray"> - <string name="SpeakBtnToolTip"> - Accende o spegne il microfono - </string> - <string name="VoiceControlBtnToolTip"> - Mostra o nasconde il pannello di regolazione voce - </string> + <string name="SpeakBtnToolTip" value="Accende o spegne il microfono"/> + <string name="VoiceControlBtnToolTip" value="Mostra o nasconde il pannello di regolazione voce"/> <layout_stack name="toolbar_stack"> <layout_panel name="speak_panel"> <talk_button name="talk"> @@ -24,6 +20,21 @@ <layout_panel name="snapshot_panel"> <button label="" name="snapshots" tool_tip="Scatta una foto"/> </layout_panel> + <layout_panel name="sidebar_btn_panel"> + <button label="Barra laterale" name="sidebar_btn" tool_tip="Mostra o nasconde la barra laterale"/> + </layout_panel> + <layout_panel name="build_btn_panel"> + <button label="Costruisci" name="build_btn" tool_tip="Mostra o nasconde gli strumenti di costruzione"/> + </layout_panel> + <layout_panel name="search_btn_panel"> + <button label="Cerca" name="search_btn" tool_tip="Mostra o nasconde la ricerca"/> + </layout_panel> + <layout_panel name="world_map_btn_panel"> + <button label="Mappa" name="world_map_btn" tool_tip="Mostra o nasconde la mappa del mondo"/> + </layout_panel> + <layout_panel name="mini_map_btn_panel"> + <button label="Mini mappa" name="mini_map_btn" tool_tip="Mostra o nasconde la mini mappa"/> + </layout_panel> <layout_panel name="im_well_panel"> <chiclet_im_well name="im_well"> <button name="Unread IM messages" tool_tip="Conversazioni"/> diff --git a/indra/newview/skins/default/xui/it/panel_clothing_list_button_bar.xml b/indra/newview/skins/default/xui/it/panel_clothing_list_button_bar.xml new file mode 100644 index 0000000000..e9d9795b3a --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_clothing_list_button_bar.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="clothing_list_button_bar_panel"> + <button label="Aggiungi +" name="add_btn"/> + <button label="Acquista >" name="clothing_shop_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_clothing_list_item.xml b/indra/newview/skins/default/xui/it/panel_clothing_list_item.xml new file mode 100644 index 0000000000..de764d8025 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_clothing_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="wearable_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_cof_wearables.xml b/indra/newview/skins/default/xui/it/panel_cof_wearables.xml new file mode 100644 index 0000000000..d914a5740f --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_cof_wearables.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="cof_wearables"> + <accordion name="cof_wearables_accordion"> + <accordion_tab name="tab_attachments" title="Allegati"/> + <accordion_tab name="tab_clothing" title="Vestiario"/> + <accordion_tab name="tab_body_parts" title="Parti del corpo"/> + </accordion> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_deletable_wearable_list_item.xml b/indra/newview/skins/default/xui/it/panel_deletable_wearable_list_item.xml new file mode 100644 index 0000000000..91d90a5660 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_deletable_wearable_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="deletable_wearable_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/it/panel_dummy_clothing_list_item.xml new file mode 100644 index 0000000000..6af84de0c7 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_dummy_clothing_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="dummy_clothing_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_edit_shape.xml b/indra/newview/skins/default/xui/it/panel_edit_shape.xml index 7e1ba43756..ab77548f26 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_shape.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_shape.xml @@ -1,14 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="edit_shape_panel"> - <panel name="avatar_sex_panel"> - <text name="gender_text"> - Sesso: - </text> - <radio_group name="sex_radio"> - <radio_item label="Femmina" name="radio"/> - <radio_item label="Maschio" name="radio2"/> - </radio_group> - </panel> + <text name="avatar_height"> + Statura: [HEIGHT] metri + </text> <panel label="Camicia" name="accordion_panel"> <accordion name="wearable_accordion"> <accordion_tab name="shape_body_tab" title="Corpo"/> diff --git a/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml index d8cfa15b25..d76fb62c53 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml @@ -4,5 +4,6 @@ <texture_picker label="Tatuaggio della testa" name="Head Tattoo" tool_tip="Clicca per scegliere una fotografia"/> <texture_picker label="Tatuaggio superiore" name="Upper Tattoo" tool_tip="Clicca per scegliere una fotografia"/> <texture_picker label="Tattuaggio inferiore" name="Lower Tattoo" tool_tip="Clicca per scegliere una fotografia"/> + <color_swatch label="Colore/Tinta" name="Color/Tint" tool_tip="Clicca per aprire il selettore dei colori"/> </panel> </panel> diff --git a/indra/newview/skins/default/xui/it/panel_edit_wearable.xml b/indra/newview/skins/default/xui/it/panel_edit_wearable.xml index 1135a582f5..3d8aa858db 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_wearable.xml @@ -93,6 +93,12 @@ <text name="edit_wearable_title" value="Modifica della figura corporea"/> <panel label="Camicia" name="wearable_type_panel"> <text name="description_text" value="Figura corporea:"/> + <radio_group name="sex_radio"> + <radio_item label="" name="sex_male" tool_tip="Maschio" value="1"/> + <radio_item label="" name="sex_female" tool_tip="Femmina" value="0"/> + </radio_group> + <icon name="male_icon" tool_tip="Maschio"/> + <icon name="female_icon" tool_tip="Femmina"/> </panel> <panel label="gear_buttom_panel" name="gear_buttom_panel"> <button name="friends_viewsort_btn" tool_tip="Opzioni"/> diff --git a/indra/newview/skins/default/xui/it/panel_group_land_money.xml b/indra/newview/skins/default/xui/it/panel_group_land_money.xml index 1e3ef5e657..16cc91cd9d 100644 --- a/indra/newview/skins/default/xui/it/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/it/panel_group_land_money.xml @@ -6,6 +6,9 @@ <panel.string name="cant_view_group_land_text"> Non sei autorizzato a vedere quali terreni appartengono al gruppo. </panel.string> + <panel.string name="epmty_view_group_land_text"> + Nessuna voce + </panel.string> <panel.string name="cant_view_group_accounting_text"> Non sei autorizzato a visionare le informazioni finanziarie del gruppo. </panel.string> diff --git a/indra/newview/skins/default/xui/it/panel_group_notices.xml b/indra/newview/skins/default/xui/it/panel_group_notices.xml index 9dac282de9..8dd945830e 100644 --- a/indra/newview/skins/default/xui/it/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/it/panel_group_notices.xml @@ -40,6 +40,7 @@ Massimo 200 per gruppo al giorno <text name="string"> Trascina e rilascia qui l'oggetto da allegare: </text> + <button label="Inventario" name="open_inventory" tool_tip="Apri l'inventario"/> <button label="Rimuovi" label_selected="Rimuovi allegato" name="remove_attachment" tool_tip="Rimuovi allegato dal tuo avviso"/> <button label="Invia" label_selected="Invia" name="send_notice"/> <group_drop_target name="drop_target" tool_tip="Trascina un oggetto dall'inventario Ãn questa casella per spedirlo con questo avviso. Devi avere i diritti per la copia e il trasferimento per poter allegare l'oggetto."/> diff --git a/indra/newview/skins/default/xui/it/panel_login.xml b/indra/newview/skins/default/xui/it/panel_login.xml index 287e938d57..473bcfa88d 100644 --- a/indra/newview/skins/default/xui/it/panel_login.xml +++ b/indra/newview/skins/default/xui/it/panel_login.xml @@ -8,18 +8,15 @@ </panel.string> <layout_stack name="login_widgets"> <layout_panel name="login"> - <text name="first_name_text"> - Nome: + <text name="username_text"> + Nome utente: </text> - <line_editor label="Nome" name="first_name_edit" tool_tip="[SECOND_LIFE] First Name"/> - <text name="last_name_text"> - Cognome: - </text> - <line_editor label="Cognome" name="last_name_edit" tool_tip="[SECOND_LIFE] Last Name"/> + <line_editor label="Nome utente" name="username_edit" tool_tip="Nome utente [SECOND_LIFE]"/> <text name="password_text"> Password: </text> <check_box label="Ricorda password" name="remember_check"/> + <button label="Accedi" name="connect_btn"/> <text name="start_location_text"> Inizia da: </text> @@ -28,7 +25,6 @@ <combo_box.item label="Casa mia" name="MyHome"/> <combo_box.item label="<Scrivi nome regione>" name="Typeregionname"/> </combo_box> - <button label="Accedi" name="connect_btn"/> </layout_panel> <layout_panel name="links"> <text name="create_new_account_text"> diff --git a/indra/newview/skins/default/xui/it/panel_main_inventory.xml b/indra/newview/skins/default/xui/it/panel_main_inventory.xml index 878daf1e6b..446b51ffa3 100644 --- a/indra/newview/skins/default/xui/it/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/it/panel_main_inventory.xml @@ -9,62 +9,20 @@ <text name="ItemcountText"> Oggetti: </text> - <menu_bar name="Inventory Menu"> - <menu label="File" name="File"> - <menu_item_call label="Apri" name="Open"/> - <menu label="Carica nel server" name="upload"> - <menu_item_call label="Immagine ([COST]L$)..." name="Upload Image"/> - <menu_item_call label="Suono ([COST]L$)..." name="Upload Sound"/> - <menu_item_call label="Animazione ([COST]L$)..." name="Upload Animation"/> - <menu_item_call label="In blocco ([COST]L$ per file)..." name="Bulk Upload"/> - </menu> - <menu_item_call label="Nuova finestra" name="New Window"/> - <menu_item_call label="Mostra filtri" name="Show Filters"/> - <menu_item_call label="Ripristina filtri" name="Reset Current"/> - <menu_item_call label="Chiudi tutte le cartelle" name="Close All Folders"/> - <menu_item_call label="Svuota cestino" name="Empty Trash"/> - <menu_item_call label="Svuota oggetti smarriti" name="Empty Lost And Found"/> - </menu> - <menu label="Crea" name="Create"> - <menu_item_call label="Nuova cartella" name="New Folder"/> - <menu_item_call label="Nuovo script" name="New Script"/> - <menu_item_call label="Nuovo biglietto" name="New Note"/> - <menu_item_call label="Nuova gesture" name="New Gesture"/> - <menu label="Maglietta intima" name="New Clothes"> - <menu_item_call label="Nuova camicia" name="New Shirt"/> - <menu_item_call label="Nuovi pantaloni" name="New Pants"/> - <menu_item_call label="Nuove scarpe" name="New Shoes"/> - <menu_item_call label="Nuove calze" name="New Socks"/> - <menu_item_call label="Nuova giacca" name="New Jacket"/> - <menu_item_call label="Nuova gonna" name="New Skirt"/> - <menu_item_call label="Nuovi guanti" name="New Gloves"/> - <menu_item_call label="Nuova maglietta intima" name="New Undershirt"/> - <menu_item_call label="Nuovi slip" name="New Underpants"/> - <menu_item_call label="Nuovo Alfa (trasparenza)" name="New Alpha"/> - <menu_item_call label="Nuovo tatuaggio" name="New Tattoo"/> - </menu> - <menu label="Nuove parti del corpo" name="New Body Parts"> - <menu_item_call label="Nuova figura corporea" name="New Shape"/> - <menu_item_call label="Nuova pelle" name="New Skin"/> - <menu_item_call label="Nuovi capelli" name="New Hair"/> - <menu_item_call label="Nuovi occhi" name="New Eyes"/> - </menu> - </menu> - <menu label="Ordina" name="Sort"> - <menu_item_check label="In base al nome" name="By Name"/> - <menu_item_check label="In base alla data" name="By Date"/> - <menu_item_check label="Cartelle sempre in base al nome" name="Folders Always By Name"/> - <menu_item_check label="Cartelle di sistema all'inizio" name="System Folders To Top"/> - </menu> - </menu_bar> <filter_editor label="Filtro" name="inventory search editor"/> <tab_container name="inventory filter tabs"> <inventory_panel label="Tutti gli elementi" name="All Items"/> - <inventory_panel label="Elementi recenti" name="Recent Items"/> + <recent_inventory_panel label="Elementi recenti" name="Recent Items"/> </tab_container> - <panel name="bottom_panel"> - <button name="options_gear_btn" tool_tip="Mostra opzioni addizionali"/> - <button name="add_btn" tool_tip="Aggiungi nuovo elemento"/> - <dnd_button name="trash_btn" tool_tip="Rimuovi l'articolo selezionato"/> - </panel> + <layout_stack name="bottom_panel"> + <layout_panel name="options_gear_btn_panel"> + <button name="options_gear_btn" tool_tip="Mostra opzioni addizionali"/> + </layout_panel> + <layout_panel name="add_btn_panel"> + <button name="add_btn" tool_tip="Aggiungi nuovo elemento"/> + </layout_panel> + <layout_panel name="trash_btn_panel"> + <dnd_button name="trash_btn" tool_tip="Rimuovi l'articolo selezionato"/> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/it/panel_outfit_edit.xml b/indra/newview/skins/default/xui/it/panel_outfit_edit.xml index 516181e0e9..bd2202b60e 100644 --- a/indra/newview/skins/default/xui/it/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/it/panel_outfit_edit.xml @@ -2,6 +2,8 @@ <!-- Side tray Outfit Edit panel --> <panel label="Modifica del vestiario" name="outfit_edit"> <string name="No Outfit" value="Nessun vestiario"/> + <string name="unsaved_changes" value="Modifiche non salvate"/> + <string name="now_editing" value="Modifica di"/> <panel.string name="not_available"> (non pert.) </panel.string> @@ -15,24 +17,19 @@ <text name="title" value="Modifica vestiario"/> <panel label="bottom_panel" name="header_panel"> <panel label="bottom_panel" name="outfit_name_and_status"> - <text name="status" value="Modifica..."/> + <text name="status" value="Modifica di..."/> <text name="curr_outfit_name" value="[Current Outfit]"/> </panel> </panel> <layout_stack name="im_panels"> <layout_panel label="Pannello di controllo IM" name="outfit_wearables_panel"> - <scroll_list name="look_items_list"> - <scroll_list.columns label="Articolo look" name="look_item"/> - <scroll_list.columns label="Ordina in base agli articoli del vestiario" name="look_item_sort"/> - </scroll_list> <panel label="bottom_panel" name="edit_panel"/> </layout_panel> <layout_panel name="add_wearables_panel"> - <filter_editor label="Filtro" name="look_item_filter"/> + <text name="add_to_outfit_label" value="Aggiungi al vestiario:"/> <layout_stack name="filter_panels"> - <layout_panel label="Pannello di controllo IM" name="filter_button_panel"> - <text name="add_to_outfit_label" value="Aggiungi al vestiario:"/> - <button label="V" name="filter_button"/> + <layout_panel label="Pannello di controllo IM" name="filter_panel"> + <filter_editor label="Filtro" name="look_item_filter"/> </layout_panel> </layout_stack> <panel label="add_wearables_button_bar" name="add_wearables_button_bar"> diff --git a/indra/newview/skins/default/xui/it/panel_people.xml b/indra/newview/skins/default/xui/it/panel_people.xml index c469da014a..056e424436 100644 --- a/indra/newview/skins/default/xui/it/panel_people.xml +++ b/indra/newview/skins/default/xui/it/panel_people.xml @@ -2,9 +2,9 @@ <!-- Side tray panel --> <panel label="Persone" name="people_panel"> <string name="no_recent_people" value="Nessuna persona recente. Stai cercando persone da frequentare? Prova la [secondlife:///app/search/people Ricerca] o la [secondlife:///app/worldmap Mappa del mondo]."/> - <string name="no_filtered_recent_people" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people Cerca]."/> + <string name="no_filtered_recent_people" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people/[SEARCH_TERM] Cerca]."/> <string name="no_one_near" value="Nessuno vicino. Stai cercando persone da frequentare? Try la [secondlife:///app/search/people Ricerca] o la [secondlife:///app/worldmap Mappa del mondo]."/> - <string name="no_one_filtered_near" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people Cerca]."/> + <string name="no_one_filtered_near" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people/[SEARCH_TERM] Cerca]."/> <string name="no_friends_online" value="Nessun amico online"/> <string name="no_friends" value="Nessun amico"/> <string name="no_friends_msg"> @@ -12,11 +12,11 @@ Stai cercando persone da frequentare? Prova la [secondlife:///app/worldmap Mappa del mondo]. </string> <string name="no_filtered_friends_msg"> - Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people Cerca]. + Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people/[SEARCH_TERM] Cerca]. </string> <string name="people_filter_label" value="Filtro persone"/> <string name="groups_filter_label" value="Filtro gruppi"/> - <string name="no_filtered_groups_msg" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/groups Cerca]."/> + <string name="no_filtered_groups_msg" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/groups/[SEARCH_TERM] Cerca]."/> <string name="no_groups_msg" value="Stai cercando gruppi di cui far parte? Prova [secondlife:///app/search/groups Cerca]."/> <filter_editor label="Filtro" name="filter_input"/> <tab_container name="tabs"> @@ -55,7 +55,7 @@ Stai cercando persone da frequentare? Prova la [secondlife:///app/worldmap Mappa <button label="Profilo" name="view_profile_btn" tool_tip="Mostra immagine, gruppi e altre informazioni del residente"/> <button label="IM" name="im_btn" tool_tip="Apri una sessione messaggio istantaneo"/> <button label="Chiama" name="call_btn" tool_tip="Chiama questo residente"/> - <button label="Condividi" name="share_btn"/> + <button label="Condividi" name="share_btn" tool_tip="Condividi un oggetto dell'inventario"/> <button label="Teleport" name="teleport_btn" tool_tip="Offri teleport"/> <button label="Profilo del gruppo" name="group_info_btn" tool_tip="Mostra informazioni gruppo"/> <button label="Chat di gruppo" name="chat_btn" tool_tip="Apri sessione chat"/> diff --git a/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml index 09e19f4bc0..7c3f32ad7b 100644 --- a/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml @@ -13,6 +13,7 @@ </text> <check_box label="Costruire/Modificare" name="edit_camera_movement" tool_tip="Utilizza il posizionamento automatico della fotocamera entrando o uscendo dalla modalità modifica"/> <check_box label="Aspetto fisico" name="appearance_camera_movement" tool_tip="Utilizza il posizionamento automatico della camera in modalità modifica"/> + <check_box initial_value="1" label="Barra laterale" name="appearance_sidebar_positioning" tool_tip="Utilizza il posizionamento automatico della fotocamera per la barra laterale"/> <check_box label="Visualizzami in modalità soggettiva" name="first_person_avatar_visible"/> <check_box label="Le frecce di direzione mi fanno sempre spostare" name="arrow_keys_move_avatar_check"/> <check_box label="Doppio click e tieni premuto per correre" name="tap_tap_hold_to_run"/> diff --git a/indra/newview/skins/default/xui/it/panel_preferences_chat.xml b/indra/newview/skins/default/xui/it/panel_preferences_chat.xml index 28df9d2e43..fb8ddf607d 100644 --- a/indra/newview/skins/default/xui/it/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/it/panel_preferences_chat.xml @@ -45,6 +45,7 @@ </text> <check_box initial_value="true" label="Simula la battitura tasti quando scrivi" name="play_typing_animation"/> <check_box label="Quando sono OFF-LINE, spediscimi gli IM in una e-mail" name="send_im_to_email"/> + <check_box label="Attiva IM in testo semplice e cronologia chat" name="plain_text_chat_history"/> <text name="show_ims_in_label"> Mostra gli IM in: </text> diff --git a/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml index 5bd0cfb106..37857473aa 100644 --- a/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml @@ -1,8 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="Grafica" name="Display panel"> - <text name="UI Size:"> - Dimensioni UI: - </text> <text name="QualitySpeed"> Qualità e velocità : </text> @@ -52,6 +49,10 @@ m </text> <slider label="Conteggio massimo particelle:" name="MaxParticleCount"/> + <slider label="Distanza visual. max avatar:" name="MaxAvatarDrawDistance"/> + <text name="DrawDistanceMeterText3"> + m + </text> <slider label="Qualità in post-produzione:" name="RenderPostProcess"/> <text name="MeshDetailText"> Dettagli reticolo: diff --git a/indra/newview/skins/default/xui/it/sidepanel_appearance.xml b/indra/newview/skins/default/xui/it/sidepanel_appearance.xml index c2e99b5573..df25772ffb 100644 --- a/indra/newview/skins/default/xui/it/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/it/sidepanel_appearance.xml @@ -1,9 +1,13 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="Vestiario" name="appearance panel"> <string name="No Outfit" value="Nessun vestiario"/> + <string name="Unsaved Changes" value="Modifiche non salvate"/> + <string name="Now Wearing" value="Abbigliamento attuale..."/> <panel name="panel_currentlook"> - <text name="currentlook_title"> - (non salvato) + <button label="M" name="editappearance_btn"/> + <button label="A" name="openoutfit_btn"/> + <text name="currentlook_status"> + (Stato) </text> </panel> <filter_editor label="Filtri per il vestiario" name="Filter"/> diff --git a/indra/newview/skins/default/xui/it/sidepanel_inventory.xml b/indra/newview/skins/default/xui/it/sidepanel_inventory.xml index 8a391c882c..0d862a0ff7 100644 --- a/indra/newview/skins/default/xui/it/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/it/sidepanel_inventory.xml @@ -4,6 +4,7 @@ <panel name="button_panel"> <button label="Profilo" name="info_btn"/> <button label="Condividi" name="share_btn"/> + <button label="Acquisti" name="shop_btn"/> <button label="Indossa" name="wear_btn"/> <button label="Riproduci" name="play_btn"/> <button label="Teleport" name="teleport_btn"/> diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index 9a6c648c8e..67cd4c35b2 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -94,6 +94,24 @@ <string name="LoginDownloadingClothing"> Sto caricando i vestiti... </string> + <string name="InvalidCertificate"> + Il server ha inviato un certificato non valido o errato. Rivolgiti all'amministratore della griglia. + </string> + <string name="CertInvalidHostname"> + Per accedere al server è stato utilizzato un nome host non valido; controlla lo SLURL o il nome host della griglia. + </string> + <string name="CertExpired"> + Il certificato inviato dalla griglia sembra essere scaduto. Controlla l'orologio del sistema o rivolgiti all'amministratore della griglia. + </string> + <string name="CertKeyUsage"> + Impossibile utilizzare per SSl il certificato inviato dal server. Rivolgiti all'amministratore della griglia. + </string> + <string name="CertBasicConstraints"> + Nella catena dei certificati del server erano presenti troppi certificati. Rivolgiti all'amministratore della griglia. + </string> + <string name="CertInvalidSignature"> + Impossibile verificare la firma del certificato inviato dal server della griglia. Rivolgiti all'amministratore della griglia. + </string> <string name="LoginFailedNoNetwork"> Errore di rete: Non è stato possibile stabilire un collegamento, controlla la tua connessione. </string> @@ -825,6 +843,42 @@ <string name="invalid"> non valido </string> + <string name="shirt_not_worn"> + Camicia non indossata + </string> + <string name="pants_not_worn"> + Pantaloni non indossati + </string> + <string name="shoes_not_worn"> + Scarpe non indossate + </string> + <string name="socks_not_worn"> + Calzini non indossati + </string> + <string name="jacket_not_worn"> + Giacca non indossata + </string> + <string name="gloves_not_worn"> + Guanti non indossati + </string> + <string name="undershirt_not_worn"> + Maglietta intima non indossata + </string> + <string name="underpants_not_worn"> + Slip non indossati + </string> + <string name="skirt_not_worn"> + Gonna non indossata + </string> + <string name="alpha_not_worn"> + Alpha non portato + </string> + <string name="tattoo_not_worn"> + Tatuaggio non portato + </string> + <string name="invalid_not_worn"> + non valido + </string> <string name="NewWearable"> Nuovo [WEARABLE_ITEM] </string> @@ -895,7 +949,10 @@ Premi ESC per tornare in visualizzazione normale </string> <string name="InventoryNoMatchingItems"> - Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/all Cerca]. + Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/all/[SEARCH_TERM] Cerca]. + </string> + <string name="PlacesNoMatchingItems"> + Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/places/[SEARCH_TERM] Cerca]. </string> <string name="FavoritesNoMatchingItems"> Trascina qui un punto di riferimento per aggiungerlo ai Preferiti. @@ -925,6 +982,7 @@ <string name="Wave" value="Saluta con la mano"/> <string name="HelloAvatar" value="Ciao, avatar!"/> <string name="ViewAllGestures" value="Visualizza tutto >>"/> + <string name="GetMoreGestures" value="Altre >>"/> <string name="Animations" value="Animazioni,"/> <string name="Calling Cards" value="Biglietti da visita,"/> <string name="Clothing" value="Vestiti,"/> @@ -1537,16 +1595,19 @@ Il residente al quale hai inviato un messaggio è in modalità 'occupato', ovvero ha chiesto di non essere disturbato. Il tuo messaggio comparirà nel suo pannello IM, dove potrà essere letto in un secondo momento. </string> <string name="MuteByName"> - (in base al nome) + (In base al nome) </string> <string name="MuteAgent"> (Residente) </string> <string name="MuteObject"> - (oggetto) + (Oggetto) </string> <string name="MuteGroup"> - (gruppo) + (Gruppo) + </string> + <string name="MuteExternal"> + (esterno) </string> <string name="RegionNoCovenant"> Non esiste alcun regolamento per questa proprietà . @@ -3306,11 +3367,14 @@ Se il messaggio persiste, contatta [SUPPORT_SITE]. <string name="answered_call"> Risposto alla chiamata </string> - <string name="started_call"> - Chiamata vocale iniziata + <string name="you_started_call"> + Hai iniziato una chiamata vocale + </string> + <string name="you_joined_call"> + Ti sei collegato alla chiamata in voce </string> - <string name="joined_call"> - Si è collegato alla chiamata in voce + <string name="name_started_call"> + [NAME] ha iniziato una chiamata vocale </string> <string name="ringing-im"> Collegamento alla chiamata vocale... @@ -3509,6 +3573,90 @@ Segnala abuso <string name="Contents"> Contenuto </string> + <string name="Gesture"> + Gesture + </string> + <string name="Male Gestures"> + Gesture maschili + </string> + <string name="Female Gestures"> + Gesture femminili + </string> + <string name="Other Gestures"> + Altre gesture + </string> + <string name="Speech Gestures"> + Gesture del parlato + </string> + <string name="Common Gestures"> + Gesture comuni + </string> + <string name="Male - Excuse me"> + Maschio - Chiedere scusa + </string> + <string name="Male - Get lost"> + Maschio - Levati dai piedi! + </string> + <string name="Male - Blow kiss"> + Maschio - Butta un bacio + </string> + <string name="Male - Boo"> + Maschio - Bu + </string> + <string name="Male - Bored"> + Maschio - Annoiato + </string> + <string name="Male - Hey"> + Maschio - Ehi + </string> + <string name="Male - Laugh"> + Maschio - Ridere + </string> + <string name="Male - Repulsed"> + Maschio - Disgustato + </string> + <string name="Male - Shrug"> + Maschio - Spallucce + </string> + <string name="Male - Stick tougue out"> + Maschio - Tira fuori la lingua + </string> + <string name="Male - Wow"> + Maschio - Accipicchia + </string> + <string name="FeMale - Excuse me"> + Femmina - Chiedere scusa + </string> + <string name="FeMale - Get lost"> + Femmina - Levati dai piedi! + </string> + <string name="FeMale - Blow kiss"> + Femmina - Butta un bacio + </string> + <string name="FeMale - Boo"> + Femmina - Bu + </string> + <string name="Female - Bored"> + Femmina - Annoiata + </string> + <string name="Female - Hey"> + Femmina - Ehi + </string> + <string name="Female - Laugh"> + Femmina - Ridere + </string> + <string name="Female - Repulsed"> + Femmina - Disgustata + </string> + <string name="Female - Shrug"> + Femmina - Spallucce + </string> + <string name="Female - Stick tougue out"> + Femmina - Tira fuori la lingua + </string> + <string name="Female - Wow"> + Femmina - Accipicchia + </string> <string name="AvatarBirthDateFormat"> [day,datetime,slt]/[mthnum,datetime,slt]/[year,datetime,slt] </string> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 364cfaaf93..06050db627 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -41,9 +41,12 @@ from llmanifest import LLManifest, main, proper_windows_path, path_ancestors class ViewerManifest(LLManifest): def is_packaging_viewer(self): - # This is overridden by the WindowsManifest sub-class, - # which has different behavior if it is not packaging the viewer. - return True + # Some commands, files will only be included + # if we are packaging the viewer on windows. + # This manifest is also used to copy + # files during the build (see copy_w_viewer_manifest + # and copy_l_viewer_manifest targets) + return 'package' in self.args['actions'] def construct(self): super(ViewerManifest, self).construct() @@ -175,13 +178,6 @@ class WindowsManifest(ViewerManifest): else: return ''.join(self.channel().split()) + '.exe' - def is_packaging_viewer(self): - # Some commands, files will only be included - # if we are packaging the viewer on windows. - # This manifest is also used to copy - # files during the build. - return 'package' in self.args['actions'] - def test_msvcrt_and_copy_action(self, src, dst): # This is used to test a dll manifest. # It is used as a temporary override during the construct method @@ -650,7 +646,9 @@ class DarwinManifest(ViewerManifest): if dylibs["llcommon"]: for libfile in ("libapr-1.0.3.7.dylib", "libaprutil-1.0.3.8.dylib", - "libexpat.0.5.0.dylib"): + "libexpat.0.5.0.dylib", + "libexception_handler.dylib", + ): self.path(os.path.join(libdir, libfile), libfile) #libfmodwrapper.dylib @@ -671,7 +669,9 @@ class DarwinManifest(ViewerManifest): for libfile in ("libllcommon.dylib", "libapr-1.0.3.7.dylib", "libaprutil-1.0.3.8.dylib", - "libexpat.0.5.0.dylib"): + "libexpat.0.5.0.dylib", + "libexception_handler.dylib", + ): target_lib = os.path.join('../../..', libfile) self.run_command("ln -sf %(target)r %(link)r" % {'target': target_lib, @@ -902,6 +902,7 @@ class Linux_i686Manifest(LinuxManifest): if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): self.path("libapr-1.so.0") self.path("libaprutil-1.so.0") + self.path("libbreakpad_client.so.0.0.0", "libbreakpad_client.so.0") self.path("libdb-4.2.so") self.path("libcrypto.so.0.9.7") self.path("libexpat.so.1") @@ -939,7 +940,7 @@ class Linux_i686Manifest(LinuxManifest): self.path("libvivoxplatform.so") self.end_prefix("lib") - if self.args['buildtype'].lower() == 'release': + if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" self.run_command("find %(d)r/bin %(d)r/lib -type f | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp index c9e01c8418..2884231299 100644 --- a/indra/win_crash_logger/llcrashloggerwindows.cpp +++ b/indra/win_crash_logger/llcrashloggerwindows.cpp @@ -299,7 +299,6 @@ void LLCrashLoggerWindows::gatherPlatformSpecificFiles() // At this point we're responsive enough the user could click the close button SetCursor(gCursorArrow); mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo(); - mFileMap["CrashLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLifeException.log"); } bool LLCrashLoggerWindows::mainLoop() |