diff --git a/doc/contributions.txt b/doc/contributions.txt index 3b14ce5125ffd0823a401a43c78fe869aaf8fdf8..f21354b4069d4d9516fa8761d39f4721a18e5014 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -219,6 +219,8 @@ Catherine Pfeffer Celierra Darling VWR-1274 VWR-6975 +Coaldust Numbers + VWR-1095 Cron Stardust VWR-10579 Cypren Christenson @@ -364,15 +366,17 @@ JB Kraft Joghert LeSabre VWR-64 Jonathan Yap - STORM-596 STORM-523 + STORM-596 + STORM-615 STORM-616 STORM-679 - STORM-737 + STORM-723 STORM-726 + STORM-737 + STORM-785 STORM-812 VWR-17801 - STORM-785 Kage Pixel VWR-11 Ken March diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index 7ce57a5572336c4927a7f2b6e4e97d4e3aecb745..012d3c2ab204853214cdd09db8f79762c3d6806c 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -10,6 +10,8 @@ if (STANDALONE) set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-mt) set(BOOST_REGEX_LIBRARY boost_regex-mt) set(BOOST_SIGNALS_LIBRARY boost_signals-mt) + set(BOOST_SYSTEM_LIBRARY boost_system-mt) + set(BOOST_FILESYSTEM_LIBRARY boost_filesystem-mt) else (STANDALONE) use_prebuilt_binary(boost) set(Boost_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) @@ -26,6 +28,12 @@ else (STANDALONE) set(BOOST_SIGNALS_LIBRARY optimized libboost_signals-vc71-mt-s-${BOOST_VERSION} debug libboost_signals-vc71-mt-sgd-${BOOST_VERSION}) + set(BOOST_SYSTEM_LIBRARY + optimized libboost_system-vc71-mt-s-${BOOST_VERSION} + debug libboost_system-vc71-mt-sgd-${BOOST_VERSION}) + set(BOOST_FILESYSTEM_LIBRARY + optimized libboost_filesystem-vc71-mt-s-${BOOST_VERSION} + debug libboost_filesystem-vc71-mt-sgd-${BOOST_VERSION}) else (MSVC71) set(BOOST_PROGRAM_OPTIONS_LIBRARY optimized libboost_program_options-vc80-mt-${BOOST_VERSION} @@ -36,14 +44,24 @@ else (STANDALONE) set(BOOST_SIGNALS_LIBRARY optimized libboost_signals-vc80-mt-${BOOST_VERSION} debug libboost_signals-vc80-mt-gd-${BOOST_VERSION}) + set(BOOST_SYSTEM_LIBRARY + optimized libboost_system-vc80-mt-${BOOST_VERSION} + debug libboost_system-vc80-mt-gd-${BOOST_VERSION}) + set(BOOST_FILESYSTEM_LIBRARY + optimized libboost_filesystem-vc80-mt-${BOOST_VERSION} + debug libboost_filesystem-vc80-mt-gd-${BOOST_VERSION}) endif (MSVC71) elseif (DARWIN) set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-xgcc40-mt) set(BOOST_REGEX_LIBRARY boost_regex-xgcc40-mt) set(BOOST_SIGNALS_LIBRARY boost_signals-xgcc40-mt) + set(BOOST_SYSTEM_LIBRARY boost_system-xgcc40-mt) + set(BOOST_FILESYSTEM_LIBRARY boost_filesystem-xgcc40-mt) elseif (LINUX) set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-gcc41-mt) set(BOOST_REGEX_LIBRARY boost_regex-gcc41-mt) set(BOOST_SIGNALS_LIBRARY boost_signals-gcc41-mt) + set(BOOST_SYSTEM_LIBRARY boost_system-gcc41-mt) + set(BOOST_FILESYSTEM_LIBRARY boost_filesystem-gcc41-mt) endif (WINDOWS) endif (STANDALONE) diff --git a/indra/cmake/GetPrerequisites_2_8.cmake b/indra/cmake/GetPrerequisites_2_8.cmake index 5a24842c896af36c13b8897a0285222dbffa2d12..05ec1539ba1bc5842565dbc419b65aef914e7319 100644 --- a/indra/cmake/GetPrerequisites_2_8.cmake +++ b/indra/cmake/GetPrerequisites_2_8.cmake @@ -1,786 +1,786 @@ -# GetPrerequisites.cmake -# -# This script provides functions to list the .dll, .dylib or .so files that an -# executable or shared library file depends on. (Its prerequisites.) -# -# It uses various tools to obtain the list of required shared library files: -# dumpbin (Windows) -# ldd (Linux/Unix) -# otool (Mac OSX) -# -# The following functions are provided by this script: -# gp_append_unique -# is_file_executable -# gp_item_default_embedded_path -# (projects can override with gp_item_default_embedded_path_override) -# gp_resolve_item -# (projects can override with gp_resolve_item_override) -# gp_resolved_file_type -# gp_file_type -# get_prerequisites -# list_prerequisites -# list_prerequisites_by_glob -# -# Requires CMake 2.6 or greater because it uses function, break, return and -# PARENT_SCOPE. - -#============================================================================= -# Copyright 2008-2009 Kitware, Inc. -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distributed this file outside of CMake, substitute the full -# License text for the above reference.) - -# gp_append_unique list_var value -# -# Append value to the list variable ${list_var} only if the value is not -# already in the list. -# -function(gp_append_unique list_var value) - set(contains 0) - - foreach(item ${${list_var}}) - if("${item}" STREQUAL "${value}") - set(contains 1) - break() - endif("${item}" STREQUAL "${value}") - endforeach(item) - - if(NOT contains) - set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE) - endif(NOT contains) -endfunction(gp_append_unique) - - -# is_file_executable file result_var -# -# Return 1 in ${result_var} if ${file} is a binary executable. -# -# Return 0 in ${result_var} otherwise. -# -function(is_file_executable file result_var) - # - # A file is not executable until proven otherwise: - # - set(${result_var} 0 PARENT_SCOPE) - - get_filename_component(file_full "${file}" ABSOLUTE) - string(TOLOWER "${file_full}" file_full_lower) - - # If file name ends in .exe on Windows, *assume* executable: - # - if(WIN32) - if("${file_full_lower}" MATCHES "\\.exe$") - set(${result_var} 1 PARENT_SCOPE) - return() - endif("${file_full_lower}" MATCHES "\\.exe$") - - # A clause could be added here that uses output or return value of dumpbin - # to determine ${result_var}. In 99%+? practical cases, the exe name - # match will be sufficient... - # - endif(WIN32) - - # Use the information returned from the Unix shell command "file" to - # determine if ${file_full} should be considered an executable file... - # - # If the file command's output contains "executable" and does *not* contain - # "text" then it is likely an executable suitable for prerequisite analysis - # via the get_prerequisites macro. - # - if(UNIX) - if(NOT file_cmd) - find_program(file_cmd "file") - endif(NOT file_cmd) - - if(file_cmd) - execute_process(COMMAND "${file_cmd}" "${file_full}" - OUTPUT_VARIABLE file_ov - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - # Replace the name of the file in the output with a placeholder token - # (the string " _file_full_ ") so that just in case the path name of - # the file contains the word "text" or "executable" we are not fooled - # into thinking "the wrong thing" because the file name matches the - # other 'file' command output we are looking for... - # - string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}") - string(TOLOWER "${file_ov}" file_ov) - - #message(STATUS "file_ov='${file_ov}'") - if("${file_ov}" MATCHES "executable") - #message(STATUS "executable!") - if("${file_ov}" MATCHES "text") - #message(STATUS "but text, so *not* a binary executable!") - else("${file_ov}" MATCHES "text") - set(${result_var} 1 PARENT_SCOPE) - return() - endif("${file_ov}" MATCHES "text") - endif("${file_ov}" MATCHES "executable") - else(file_cmd) - message(STATUS "warning: No 'file' command, skipping execute_process...") - endif(file_cmd) - endif(UNIX) -endfunction(is_file_executable) - - -# gp_item_default_embedded_path item default_embedded_path_var -# -# Return the path that others should refer to the item by when the item -# is embedded inside a bundle. -# -# Override on a per-project basis by providing a project-specific -# gp_item_default_embedded_path_override function. -# -function(gp_item_default_embedded_path item default_embedded_path_var) - - # On Windows and Linux, "embed" prerequisites in the same directory - # as the executable by default: - # - set(path "@executable_path") - set(overridden 0) - - # On the Mac, relative to the executable depending on the type - # of the thing we are embedding: - # - if(APPLE) - # - # The assumption here is that all executables in the bundle will be - # in same-level-directories inside the bundle. The parent directory - # of an executable inside the bundle should be MacOS or a sibling of - # MacOS and all embedded paths returned from here will begin with - # "@executable_path/../" and will work from all executables in all - # such same-level-directories inside the bundle. - # - - # By default, embed things right next to the main bundle executable: - # - set(path "@executable_path/../../Contents/MacOS") - - # Embed .dylibs right next to the main bundle executable: - # - if(item MATCHES "\\.dylib$") - set(path "@executable_path/../MacOS") - set(overridden 1) - endif(item MATCHES "\\.dylib$") - - # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS): - # - if(NOT overridden) - if(item MATCHES "[^/]+\\.framework/") - set(path "@executable_path/../Frameworks") - set(overridden 1) - endif(item MATCHES "[^/]+\\.framework/") - endif(NOT overridden) - endif() - - # Provide a hook so that projects can override the default embedded location - # of any given library by whatever logic they choose: - # - if(COMMAND gp_item_default_embedded_path_override) - gp_item_default_embedded_path_override("${item}" path) - endif(COMMAND gp_item_default_embedded_path_override) - - set(${default_embedded_path_var} "${path}" PARENT_SCOPE) -endfunction(gp_item_default_embedded_path) - - -# gp_resolve_item context item exepath dirs resolved_item_var -# -# Resolve an item into an existing full path file. -# -# Override on a per-project basis by providing a project-specific -# gp_resolve_item_override function. -# -function(gp_resolve_item context item exepath dirs resolved_item_var) - set(resolved 0) - set(resolved_item "${item}") - - # Is it already resolved? - # - if(EXISTS "${resolved_item}") - set(resolved 1) - endif(EXISTS "${resolved_item}") - - if(NOT resolved) - if(item MATCHES "@executable_path") - # - # @executable_path references are assumed relative to exepath - # - string(REPLACE "@executable_path" "${exepath}" ri "${item}") - get_filename_component(ri "${ri}" ABSOLUTE) - - if(EXISTS "${ri}") - #message(STATUS "info: embedded item exists (${ri})") - set(resolved 1) - set(resolved_item "${ri}") - else(EXISTS "${ri}") - message(STATUS "warning: embedded item does not exist '${ri}'") - endif(EXISTS "${ri}") - endif(item MATCHES "@executable_path") - endif(NOT resolved) - - if(NOT resolved) - if(item MATCHES "@loader_path") - # - # @loader_path references are assumed relative to the - # PATH of the given "context" (presumably another library) - # - get_filename_component(contextpath "${context}" PATH) - string(REPLACE "@loader_path" "${contextpath}" ri "${item}") - get_filename_component(ri "${ri}" ABSOLUTE) - - if(EXISTS "${ri}") - #message(STATUS "info: embedded item exists (${ri})") - set(resolved 1) - set(resolved_item "${ri}") - else(EXISTS "${ri}") - message(STATUS "warning: embedded item does not exist '${ri}'") - endif(EXISTS "${ri}") - endif(item MATCHES "@loader_path") - endif(NOT resolved) - - if(NOT resolved) - set(ri "ri-NOTFOUND") - find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH) - find_file(ri "${item}" ${exepath} ${dirs} /usr/lib) - if(ri) - #message(STATUS "info: 'find_file' in exepath/dirs (${ri})") - set(resolved 1) - set(resolved_item "${ri}") - set(ri "ri-NOTFOUND") - endif(ri) - endif(NOT resolved) - - if(NOT resolved) - if(item MATCHES "[^/]+\\.framework/") - set(fw "fw-NOTFOUND") - find_file(fw "${item}" - "~/Library/Frameworks" - "/Library/Frameworks" - "/System/Library/Frameworks" - ) - if(fw) - #message(STATUS "info: 'find_file' found framework (${fw})") - set(resolved 1) - set(resolved_item "${fw}") - set(fw "fw-NOTFOUND") - endif(fw) - endif(item MATCHES "[^/]+\\.framework/") - endif(NOT resolved) - - # Using find_program on Windows will find dll files that are in the PATH. - # (Converting simple file names into full path names if found.) - # - if(WIN32) - if(NOT resolved) - set(ri "ri-NOTFOUND") - find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH) - find_program(ri "${item}" PATHS "${exepath};${dirs}") - if(ri) - #message(STATUS "info: 'find_program' in exepath/dirs (${ri})") - set(resolved 1) - set(resolved_item "${ri}") - set(ri "ri-NOTFOUND") - endif(ri) - endif(NOT resolved) - endif(WIN32) - - # Provide a hook so that projects can override item resolution - # by whatever logic they choose: - # - if(COMMAND gp_resolve_item_override) - gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved) - endif(COMMAND gp_resolve_item_override) - - if(NOT resolved) - message(STATUS " -warning: cannot resolve item '${item}' - - possible problems: - need more directories? - need to use InstallRequiredSystemLibraries? - run in install tree instead of build tree? -") -# message(STATUS " -#****************************************************************************** -#warning: cannot resolve item '${item}' -# -# possible problems: -# need more directories? -# need to use InstallRequiredSystemLibraries? -# run in install tree instead of build tree? -# -# context='${context}' -# item='${item}' -# exepath='${exepath}' -# dirs='${dirs}' -# resolved_item_var='${resolved_item_var}' -#****************************************************************************** -#") - endif(NOT resolved) - - set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE) -endfunction(gp_resolve_item) - - -# gp_resolved_file_type original_file file exepath dirs type_var -# -# Return the type of ${file} with respect to ${original_file}. String -# describing type of prerequisite is returned in variable named ${type_var}. -# -# Use ${exepath} and ${dirs} if necessary to resolve non-absolute ${file} -# values -- but only for non-embedded items. -# -# Possible types are: -# system -# local -# embedded -# other -# -function(gp_resolved_file_type original_file file exepath dirs type_var) - #message(STATUS "**") - - if(NOT IS_ABSOLUTE "${original_file}") - message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file") - endif() - - set(is_embedded 0) - set(is_local 0) - set(is_system 0) - - set(resolved_file "${file}") - - if("${file}" MATCHES "^@(executable|loader)_path") - set(is_embedded 1) - endif() - - if(NOT is_embedded) - if(NOT IS_ABSOLUTE "${file}") - gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file) - endif() - - string(TOLOWER "${original_file}" original_lower) - string(TOLOWER "${resolved_file}" lower) - - if(UNIX) - if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/)") - set(is_system 1) - endif() - endif() - - if(APPLE) - if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)") - set(is_system 1) - endif() - endif() - - if(WIN32) - string(TOLOWER "$ENV{SystemRoot}" sysroot) - string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}") - - string(TOLOWER "$ENV{windir}" windir) - string(REGEX REPLACE "\\\\" "/" windir "${windir}") - - if(lower MATCHES "^(${sysroot}/system|${windir}/system|${sysroot}/syswow|${windir}/syswow|(.*/)*msvc[^/]+dll)") - set(is_system 1) - endif() - endif() - - if(NOT is_system) - get_filename_component(original_path "${original_lower}" PATH) - get_filename_component(path "${lower}" PATH) - if("${original_path}" STREQUAL "${path}") - set(is_local 1) - endif() - endif() - endif() - - # Return type string based on computed booleans: - # - set(type "other") - - if(is_system) - set(type "system") - elseif(is_embedded) - set(type "embedded") - elseif(is_local) - set(type "local") - endif() - - #message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'") - #message(STATUS " type: '${type}'") - - if(NOT is_embedded) - if(NOT IS_ABSOLUTE "${resolved_file}") - if(lower MATCHES "^msvc[^/]+dll" AND is_system) - message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'") - else() - message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect") - endif() - endif() - endif() - - set(${type_var} "${type}" PARENT_SCOPE) - - #message(STATUS "**") -endfunction() - - -# gp_file_type original_file file type_var -# -# Return the type of ${file} with respect to ${original_file}. String -# describing type of prerequisite is returned in variable named ${type_var}. -# -# Possible types are: -# system -# local -# embedded -# other -# -function(gp_file_type original_file file type_var) - if(NOT IS_ABSOLUTE "${original_file}") - message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file") - endif() - - get_filename_component(exepath "${original_file}" PATH) - - set(type "") - gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type) - - set(${type_var} "${type}" PARENT_SCOPE) -endfunction(gp_file_type) - - -# get_prerequisites target prerequisites_var exclude_system recurse dirs -# -# Get the list of shared library files required by ${target}. The list in -# the variable named ${prerequisites_var} should be empty on first entry to -# this function. On exit, ${prerequisites_var} will contain the list of -# required shared library files. -# -# target is the full path to an executable file -# -# prerequisites_var is the name of a CMake variable to contain the results -# -# exclude_system is 0 or 1: 0 to include "system" prerequisites , 1 to -# exclude them -# -# recurse is 0 or 1: 0 for direct prerequisites only, 1 for all prerequisites -# recursively -# -# exepath is the path to the top level executable used for @executable_path -# replacment on the Mac -# -# dirs is a list of paths where libraries might be found: these paths are -# searched first when a target without any path info is given. Then standard -# system locations are also searched: PATH, Framework locations, /usr/lib... -# -function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs) - set(verbose 0) - set(eol_char "E") - - if(NOT IS_ABSOLUTE "${target}") - message("warning: target '${target}' is not absolute...") - endif(NOT IS_ABSOLUTE "${target}") - - if(NOT EXISTS "${target}") - message("warning: target '${target}' does not exist...") - endif(NOT EXISTS "${target}") - - # <setup-gp_tool-vars> - # - # Try to choose the right tool by default. Caller can set gp_tool prior to - # calling this function to force using a different tool. - # - if("${gp_tool}" STREQUAL "") - set(gp_tool "ldd") - if(APPLE) - set(gp_tool "otool") - endif(APPLE) - if(WIN32) - set(gp_tool "dumpbin") - endif(WIN32) - endif("${gp_tool}" STREQUAL "") - - set(gp_tool_known 0) - - if("${gp_tool}" STREQUAL "ldd") - set(gp_cmd_args "") - set(gp_regex "^[\t ]*[^\t ]+ => ([^\t ]+).*${eol_char}$") - set(gp_regex_cmp_count 1) - set(gp_tool_known 1) - endif("${gp_tool}" STREQUAL "ldd") - - if("${gp_tool}" STREQUAL "otool") - set(gp_cmd_args "-L") - set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$") - set(gp_regex_cmp_count 3) - set(gp_tool_known 1) - endif("${gp_tool}" STREQUAL "otool") - - if("${gp_tool}" STREQUAL "dumpbin") - set(gp_cmd_args "/dependents") - set(gp_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$") - set(gp_regex_cmp_count 1) - set(gp_tool_known 1) - set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE. - endif("${gp_tool}" STREQUAL "dumpbin") - - if(NOT gp_tool_known) - message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...") - message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'") - message(STATUS "Valid gp_tool values are dumpbin, ldd and otool.") - return() - endif(NOT gp_tool_known) - - set(gp_cmd_paths ${gp_cmd_paths} - "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin" - "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin" - "C:/Program Files/Microsoft Visual Studio 8/VC/BIN" - "C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN" - "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN" - "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN" - "/usr/local/bin" - "/usr/bin" - ) - - find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths}) - - if(NOT gp_cmd) - message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...") - return() - endif(NOT gp_cmd) - - if("${gp_tool}" STREQUAL "dumpbin") - # When running dumpbin, it also needs the "Common7/IDE" directory in the - # PATH. It will already be in the PATH if being run from a Visual Studio - # command prompt. Add it to the PATH here in case we are running from a - # different command prompt. - # - get_filename_component(gp_cmd_dir "${gp_cmd}" PATH) - get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE) - if(EXISTS "${gp_cmd_dlls_dir}") - # only add to the path if it is not already in the path - if(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}") - set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}") - endif(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}") - endif(EXISTS "${gp_cmd_dlls_dir}") - endif("${gp_tool}" STREQUAL "dumpbin") - # - # </setup-gp_tool-vars> - - if("${gp_tool}" STREQUAL "ldd") - set(old_ld_env "$ENV{LD_LIBRARY_PATH}") - foreach(dir ${exepath} ${dirs}) - set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}") - endforeach(dir) - endif("${gp_tool}" STREQUAL "ldd") - - - # Track new prerequisites at each new level of recursion. Start with an - # empty list at each level: - # - set(unseen_prereqs) - - # Run gp_cmd on the target: - # - execute_process( - COMMAND ${gp_cmd} ${gp_cmd_args} ${target} - OUTPUT_VARIABLE gp_cmd_ov - ) - - if("${gp_tool}" STREQUAL "ldd") - set(ENV{LD_LIBRARY_PATH} "${old_ld_env}") - endif("${gp_tool}" STREQUAL "ldd") - - if(verbose) - message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>") - message(STATUS "gp_cmd_ov='${gp_cmd_ov}'") - message(STATUS "</RawOutput>") - endif(verbose) - - get_filename_component(target_dir "${target}" PATH) - - # Convert to a list of lines: - # - string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}") - string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}") - - # Analyze each line for file names that match the regular expression: - # - foreach(candidate ${candidates}) - if("${candidate}" MATCHES "${gp_regex}") - # Extract information from each candidate: - string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}") - - if(gp_regex_cmp_count GREATER 1) - string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}") - string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}") - string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}") - string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}") - endif(gp_regex_cmp_count GREATER 1) - - if(gp_regex_cmp_count GREATER 2) - string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}") - string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}") - string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}") - string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}") - endif(gp_regex_cmp_count GREATER 2) - - # Use the raw_item as the list entries returned by this function. Use the - # gp_resolve_item function to resolve it to an actual full path file if - # necessary. - # - set(item "${raw_item}") - - # Add each item unless it is excluded: - # - set(add_item 1) - - if(${exclude_system}) - set(type "") - gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type) - if("${type}" STREQUAL "system") - set(add_item 0) - endif("${type}" STREQUAL "system") - endif(${exclude_system}) - - if(add_item) - list(LENGTH ${prerequisites_var} list_length_before_append) - gp_append_unique(${prerequisites_var} "${item}") - list(LENGTH ${prerequisites_var} list_length_after_append) - - if(${recurse}) - # If item was really added, this is the first time we have seen it. - # Add it to unseen_prereqs so that we can recursively add *its* - # prerequisites... - # - # But first: resolve its name to an absolute full path name such - # that the analysis tools can simply accept it as input. - # - if(NOT list_length_before_append EQUAL list_length_after_append) - gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item) - set(unseen_prereqs ${unseen_prereqs} "${resolved_item}") - endif(NOT list_length_before_append EQUAL list_length_after_append) - endif(${recurse}) - endif(add_item) - else("${candidate}" MATCHES "${gp_regex}") - if(verbose) - message(STATUS "ignoring non-matching line: '${candidate}'") - endif(verbose) - endif("${candidate}" MATCHES "${gp_regex}") - endforeach(candidate) - - list(LENGTH ${prerequisites_var} prerequisites_var_length) - if(prerequisites_var_length GREATER 0) - list(SORT ${prerequisites_var}) - endif(prerequisites_var_length GREATER 0) - if(${recurse}) - set(more_inputs ${unseen_prereqs}) - foreach(input ${more_inputs}) - get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}") - endforeach(input) - endif(${recurse}) - - set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE) -endfunction(get_prerequisites) - - -# list_prerequisites target all exclude_system verbose -# -# ARGV0 (target) is the full path to an executable file -# -# optional ARGV1 (all) is 0 or 1: 0 for direct prerequisites only, -# 1 for all prerequisites recursively -# -# optional ARGV2 (exclude_system) is 0 or 1: 0 to include "system" -# prerequisites , 1 to exclude them -# -# optional ARGV3 (verbose) is 0 or 1: 0 to print only full path -# names of prerequisites, 1 to print extra information -# -function(list_prerequisites target) - if("${ARGV1}" STREQUAL "") - set(all 1) - else("${ARGV1}" STREQUAL "") - set(all "${ARGV1}") - endif("${ARGV1}" STREQUAL "") - - if("${ARGV2}" STREQUAL "") - set(exclude_system 0) - else("${ARGV2}" STREQUAL "") - set(exclude_system "${ARGV2}") - endif("${ARGV2}" STREQUAL "") - - if("${ARGV3}" STREQUAL "") - set(verbose 0) - else("${ARGV3}" STREQUAL "") - set(verbose "${ARGV3}") - endif("${ARGV3}" STREQUAL "") - - set(count 0) - set(count_str "") - set(print_count "${verbose}") - set(print_prerequisite_type "${verbose}") - set(print_target "${verbose}") - set(type_str "") - - get_filename_component(exepath "${target}" PATH) - - set(prereqs "") - get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "") - - if(print_target) - message(STATUS "File '${target}' depends on:") - endif(print_target) - - foreach(d ${prereqs}) - math(EXPR count "${count} + 1") - - if(print_count) - set(count_str "${count}. ") - endif(print_count) - - if(print_prerequisite_type) - gp_file_type("${target}" "${d}" type) - set(type_str " (${type})") - endif(print_prerequisite_type) - - message(STATUS "${count_str}${d}${type_str}") - endforeach(d) -endfunction(list_prerequisites) - - -# list_prerequisites_by_glob glob_arg glob_exp -# -# glob_arg is GLOB or GLOB_RECURSE -# -# glob_exp is a globbing expression used with "file(GLOB" to retrieve a list -# of matching files. If a matching file is executable, its prerequisites are -# listed. -# -# Any additional (optional) arguments provided are passed along as the -# optional arguments to the list_prerequisites calls. -# -function(list_prerequisites_by_glob glob_arg glob_exp) - message(STATUS "=============================================================================") - message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'") - message(STATUS "") - file(${glob_arg} file_list ${glob_exp}) - foreach(f ${file_list}) - is_file_executable("${f}" is_f_executable) - if(is_f_executable) - message(STATUS "=============================================================================") - list_prerequisites("${f}" ${ARGN}) - message(STATUS "") - endif(is_f_executable) - endforeach(f) -endfunction(list_prerequisites_by_glob) +# GetPrerequisites.cmake +# +# This script provides functions to list the .dll, .dylib or .so files that an +# executable or shared library file depends on. (Its prerequisites.) +# +# It uses various tools to obtain the list of required shared library files: +# dumpbin (Windows) +# ldd (Linux/Unix) +# otool (Mac OSX) +# +# The following functions are provided by this script: +# gp_append_unique +# is_file_executable +# gp_item_default_embedded_path +# (projects can override with gp_item_default_embedded_path_override) +# gp_resolve_item +# (projects can override with gp_resolve_item_override) +# gp_resolved_file_type +# gp_file_type +# get_prerequisites +# list_prerequisites +# list_prerequisites_by_glob +# +# Requires CMake 2.6 or greater because it uses function, break, return and +# PARENT_SCOPE. + +#============================================================================= +# Copyright 2008-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distributed this file outside of CMake, substitute the full +# License text for the above reference.) + +# gp_append_unique list_var value +# +# Append value to the list variable ${list_var} only if the value is not +# already in the list. +# +function(gp_append_unique list_var value) + set(contains 0) + + foreach(item ${${list_var}}) + if("${item}" STREQUAL "${value}") + set(contains 1) + break() + endif("${item}" STREQUAL "${value}") + endforeach(item) + + if(NOT contains) + set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE) + endif(NOT contains) +endfunction(gp_append_unique) + + +# is_file_executable file result_var +# +# Return 1 in ${result_var} if ${file} is a binary executable. +# +# Return 0 in ${result_var} otherwise. +# +function(is_file_executable file result_var) + # + # A file is not executable until proven otherwise: + # + set(${result_var} 0 PARENT_SCOPE) + + get_filename_component(file_full "${file}" ABSOLUTE) + string(TOLOWER "${file_full}" file_full_lower) + + # If file name ends in .exe on Windows, *assume* executable: + # + if(WIN32) + if("${file_full_lower}" MATCHES "\\.exe$") + set(${result_var} 1 PARENT_SCOPE) + return() + endif("${file_full_lower}" MATCHES "\\.exe$") + + # A clause could be added here that uses output or return value of dumpbin + # to determine ${result_var}. In 99%+? practical cases, the exe name + # match will be sufficient... + # + endif(WIN32) + + # Use the information returned from the Unix shell command "file" to + # determine if ${file_full} should be considered an executable file... + # + # If the file command's output contains "executable" and does *not* contain + # "text" then it is likely an executable suitable for prerequisite analysis + # via the get_prerequisites macro. + # + if(UNIX) + if(NOT file_cmd) + find_program(file_cmd "file") + endif(NOT file_cmd) + + if(file_cmd) + execute_process(COMMAND "${file_cmd}" "${file_full}" + OUTPUT_VARIABLE file_ov + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # Replace the name of the file in the output with a placeholder token + # (the string " _file_full_ ") so that just in case the path name of + # the file contains the word "text" or "executable" we are not fooled + # into thinking "the wrong thing" because the file name matches the + # other 'file' command output we are looking for... + # + string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}") + string(TOLOWER "${file_ov}" file_ov) + + #message(STATUS "file_ov='${file_ov}'") + if("${file_ov}" MATCHES "executable") + #message(STATUS "executable!") + if("${file_ov}" MATCHES "text") + #message(STATUS "but text, so *not* a binary executable!") + else("${file_ov}" MATCHES "text") + set(${result_var} 1 PARENT_SCOPE) + return() + endif("${file_ov}" MATCHES "text") + endif("${file_ov}" MATCHES "executable") + else(file_cmd) + message(STATUS "warning: No 'file' command, skipping execute_process...") + endif(file_cmd) + endif(UNIX) +endfunction(is_file_executable) + + +# gp_item_default_embedded_path item default_embedded_path_var +# +# Return the path that others should refer to the item by when the item +# is embedded inside a bundle. +# +# Override on a per-project basis by providing a project-specific +# gp_item_default_embedded_path_override function. +# +function(gp_item_default_embedded_path item default_embedded_path_var) + + # On Windows and Linux, "embed" prerequisites in the same directory + # as the executable by default: + # + set(path "@executable_path") + set(overridden 0) + + # On the Mac, relative to the executable depending on the type + # of the thing we are embedding: + # + if(APPLE) + # + # The assumption here is that all executables in the bundle will be + # in same-level-directories inside the bundle. The parent directory + # of an executable inside the bundle should be MacOS or a sibling of + # MacOS and all embedded paths returned from here will begin with + # "@executable_path/../" and will work from all executables in all + # such same-level-directories inside the bundle. + # + + # By default, embed things right next to the main bundle executable: + # + set(path "@executable_path/../../Contents/MacOS") + + # Embed .dylibs right next to the main bundle executable: + # + if(item MATCHES "\\.dylib$") + set(path "@executable_path/../MacOS") + set(overridden 1) + endif(item MATCHES "\\.dylib$") + + # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS): + # + if(NOT overridden) + if(item MATCHES "[^/]+\\.framework/") + set(path "@executable_path/../Frameworks") + set(overridden 1) + endif(item MATCHES "[^/]+\\.framework/") + endif(NOT overridden) + endif() + + # Provide a hook so that projects can override the default embedded location + # of any given library by whatever logic they choose: + # + if(COMMAND gp_item_default_embedded_path_override) + gp_item_default_embedded_path_override("${item}" path) + endif(COMMAND gp_item_default_embedded_path_override) + + set(${default_embedded_path_var} "${path}" PARENT_SCOPE) +endfunction(gp_item_default_embedded_path) + + +# gp_resolve_item context item exepath dirs resolved_item_var +# +# Resolve an item into an existing full path file. +# +# Override on a per-project basis by providing a project-specific +# gp_resolve_item_override function. +# +function(gp_resolve_item context item exepath dirs resolved_item_var) + set(resolved 0) + set(resolved_item "${item}") + + # Is it already resolved? + # + if(EXISTS "${resolved_item}") + set(resolved 1) + endif(EXISTS "${resolved_item}") + + if(NOT resolved) + if(item MATCHES "@executable_path") + # + # @executable_path references are assumed relative to exepath + # + string(REPLACE "@executable_path" "${exepath}" ri "${item}") + get_filename_component(ri "${ri}" ABSOLUTE) + + if(EXISTS "${ri}") + #message(STATUS "info: embedded item exists (${ri})") + set(resolved 1) + set(resolved_item "${ri}") + else(EXISTS "${ri}") + message(STATUS "warning: embedded item does not exist '${ri}'") + endif(EXISTS "${ri}") + endif(item MATCHES "@executable_path") + endif(NOT resolved) + + if(NOT resolved) + if(item MATCHES "@loader_path") + # + # @loader_path references are assumed relative to the + # PATH of the given "context" (presumably another library) + # + get_filename_component(contextpath "${context}" PATH) + string(REPLACE "@loader_path" "${contextpath}" ri "${item}") + get_filename_component(ri "${ri}" ABSOLUTE) + + if(EXISTS "${ri}") + #message(STATUS "info: embedded item exists (${ri})") + set(resolved 1) + set(resolved_item "${ri}") + else(EXISTS "${ri}") + message(STATUS "warning: embedded item does not exist '${ri}'") + endif(EXISTS "${ri}") + endif(item MATCHES "@loader_path") + endif(NOT resolved) + + if(NOT resolved) + set(ri "ri-NOTFOUND") + find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH) + find_file(ri "${item}" ${exepath} ${dirs} /usr/lib) + if(ri) + #message(STATUS "info: 'find_file' in exepath/dirs (${ri})") + set(resolved 1) + set(resolved_item "${ri}") + set(ri "ri-NOTFOUND") + endif(ri) + endif(NOT resolved) + + if(NOT resolved) + if(item MATCHES "[^/]+\\.framework/") + set(fw "fw-NOTFOUND") + find_file(fw "${item}" + "~/Library/Frameworks" + "/Library/Frameworks" + "/System/Library/Frameworks" + ) + if(fw) + #message(STATUS "info: 'find_file' found framework (${fw})") + set(resolved 1) + set(resolved_item "${fw}") + set(fw "fw-NOTFOUND") + endif(fw) + endif(item MATCHES "[^/]+\\.framework/") + endif(NOT resolved) + + # Using find_program on Windows will find dll files that are in the PATH. + # (Converting simple file names into full path names if found.) + # + if(WIN32) + if(NOT resolved) + set(ri "ri-NOTFOUND") + find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH) + find_program(ri "${item}" PATHS "${exepath};${dirs}") + if(ri) + #message(STATUS "info: 'find_program' in exepath/dirs (${ri})") + set(resolved 1) + set(resolved_item "${ri}") + set(ri "ri-NOTFOUND") + endif(ri) + endif(NOT resolved) + endif(WIN32) + + # Provide a hook so that projects can override item resolution + # by whatever logic they choose: + # + if(COMMAND gp_resolve_item_override) + gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved) + endif(COMMAND gp_resolve_item_override) + + if(NOT resolved) + message(STATUS " +warning: cannot resolve item '${item}' + + possible problems: + need more directories? + need to use InstallRequiredSystemLibraries? + run in install tree instead of build tree? +") +# message(STATUS " +#****************************************************************************** +#warning: cannot resolve item '${item}' +# +# possible problems: +# need more directories? +# need to use InstallRequiredSystemLibraries? +# run in install tree instead of build tree? +# +# context='${context}' +# item='${item}' +# exepath='${exepath}' +# dirs='${dirs}' +# resolved_item_var='${resolved_item_var}' +#****************************************************************************** +#") + endif(NOT resolved) + + set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE) +endfunction(gp_resolve_item) + + +# gp_resolved_file_type original_file file exepath dirs type_var +# +# Return the type of ${file} with respect to ${original_file}. String +# describing type of prerequisite is returned in variable named ${type_var}. +# +# Use ${exepath} and ${dirs} if necessary to resolve non-absolute ${file} +# values -- but only for non-embedded items. +# +# Possible types are: +# system +# local +# embedded +# other +# +function(gp_resolved_file_type original_file file exepath dirs type_var) + #message(STATUS "**") + + if(NOT IS_ABSOLUTE "${original_file}") + message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file") + endif() + + set(is_embedded 0) + set(is_local 0) + set(is_system 0) + + set(resolved_file "${file}") + + if("${file}" MATCHES "^@(executable|loader)_path") + set(is_embedded 1) + endif() + + if(NOT is_embedded) + if(NOT IS_ABSOLUTE "${file}") + gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file) + endif() + + string(TOLOWER "${original_file}" original_lower) + string(TOLOWER "${resolved_file}" lower) + + if(UNIX) + if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/)") + set(is_system 1) + endif() + endif() + + if(APPLE) + if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)") + set(is_system 1) + endif() + endif() + + if(WIN32) + string(TOLOWER "$ENV{SystemRoot}" sysroot) + string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}") + + string(TOLOWER "$ENV{windir}" windir) + string(REGEX REPLACE "\\\\" "/" windir "${windir}") + + if(lower MATCHES "^(${sysroot}/system|${windir}/system|${sysroot}/syswow|${windir}/syswow|(.*/)*msvc[^/]+dll)") + set(is_system 1) + endif() + endif() + + if(NOT is_system) + get_filename_component(original_path "${original_lower}" PATH) + get_filename_component(path "${lower}" PATH) + if("${original_path}" STREQUAL "${path}") + set(is_local 1) + endif() + endif() + endif() + + # Return type string based on computed booleans: + # + set(type "other") + + if(is_system) + set(type "system") + elseif(is_embedded) + set(type "embedded") + elseif(is_local) + set(type "local") + endif() + + #message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'") + #message(STATUS " type: '${type}'") + + if(NOT is_embedded) + if(NOT IS_ABSOLUTE "${resolved_file}") + if(lower MATCHES "^msvc[^/]+dll" AND is_system) + message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'") + else() + message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect") + endif() + endif() + endif() + + set(${type_var} "${type}" PARENT_SCOPE) + + #message(STATUS "**") +endfunction() + + +# gp_file_type original_file file type_var +# +# Return the type of ${file} with respect to ${original_file}. String +# describing type of prerequisite is returned in variable named ${type_var}. +# +# Possible types are: +# system +# local +# embedded +# other +# +function(gp_file_type original_file file type_var) + if(NOT IS_ABSOLUTE "${original_file}") + message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file") + endif() + + get_filename_component(exepath "${original_file}" PATH) + + set(type "") + gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type) + + set(${type_var} "${type}" PARENT_SCOPE) +endfunction(gp_file_type) + + +# get_prerequisites target prerequisites_var exclude_system recurse dirs +# +# Get the list of shared library files required by ${target}. The list in +# the variable named ${prerequisites_var} should be empty on first entry to +# this function. On exit, ${prerequisites_var} will contain the list of +# required shared library files. +# +# target is the full path to an executable file +# +# prerequisites_var is the name of a CMake variable to contain the results +# +# exclude_system is 0 or 1: 0 to include "system" prerequisites , 1 to +# exclude them +# +# recurse is 0 or 1: 0 for direct prerequisites only, 1 for all prerequisites +# recursively +# +# exepath is the path to the top level executable used for @executable_path +# replacment on the Mac +# +# dirs is a list of paths where libraries might be found: these paths are +# searched first when a target without any path info is given. Then standard +# system locations are also searched: PATH, Framework locations, /usr/lib... +# +function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs) + set(verbose 0) + set(eol_char "E") + + if(NOT IS_ABSOLUTE "${target}") + message("warning: target '${target}' is not absolute...") + endif(NOT IS_ABSOLUTE "${target}") + + if(NOT EXISTS "${target}") + message("warning: target '${target}' does not exist...") + endif(NOT EXISTS "${target}") + + # <setup-gp_tool-vars> + # + # Try to choose the right tool by default. Caller can set gp_tool prior to + # calling this function to force using a different tool. + # + if("${gp_tool}" STREQUAL "") + set(gp_tool "ldd") + if(APPLE) + set(gp_tool "otool") + endif(APPLE) + if(WIN32) + set(gp_tool "dumpbin") + endif(WIN32) + endif("${gp_tool}" STREQUAL "") + + set(gp_tool_known 0) + + if("${gp_tool}" STREQUAL "ldd") + set(gp_cmd_args "") + set(gp_regex "^[\t ]*[^\t ]+ => ([^\t ]+).*${eol_char}$") + set(gp_regex_cmp_count 1) + set(gp_tool_known 1) + endif("${gp_tool}" STREQUAL "ldd") + + if("${gp_tool}" STREQUAL "otool") + set(gp_cmd_args "-L") + set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$") + set(gp_regex_cmp_count 3) + set(gp_tool_known 1) + endif("${gp_tool}" STREQUAL "otool") + + if("${gp_tool}" STREQUAL "dumpbin") + set(gp_cmd_args "/dependents") + set(gp_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$") + set(gp_regex_cmp_count 1) + set(gp_tool_known 1) + set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE. + endif("${gp_tool}" STREQUAL "dumpbin") + + if(NOT gp_tool_known) + message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...") + message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'") + message(STATUS "Valid gp_tool values are dumpbin, ldd and otool.") + return() + endif(NOT gp_tool_known) + + set(gp_cmd_paths ${gp_cmd_paths} + "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin" + "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin" + "C:/Program Files/Microsoft Visual Studio 8/VC/BIN" + "C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN" + "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN" + "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN" + "/usr/local/bin" + "/usr/bin" + ) + + find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths}) + + if(NOT gp_cmd) + message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...") + return() + endif(NOT gp_cmd) + + if("${gp_tool}" STREQUAL "dumpbin") + # When running dumpbin, it also needs the "Common7/IDE" directory in the + # PATH. It will already be in the PATH if being run from a Visual Studio + # command prompt. Add it to the PATH here in case we are running from a + # different command prompt. + # + get_filename_component(gp_cmd_dir "${gp_cmd}" PATH) + get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE) + if(EXISTS "${gp_cmd_dlls_dir}") + # only add to the path if it is not already in the path + if(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}") + set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}") + endif(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}") + endif(EXISTS "${gp_cmd_dlls_dir}") + endif("${gp_tool}" STREQUAL "dumpbin") + # + # </setup-gp_tool-vars> + + if("${gp_tool}" STREQUAL "ldd") + set(old_ld_env "$ENV{LD_LIBRARY_PATH}") + foreach(dir ${exepath} ${dirs}) + set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}") + endforeach(dir) + endif("${gp_tool}" STREQUAL "ldd") + + + # Track new prerequisites at each new level of recursion. Start with an + # empty list at each level: + # + set(unseen_prereqs) + + # Run gp_cmd on the target: + # + execute_process( + COMMAND ${gp_cmd} ${gp_cmd_args} ${target} + OUTPUT_VARIABLE gp_cmd_ov + ) + + if("${gp_tool}" STREQUAL "ldd") + set(ENV{LD_LIBRARY_PATH} "${old_ld_env}") + endif("${gp_tool}" STREQUAL "ldd") + + if(verbose) + message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>") + message(STATUS "gp_cmd_ov='${gp_cmd_ov}'") + message(STATUS "</RawOutput>") + endif(verbose) + + get_filename_component(target_dir "${target}" PATH) + + # Convert to a list of lines: + # + string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}") + string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}") + + # Analyze each line for file names that match the regular expression: + # + foreach(candidate ${candidates}) + if("${candidate}" MATCHES "${gp_regex}") + # Extract information from each candidate: + string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}") + + if(gp_regex_cmp_count GREATER 1) + string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}") + endif(gp_regex_cmp_count GREATER 1) + + if(gp_regex_cmp_count GREATER 2) + string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}") + endif(gp_regex_cmp_count GREATER 2) + + # Use the raw_item as the list entries returned by this function. Use the + # gp_resolve_item function to resolve it to an actual full path file if + # necessary. + # + set(item "${raw_item}") + + # Add each item unless it is excluded: + # + set(add_item 1) + + if(${exclude_system}) + set(type "") + gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type) + if("${type}" STREQUAL "system") + set(add_item 0) + endif("${type}" STREQUAL "system") + endif(${exclude_system}) + + if(add_item) + list(LENGTH ${prerequisites_var} list_length_before_append) + gp_append_unique(${prerequisites_var} "${item}") + list(LENGTH ${prerequisites_var} list_length_after_append) + + if(${recurse}) + # If item was really added, this is the first time we have seen it. + # Add it to unseen_prereqs so that we can recursively add *its* + # prerequisites... + # + # But first: resolve its name to an absolute full path name such + # that the analysis tools can simply accept it as input. + # + if(NOT list_length_before_append EQUAL list_length_after_append) + gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item) + set(unseen_prereqs ${unseen_prereqs} "${resolved_item}") + endif(NOT list_length_before_append EQUAL list_length_after_append) + endif(${recurse}) + endif(add_item) + else("${candidate}" MATCHES "${gp_regex}") + if(verbose) + message(STATUS "ignoring non-matching line: '${candidate}'") + endif(verbose) + endif("${candidate}" MATCHES "${gp_regex}") + endforeach(candidate) + + list(LENGTH ${prerequisites_var} prerequisites_var_length) + if(prerequisites_var_length GREATER 0) + list(SORT ${prerequisites_var}) + endif(prerequisites_var_length GREATER 0) + if(${recurse}) + set(more_inputs ${unseen_prereqs}) + foreach(input ${more_inputs}) + get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}") + endforeach(input) + endif(${recurse}) + + set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE) +endfunction(get_prerequisites) + + +# list_prerequisites target all exclude_system verbose +# +# ARGV0 (target) is the full path to an executable file +# +# optional ARGV1 (all) is 0 or 1: 0 for direct prerequisites only, +# 1 for all prerequisites recursively +# +# optional ARGV2 (exclude_system) is 0 or 1: 0 to include "system" +# prerequisites , 1 to exclude them +# +# optional ARGV3 (verbose) is 0 or 1: 0 to print only full path +# names of prerequisites, 1 to print extra information +# +function(list_prerequisites target) + if("${ARGV1}" STREQUAL "") + set(all 1) + else("${ARGV1}" STREQUAL "") + set(all "${ARGV1}") + endif("${ARGV1}" STREQUAL "") + + if("${ARGV2}" STREQUAL "") + set(exclude_system 0) + else("${ARGV2}" STREQUAL "") + set(exclude_system "${ARGV2}") + endif("${ARGV2}" STREQUAL "") + + if("${ARGV3}" STREQUAL "") + set(verbose 0) + else("${ARGV3}" STREQUAL "") + set(verbose "${ARGV3}") + endif("${ARGV3}" STREQUAL "") + + set(count 0) + set(count_str "") + set(print_count "${verbose}") + set(print_prerequisite_type "${verbose}") + set(print_target "${verbose}") + set(type_str "") + + get_filename_component(exepath "${target}" PATH) + + set(prereqs "") + get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "") + + if(print_target) + message(STATUS "File '${target}' depends on:") + endif(print_target) + + foreach(d ${prereqs}) + math(EXPR count "${count} + 1") + + if(print_count) + set(count_str "${count}. ") + endif(print_count) + + if(print_prerequisite_type) + gp_file_type("${target}" "${d}" type) + set(type_str " (${type})") + endif(print_prerequisite_type) + + message(STATUS "${count_str}${d}${type_str}") + endforeach(d) +endfunction(list_prerequisites) + + +# list_prerequisites_by_glob glob_arg glob_exp +# +# glob_arg is GLOB or GLOB_RECURSE +# +# glob_exp is a globbing expression used with "file(GLOB" to retrieve a list +# of matching files. If a matching file is executable, its prerequisites are +# listed. +# +# Any additional (optional) arguments provided are passed along as the +# optional arguments to the list_prerequisites calls. +# +function(list_prerequisites_by_glob glob_arg glob_exp) + message(STATUS "=============================================================================") + message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'") + message(STATUS "") + file(${glob_arg} file_list ${glob_exp}) + foreach(f ${file_list}) + is_file_executable("${f}" is_f_executable) + if(is_f_executable) + message(STATUS "=============================================================================") + list_prerequisites("${f}" ${ARGN}) + message(STATUS "") + endif(is_f_executable) + endforeach(f) +endfunction(list_prerequisites_by_glob) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 62b764bb307debcee404eb7bc355f8b361cabadb..05f0492234f059146f38ef586295707ef3456cff 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -1,276 +1,276 @@ -# -*- cmake -*- -include(LLTestCommand) -include(GoogleMock) - -MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources) - # Given a project name and a list of sourcefiles (with optional properties on each), - # add targets to build and run the tests specified. - # ASSUMPTIONS: - # * this macro is being executed in the project file that is passed in - # * current working SOURCE dir is that project dir - # * there is a subfolder tests/ with test code corresponding to the filenames passed in - # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT) - # - # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code - # - # WARNING: do NOT modify this code without working with poppy - - # there is another branch that will conflict heavily with any changes here. -INCLUDE(GoogleMock) - - - IF(LL_TEST_VERBOSE) - MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}") - ENDIF(LL_TEST_VERBOSE) - - # Start with the header and project-wide setup before making targets - #project(UNITTEST_PROJECT_${project}) - # Setup includes, paths, etc - SET(alltest_SOURCE_FILES - ${CMAKE_SOURCE_DIR}/test/test.cpp - ${CMAKE_SOURCE_DIR}/test/lltut.cpp - ) - SET(alltest_DEP_TARGETS - # needed by the test harness itself - ${APRUTIL_LIBRARIES} - ${APR_LIBRARIES} - llcommon - ) - IF(NOT "${project}" STREQUAL "llmath") - # add llmath as a dep unless the tested module *is* llmath! - LIST(APPEND alltest_DEP_TARGETS - llmath - ) - ENDIF(NOT "${project}" STREQUAL "llmath") - SET(alltest_INCLUDE_DIRS - ${LLMATH_INCLUDE_DIRS} - ${LLCOMMON_INCLUDE_DIRS} - ${LIBS_OPEN_DIR}/test - ${GOOGLEMOCK_INCLUDE_DIRS} - ) - SET(alltest_LIBRARIES - ${GOOGLEMOCK_LIBRARIES} - ${PTHREAD_LIBRARY} - ${WINDOWS_LIBRARIES} - ) - # Headers, for convenience in targets. - SET(alltest_HEADER_FILES - ${CMAKE_SOURCE_DIR}/test/test.h - ) - - # Use the default flags - if (LINUX) - SET(CMAKE_EXE_LINKER_FLAGS "") - endif (LINUX) - - # start the source test executable definitions - SET(${project}_TEST_OUTPUT "") - FOREACH (source ${sources}) - STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} ) - STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} ) - IF(LL_TEST_VERBOSE) - MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})") - ENDIF(LL_TEST_VERBOSE) - - # - # Per-codefile additional / external source, header, and include dir property extraction - # - # Source - GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES) - IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND) - SET(${name}_test_additional_SOURCE_FILES "") - ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND) - SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} ) - IF(LL_TEST_VERBOSE) - MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}") - ENDIF(LL_TEST_VERBOSE) - # Headers - GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES) - IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND) - SET(${name}_test_additional_HEADER_FILES "") - ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND) - SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES}) - set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) - LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES}) - IF(LL_TEST_VERBOSE) - MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}") - ENDIF(LL_TEST_VERBOSE) - # Include dirs - GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS) - IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND) - SET(${name}_test_additional_INCLUDE_DIRS "") - ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND) - INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS ) - IF(LL_TEST_VERBOSE) - MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}") - ENDIF(LL_TEST_VERBOSE) - - - # Setup target - ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES}) - SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}") - - # - # Per-codefile additional / external project dep and lib dep property extraction - # - # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19 - # Projects - GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS) - IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND) - SET(${name}_test_additional_PROJECTS "") - ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND) - # Libraries - GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES) - IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND) - SET(${name}_test_additional_LIBRARIES "") - ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND) - IF(LL_TEST_VERBOSE) - MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}") - MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}") - ENDIF(LL_TEST_VERBOSE) - # Add to project - TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} ) - # Compile-time Definitions - GET_SOURCE_FILE_PROPERTY(${name}_test_additional_CFLAGS ${source} LL_TEST_ADDITIONAL_CFLAGS) - IF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND) - SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES COMPILE_FLAGS ${${name}_test_additional_CFLAGS} ) - IF(LL_TEST_VERBOSE) - MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}") - ENDIF(LL_TEST_VERBOSE) - ENDIF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND) - - # - # Setup test targets - # - GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION) - SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt) - SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR}) - - # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19 - IF(LL_TEST_VERBOSE) - MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd = ${TEST_CMD}") - ENDIF(LL_TEST_VERBOSE) - - SET_TEST_PATH(LD_LIBRARY_PATH) - LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${TEST_CMD}) - IF(LL_TEST_VERBOSE) - MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script = ${TEST_SCRIPT_CMD}") - ENDIF(LL_TEST_VERBOSE) - # Add test - ADD_CUSTOM_COMMAND( - OUTPUT ${TEST_OUTPUT} - COMMAND ${TEST_SCRIPT_CMD} - DEPENDS PROJECT_${project}_TEST_${name} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - ) - # Why not add custom target and add POST_BUILD command? - # Slightly less uncertain behavior - # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19 - # > I did not use a post build step as I could not make it notify of a - # > failure after the first time you build and fail a test. - daveh 2009-04-20 - LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT}) - ENDFOREACH (source) - - # Add the test runner target per-project - # (replaces old _test_ok targets all over the place) - ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT}) - ADD_DEPENDENCIES(${project} ${project}_tests) -ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS) - -FUNCTION(LL_ADD_INTEGRATION_TEST - testname - additional_source_files - library_dependencies -# variable args - ) - if(TEST_DEBUG) - message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on") - endif(TEST_DEBUG) - - SET(source_files - tests/${testname}_test.cpp - ${CMAKE_SOURCE_DIR}/test/test.cpp - ${CMAKE_SOURCE_DIR}/test/lltut.cpp - ${additional_source_files} - ) - - SET(libraries - ${library_dependencies} - ${GOOGLEMOCK_LIBRARIES} - ${PTHREAD_LIBRARY} - ) - - # Add test executable build target - if(TEST_DEBUG) - message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})") - endif(TEST_DEBUG) - ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files}) - SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}") - if(STANDALONE) - SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}") - endif(STANDALONE) - - # Add link deps to the executable - if(TEST_DEBUG) - message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})") - endif(TEST_DEBUG) - TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries}) - - # Create the test running command - SET(test_command ${ARGN}) - GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION) - LIST(FIND test_command "{}" test_exe_pos) - IF(test_exe_pos LESS 0) - # The {} marker means "the full pathname of the test executable." - # test_exe_pos -1 means we didn't find it -- so append the test executable - # name to $ARGN, the variable part of the arg list. This is convenient - # shorthand for both straightforward execution of the test program (empty - # $ARGN) and for running a "wrapper" program of some kind accepting the - # pathname of the test program as the last of its args. You need specify - # {} only if the test program's pathname isn't the last argument in the - # desired command line. - LIST(APPEND test_command "${TEST_EXE}") - ELSE (test_exe_pos LESS 0) - # Found {} marker at test_exe_pos. Remove the {}... - LIST(REMOVE_AT test_command test_exe_pos) - # ...and replace it with the actual name of the test executable. - LIST(INSERT test_command test_exe_pos "${TEST_EXE}") - ENDIF (test_exe_pos LESS 0) - - SET_TEST_PATH(LD_LIBRARY_PATH) - LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${test_command}) - - if(TEST_DEBUG) - message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}") - endif(TEST_DEBUG) - - ADD_CUSTOM_COMMAND( - TARGET INTEGRATION_TEST_${testname} - POST_BUILD - COMMAND ${TEST_SCRIPT_CMD} - ) - - # Use CTEST? Not sure how to yet... - # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD}) - -ENDFUNCTION(LL_ADD_INTEGRATION_TEST) - -MACRO(SET_TEST_PATH LISTVAR) - IF(WINDOWS) - # We typically build/package only Release variants of third-party - # libraries, so append the Release staging dir in case the library being - # sought doesn't have a debug variant. - set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} ${SHARED_LIB_STAGING_DIR}/Release) - ELSEIF(DARWIN) - # We typically build/package only Release variants of third-party - # libraries, so append the Release staging dir in case the library being - # sought doesn't have a debug variant. - set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources ${SHARED_LIB_STAGING_DIR}/Release/Resources /usr/lib) - ELSE(WINDOWS) - # Linux uses a single staging directory anyway. - IF (STANDALONE) - set(${LISTVAR} ${CMAKE_BINARY_DIR}/llcommon /usr/lib /usr/local/lib) - ELSE (STANDALONE) - set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib) - ENDIF (STANDALONE) - ENDIF(WINDOWS) -ENDMACRO(SET_TEST_PATH) +# -*- cmake -*- +include(LLTestCommand) +include(GoogleMock) + +MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources) + # Given a project name and a list of sourcefiles (with optional properties on each), + # add targets to build and run the tests specified. + # ASSUMPTIONS: + # * this macro is being executed in the project file that is passed in + # * current working SOURCE dir is that project dir + # * there is a subfolder tests/ with test code corresponding to the filenames passed in + # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT) + # + # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code + # + # WARNING: do NOT modify this code without working with poppy - + # there is another branch that will conflict heavily with any changes here. +INCLUDE(GoogleMock) + + + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}") + ENDIF(LL_TEST_VERBOSE) + + # Start with the header and project-wide setup before making targets + #project(UNITTEST_PROJECT_${project}) + # Setup includes, paths, etc + SET(alltest_SOURCE_FILES + ${CMAKE_SOURCE_DIR}/test/test.cpp + ${CMAKE_SOURCE_DIR}/test/lltut.cpp + ) + SET(alltest_DEP_TARGETS + # needed by the test harness itself + ${APRUTIL_LIBRARIES} + ${APR_LIBRARIES} + llcommon + ) + IF(NOT "${project}" STREQUAL "llmath") + # add llmath as a dep unless the tested module *is* llmath! + LIST(APPEND alltest_DEP_TARGETS + llmath + ) + ENDIF(NOT "${project}" STREQUAL "llmath") + SET(alltest_INCLUDE_DIRS + ${LLMATH_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LIBS_OPEN_DIR}/test + ${GOOGLEMOCK_INCLUDE_DIRS} + ) + SET(alltest_LIBRARIES + ${GOOGLEMOCK_LIBRARIES} + ${PTHREAD_LIBRARY} + ${WINDOWS_LIBRARIES} + ) + # Headers, for convenience in targets. + SET(alltest_HEADER_FILES + ${CMAKE_SOURCE_DIR}/test/test.h + ) + + # Use the default flags + if (LINUX) + SET(CMAKE_EXE_LINKER_FLAGS "") + endif (LINUX) + + # start the source test executable definitions + SET(${project}_TEST_OUTPUT "") + FOREACH (source ${sources}) + STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} ) + STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} ) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})") + ENDIF(LL_TEST_VERBOSE) + + # + # Per-codefile additional / external source, header, and include dir property extraction + # + # Source + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES) + IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND) + SET(${name}_test_additional_SOURCE_FILES "") + ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND) + SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} ) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}") + ENDIF(LL_TEST_VERBOSE) + # Headers + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES) + IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND) + SET(${name}_test_additional_HEADER_FILES "") + ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND) + SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES}) + set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) + LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES}) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}") + ENDIF(LL_TEST_VERBOSE) + # Include dirs + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS) + IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND) + SET(${name}_test_additional_INCLUDE_DIRS "") + ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND) + INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS ) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}") + ENDIF(LL_TEST_VERBOSE) + + + # Setup target + ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES}) + SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}") + + # + # Per-codefile additional / external project dep and lib dep property extraction + # + # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19 + # Projects + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS) + IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND) + SET(${name}_test_additional_PROJECTS "") + ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND) + # Libraries + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES) + IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND) + SET(${name}_test_additional_LIBRARIES "") + ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}") + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}") + ENDIF(LL_TEST_VERBOSE) + # Add to project + TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} ) + # Compile-time Definitions + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_CFLAGS ${source} LL_TEST_ADDITIONAL_CFLAGS) + IF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND) + SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES COMPILE_FLAGS ${${name}_test_additional_CFLAGS} ) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}") + ENDIF(LL_TEST_VERBOSE) + ENDIF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND) + + # + # Setup test targets + # + GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION) + SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt) + SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR}) + + # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19 + IF(LL_TEST_VERBOSE) + MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd = ${TEST_CMD}") + ENDIF(LL_TEST_VERBOSE) + + SET_TEST_PATH(LD_LIBRARY_PATH) + LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${TEST_CMD}) + IF(LL_TEST_VERBOSE) + MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script = ${TEST_SCRIPT_CMD}") + ENDIF(LL_TEST_VERBOSE) + # Add test + ADD_CUSTOM_COMMAND( + OUTPUT ${TEST_OUTPUT} + COMMAND ${TEST_SCRIPT_CMD} + DEPENDS PROJECT_${project}_TEST_${name} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + # Why not add custom target and add POST_BUILD command? + # Slightly less uncertain behavior + # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19 + # > I did not use a post build step as I could not make it notify of a + # > failure after the first time you build and fail a test. - daveh 2009-04-20 + LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT}) + ENDFOREACH (source) + + # Add the test runner target per-project + # (replaces old _test_ok targets all over the place) + ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT}) + ADD_DEPENDENCIES(${project} ${project}_tests) +ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS) + +FUNCTION(LL_ADD_INTEGRATION_TEST + testname + additional_source_files + library_dependencies +# variable args + ) + if(TEST_DEBUG) + message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on") + endif(TEST_DEBUG) + + SET(source_files + tests/${testname}_test.cpp + ${CMAKE_SOURCE_DIR}/test/test.cpp + ${CMAKE_SOURCE_DIR}/test/lltut.cpp + ${additional_source_files} + ) + + SET(libraries + ${library_dependencies} + ${GOOGLEMOCK_LIBRARIES} + ${PTHREAD_LIBRARY} + ) + + # Add test executable build target + if(TEST_DEBUG) + message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})") + endif(TEST_DEBUG) + ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files}) + SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}") + if(STANDALONE) + SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}") + endif(STANDALONE) + + # Add link deps to the executable + if(TEST_DEBUG) + message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})") + endif(TEST_DEBUG) + TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries}) + + # Create the test running command + SET(test_command ${ARGN}) + GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION) + LIST(FIND test_command "{}" test_exe_pos) + IF(test_exe_pos LESS 0) + # The {} marker means "the full pathname of the test executable." + # test_exe_pos -1 means we didn't find it -- so append the test executable + # name to $ARGN, the variable part of the arg list. This is convenient + # shorthand for both straightforward execution of the test program (empty + # $ARGN) and for running a "wrapper" program of some kind accepting the + # pathname of the test program as the last of its args. You need specify + # {} only if the test program's pathname isn't the last argument in the + # desired command line. + LIST(APPEND test_command "${TEST_EXE}") + ELSE (test_exe_pos LESS 0) + # Found {} marker at test_exe_pos. Remove the {}... + LIST(REMOVE_AT test_command test_exe_pos) + # ...and replace it with the actual name of the test executable. + LIST(INSERT test_command test_exe_pos "${TEST_EXE}") + ENDIF (test_exe_pos LESS 0) + + SET_TEST_PATH(LD_LIBRARY_PATH) + LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${test_command}) + + if(TEST_DEBUG) + message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}") + endif(TEST_DEBUG) + + ADD_CUSTOM_COMMAND( + TARGET INTEGRATION_TEST_${testname} + POST_BUILD + COMMAND ${TEST_SCRIPT_CMD} + ) + + # Use CTEST? Not sure how to yet... + # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD}) + +ENDFUNCTION(LL_ADD_INTEGRATION_TEST) + +MACRO(SET_TEST_PATH LISTVAR) + IF(WINDOWS) + # We typically build/package only Release variants of third-party + # libraries, so append the Release staging dir in case the library being + # sought doesn't have a debug variant. + set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} ${SHARED_LIB_STAGING_DIR}/Release) + ELSEIF(DARWIN) + # We typically build/package only Release variants of third-party + # libraries, so append the Release staging dir in case the library being + # sought doesn't have a debug variant. + set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources ${SHARED_LIB_STAGING_DIR}/Release/Resources /usr/lib) + ELSE(WINDOWS) + # Linux uses a single staging directory anyway. + IF (STANDALONE) + set(${LISTVAR} ${CMAKE_BINARY_DIR}/llcommon /usr/lib /usr/local/lib) + ELSE (STANDALONE) + set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib) + ENDIF (STANDALONE) + ENDIF(WINDOWS) +ENDMACRO(SET_TEST_PATH) diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp index c34115ee8064a6d8a63b3ad03ad85e7d44b5dfed..217e26c3ca527380c91fd8bbc1e1d42d3debc83b 100644 --- a/indra/integration_tests/llui_libtest/llui_libtest.cpp +++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp @@ -33,6 +33,7 @@ // linden library includes #include "llcontrol.h" // LLControlGroup #include "lldir.h" +#include "lldiriterator.h" #include "llerrorcontrol.h" #include "llfloater.h" #include "llfontfreetype.h" @@ -174,7 +175,9 @@ void export_test_floaters() std::string delim = gDirUtilp->getDirDelimiter(); std::string xui_dir = get_xui_dir() + "en" + delim; std::string filename; - while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename)) + + LLDirIterator iter(xui_dir, "floater_test_*.xml"); + while (iter.next(filename)) { if (filename.find("_new.xml") != std::string::npos) { diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp index d909516bf8fbce6872458eec049e0b4c836df6ae..808ab3f64f81ab2da3d945212f7a510a251018ef 100644 --- a/indra/linux_updater/linux_updater.cpp +++ b/indra/linux_updater/linux_updater.cpp @@ -33,6 +33,7 @@ #include "llerrorcontrol.h" #include "llfile.h" #include "lldir.h" +#include "lldiriterator.h" #include "llxmlnode.h" #include "lltrans.h" @@ -55,6 +56,8 @@ typedef struct _updater_app_state { std::string strings_dirs; std::string strings_file; + LLDirIterator *image_dir_iter; + GtkWidget *window; GtkWidget *progress_bar; GtkWidget *image; @@ -108,7 +111,7 @@ bool translate_init(std::string comma_delim_path_list, void updater_app_ui_init(void); void updater_app_quit(UpdaterAppState *app_state); void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state); -std::string next_image_filename(std::string& image_path); +std::string next_image_filename(std::string& image_path, LLDirIterator& iter); void display_error(GtkWidget *parent, std::string title, std::string message); BOOL install_package(std::string package_file, std::string destination); BOOL spawn_viewer(UpdaterAppState *app_state); @@ -174,7 +177,7 @@ void updater_app_ui_init(UpdaterAppState *app_state) // load the first image app_state->image = gtk_image_new_from_file - (next_image_filename(app_state->image_dir).c_str()); + (next_image_filename(app_state->image_dir, *app_state->image_dir_iter).c_str()); gtk_widget_set_size_request(app_state->image, 340, 310); gtk_container_add(GTK_CONTAINER(frame), app_state->image); @@ -205,7 +208,7 @@ gboolean rotate_image_cb(gpointer data) llassert(data != NULL); app_state = (UpdaterAppState *) data; - filename = next_image_filename(app_state->image_dir); + filename = next_image_filename(app_state->image_dir, *app_state->image_dir_iter); gdk_threads_enter(); gtk_image_set_from_file(GTK_IMAGE(app_state->image), filename.c_str()); @@ -214,10 +217,10 @@ gboolean rotate_image_cb(gpointer data) return TRUE; } -std::string next_image_filename(std::string& image_path) +std::string next_image_filename(std::string& image_path, LLDirIterator& iter) { std::string image_filename; - gDirUtilp->getNextFileInDir(image_path, "/*.jpg", image_filename); + iter.next(image_filename); return image_path + "/" + image_filename; } @@ -741,6 +744,7 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state) else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc)) { app_state->image_dir = argv[i]; + app_state->image_dir_iter = new LLDirIterator(argv[i], "/*.jpg"); } else if ((!strcmp(argv[i], "--dest")) && (++i < argc)) { @@ -825,6 +829,7 @@ int main(int argc, char **argv) } bool success = !app_state->failure; + delete app_state->image_dir_iter; delete app_state; return success ? 0 : 1; } diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp index b46a6e03d2ed198ed9680e31b98bc711e9b172e1..3e2c05a6e6d4d861c6755213b88fb785e87ad0cb 100644 --- a/indra/llmath/llbbox.cpp +++ b/indra/llmath/llbbox.cpp @@ -89,6 +89,19 @@ void LLBBox::addBBoxAgent(const LLBBox& b) } } +LLBBox LLBBox::getAxisAligned() const +{ + // no rotation = axis aligned rotation + LLBBox aligned(mPosAgent, LLQuaternion(), LLVector3(), LLVector3()); + + // add the center point so that it's not empty + aligned.addPointAgent(mPosAgent); + + // add our BBox + aligned.addBBoxAgent(*this); + + return aligned; +} void LLBBox::expand( F32 delta ) { @@ -147,6 +160,15 @@ BOOL LLBBox::containsPointAgent(const LLVector3& p) const return containsPointLocal(point_local); } +LLVector3 LLBBox::getMinAgent() const +{ + return localToAgent(mMinLocal); +} + +LLVector3 LLBBox::getMaxAgent() const +{ + return localToAgent(mMaxLocal); +} /* LLBBox operator*(const LLBBox &a, const LLMatrix4 &b) diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h index 5b911793f0f4ae12289deff4e00540a8ea8a877a..28e69b75e122629aa680b83927463be3aefd52c9 100644 --- a/indra/llmath/llbbox.h +++ b/indra/llmath/llbbox.h @@ -51,9 +51,11 @@ class LLBBox const LLVector3& getPositionAgent() const { return mPosAgent; } const LLQuaternion& getRotation() const { return mRotation; } + LLVector3 getMinAgent() const; const LLVector3& getMinLocal() const { return mMinLocal; } void setMinLocal( const LLVector3& min ) { mMinLocal = min; } + LLVector3 getMaxAgent() const; const LLVector3& getMaxLocal() const { return mMaxLocal; } void setMaxLocal( const LLVector3& max ) { mMaxLocal = max; } @@ -80,6 +82,8 @@ class LLBBox LLVector3 localToAgentBasis(const LLVector3& v) const; LLVector3 agentToLocalBasis(const LLVector3& v) const; + // Get the smallest possible axis aligned bbox that contains this bbox + LLBBox getAxisAligned() const; // friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b); diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index b9b974ec4f6a8109cbad4859b0c8f4671767654e..7b796a0fa875f92785ac0f0c376338c453188f97 100644 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -42,9 +42,6 @@ const U32 REGION_FLAGS_RESET_HOME_ON_TELEPORT = (1 << 3); // Does the sun move? const U32 REGION_FLAGS_SUN_FIXED = (1 << 4); -// Tax free zone (no taxes on objects, land, etc.) -const U32 REGION_FLAGS_TAX_FREE = (1 << 5); - // Can't change the terrain heightfield, even on owned parcels, // but can plant trees and grass. const U32 REGION_FLAGS_BLOCK_TERRAFORM = (1 << 6); @@ -54,17 +51,12 @@ const U32 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7); // All content wiped once per night const U32 REGION_FLAGS_SANDBOX = (1 << 8); -const U32 REGION_FLAGS_NULL_LAYER = (1 << 9); -// const U32 REGION_FLAGS_SKIP_AGENT_ACTION = (1 << 10); -const U32 REGION_FLAGS_HARD_ALLOW_LAND_TRANSFER = (1 << 10); // Region allows land reselling -// const U32 REGION_FLAGS_SKIP_UPDATE_INTEREST_LIST= (1 << 11); -const U32 REGION_FLAGS_HARD_ALLOW_POST_CLASSIFIED = (1 << 11); // Region allows posting of classified ads const U32 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies const U32 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13); const U32 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics const U32 REGION_FLAGS_EXTERNALLY_VISIBLE = (1 << 15); -//const U32 REGION_FLAGS_MAINLAND_VISIBLE = (1 << 16); -const U32 REGION_FLAGS_PUBLIC_ALLOWED = (1 << 17); +const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16); +const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17); const U32 REGION_FLAGS_BLOCK_DWELL = (1 << 18); // Is flight allowed? @@ -81,18 +73,13 @@ const U32 REGION_FLAGS_ESTATE_SKIP_SCRIPTS = (1 << 21); const U32 REGION_FLAGS_RESTRICT_PUSHOBJECT = (1 << 22); const U32 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23); -// const U32 REGION_FLAGS_DENY_IDENTIFIED = (1 << 24); -// const U32 REGION_FLAGS_DENY_TRANSACTED = (1 << 25); const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26); -// const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); // We no longer support ELAR - const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28); const U32 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29); const U32 REGION_FLAGS_DENY_AGEUNVERIFIED = (1 << 30); -const U32 REGION_FLAGS_SKIP_MONO_SCRIPTS = (1 << 31); const U32 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK | REGION_FLAGS_ALLOW_SET_HOME | @@ -105,7 +92,6 @@ const U32 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK | REGION_FLAGS_ALLOW_SET_HOME; const U32 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE - | REGION_FLAGS_PUBLIC_ALLOWED | REGION_FLAGS_SUN_FIXED | REGION_FLAGS_DENY_ANONYMOUS | REGION_FLAGS_DENY_AGEUNVERIFIED; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index d30697e1784487c2f9694dae189b3d3ac9e11bf3..c4257827152fab8bf99420a3d2cb02e871f2f00b 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -272,9 +272,6 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) initFromParams(p); - // chrome floaters don't take focus at all - setFocusRoot(!getIsChrome()); - initFloater(p); } @@ -2910,8 +2907,6 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str params.from_xui = true; applyXUILayout(params, parent); initFromParams(params); - // chrome floaters don't take focus at all - setFocusRoot(!getIsChrome()); initFloater(params); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 6c0d47ef63d08ffc776cb5bf2cb3de240c93585d..32d7be377a3386a34f769fbb20876712b7b0ef3f 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1637,6 +1637,10 @@ LLMenuScrollItem::LLMenuScrollItem(const Params& p) } LLButton::Params bparams; + + // Disabled the Return key handling by LLMenuScrollItem instead of + // passing the key press to the currently selected menu item. See STORM-385. + bparams.commit_on_return(false); bparams.mouse_opaque(true); bparams.scale_image(false); bparams.click_callback(p.scroll_callback); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 4f7b4be52609206899dee5e9934bdf6c9aa49d62..9db1feafd1b179c9bea839139188158b4b4de205 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -36,6 +36,7 @@ #include "llcachename.h" #include "lltrans.h" #include "lluicolortable.h" +#include "message.h" #define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))" @@ -684,8 +685,8 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa LLStyle::Params LLUrlEntryGroup::getStyle() const { LLStyle::Params style_params = LLUrlEntryBase::getStyle(); - style_params.color = LLUIColorTable::instance().getColor("GroupLinkColor"); - style_params.readonly_color = LLUIColorTable::instance().getColor("GroupLinkColor"); + style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); + style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); return style_params; } @@ -740,6 +741,13 @@ std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const return LLUrlEntryBase::getLocation(url); } +// LLUrlEntryParcel statics. +LLUUID LLUrlEntryParcel::sAgentID(LLUUID::null); +LLUUID LLUrlEntryParcel::sSessionID(LLUUID::null); +LLHost LLUrlEntryParcel::sRegionHost(LLHost::invalid); +bool LLUrlEntryParcel::sDisconnected(false); +std::set<LLUrlEntryParcel*> LLUrlEntryParcel::sParcelInfoObservers; + /// /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g., /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about @@ -751,13 +759,88 @@ LLUrlEntryParcel::LLUrlEntryParcel() boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_parcel.xml"; mTooltip = LLTrans::getString("TooltipParcelUrl"); + + sParcelInfoObservers.insert(this); +} + +LLUrlEntryParcel::~LLUrlEntryParcel() +{ + sParcelInfoObservers.erase(this); } std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelCallback &cb) { + LLSD path_array = LLURI(url).pathArray(); + S32 path_parts = path_array.size(); + + if (path_parts < 3) // no parcel id + { + llwarns << "Failed to parse url [" << url << "]" << llendl; + return url; + } + + std::string parcel_id_string = unescapeUrl(path_array[2]); // parcel id + + // Add an observer to call LLUrlLabelCallback when we have parcel name. + addObserver(parcel_id_string, url, cb); + + LLUUID parcel_id(parcel_id_string); + + sendParcelInfoRequest(parcel_id); + return unescapeUrl(url); } +void LLUrlEntryParcel::sendParcelInfoRequest(const LLUUID& parcel_id) +{ + if (sRegionHost == LLHost::invalid || sDisconnected) return; + + LLMessageSystem *msg = gMessageSystem; + msg->newMessage("ParcelInfoRequest"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, sAgentID ); + msg->addUUID("SessionID", sSessionID); + msg->nextBlock("Data"); + msg->addUUID("ParcelID", parcel_id); + msg->sendReliable(sRegionHost); +} + +void LLUrlEntryParcel::onParcelInfoReceived(const std::string &id, const std::string &label) +{ + callObservers(id, label.empty() ? LLTrans::getString("RegionInfoError") : label, mIcon); +} + +// static +void LLUrlEntryParcel::processParcelInfo(const LLParcelData& parcel_data) +{ + std::string label(LLStringUtil::null); + if (!parcel_data.name.empty()) + { + label = parcel_data.name; + } + // If parcel name is empty use Sim_name (x, y, z) for parcel label. + else if (!parcel_data.sim_name.empty()) + { + S32 region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS; + S32 region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS; + S32 region_z = llround(parcel_data.global_z); + + label = llformat("%s (%d, %d, %d)", + parcel_data.sim_name.c_str(), region_x, region_y, region_z); + } + + for (std::set<LLUrlEntryParcel*>::iterator iter = sParcelInfoObservers.begin(); + iter != sParcelInfoObservers.end(); + ++iter) + { + LLUrlEntryParcel* url_entry = *iter; + if (url_entry) + { + url_entry->onParcelInfoReceived(parcel_data.parcel_id.asString(), label); + } + } +} + // // LLUrlEntryPlace Describes secondlife://<location> URLs // diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 1791739061cdae4c3cf3db6891984ef99d2eeb08..5f82721c0fdf9067383f1d974a052242c4c8a2a3 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -31,6 +31,9 @@ #include "lluuid.h" #include "lluicolor.h" #include "llstyle.h" + +#include "llhost.h" // for resolving parcel name by parcel id + #include <boost/signals2.hpp> #include <boost/regex.hpp> #include <string> @@ -285,8 +288,44 @@ class LLUrlEntryObjectIM : public LLUrlEntryBase class LLUrlEntryParcel : public LLUrlEntryBase { public: + struct LLParcelData + { + LLUUID parcel_id; + std::string name; + std::string sim_name; + F32 global_x; + F32 global_y; + F32 global_z; + }; + LLUrlEntryParcel(); + ~LLUrlEntryParcel(); /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + + // Sends a parcel info request to sim. + void sendParcelInfoRequest(const LLUUID& parcel_id); + + // Calls observers of certain parcel id providing them with parcel label. + void onParcelInfoReceived(const std::string &id, const std::string &label); + + // Processes parcel label and triggers notifying observers. + static void processParcelInfo(const LLParcelData& parcel_data); + + // Next 4 setters are used to update agent and viewer connection information + // upon events like user login, viewer disconnect and user changing region host. + // These setters are made public to be accessible from newview and should not be + // used in other cases. + static void setAgentID(const LLUUID& id) { sAgentID = id; } + static void setSessionID(const LLUUID& id) { sSessionID = id; } + static void setRegionHost(const LLHost& host) { sRegionHost = host; } + static void setDisconnected(bool disconnected) { sDisconnected = disconnected; } + +private: + static LLUUID sAgentID; + static LLUUID sSessionID; + static LLHost sRegionHost; + static bool sDisconnected; + static std::set<LLUrlEntryParcel*> sParcelInfoObservers; }; /// diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index f30704cb2269c8b40b9fd5b0f44fe51aa934e7db..96ebe83826c5137dd90cd0458620a15d2777a4c8 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -30,6 +30,7 @@ #include "llavatarnamecache.h" #include "llcachename.h" #include "lluuid.h" +#include "message.h" #include <string> @@ -191,3 +192,20 @@ LLFontGL* LLFontGL::getFontDefault() { return NULL; } + +char* _PREHASH_AgentData = "AgentData"; +char* _PREHASH_AgentID = "AgentID"; + +LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS); + +LLMessageSystem* gMessageSystem = NULL; + +// +// Stub implementation for LLMessageSystem +// +void LLMessageSystem::newMessage(const char *name) { } +void LLMessageSystem::nextBlockFast(const char *blockname) { } +void LLMessageSystem::nextBlock(const char *blockname) { } +void LLMessageSystem::addUUIDFast( const char *varname, const LLUUID& uuid) { } +void LLMessageSystem::addUUID( const char *varname, const LLUUID& uuid) { } +S32 LLMessageSystem::sendReliable(const LLHost &host) { return 0; } diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt index 722f4e2bfdef9c6212c9edf06f2abee5f55ff996..a3782d824b4cbbcf0abe31ecb5d754238cf3c8a5 100644 --- a/indra/llvfs/CMakeLists.txt +++ b/indra/llvfs/CMakeLists.txt @@ -12,6 +12,7 @@ include_directories( set(llvfs_SOURCE_FILES lldir.cpp + lldiriterator.cpp lllfsthread.cpp llpidlock.cpp llvfile.cpp @@ -24,6 +25,7 @@ set(llvfs_HEADER_FILES lldir.h lldirguard.h + lldiriterator.h lllfsthread.h llpidlock.h llvfile.h @@ -60,6 +62,11 @@ list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES}) add_library (llvfs ${llvfs_SOURCE_FILES}) +target_link_libraries(llvfs + ${BOOST_FILESYSTEM_LIBRARY} + ${BOOST_SYSTEM_LIBRARY} + ) + if (DARWIN) include(CMakeFindFrameworks) find_library(CARBON_LIBRARY Carbon) diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 64556bcb4c34dcacd2b48f391dbfebf0eb528421..ab7d15dfefdcbec79c3d894b19dee81f0352b0a3 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -40,6 +40,8 @@ #include "lltimer.h" // ms_sleep() #include "lluuid.h" +#include "lldiriterator.h" + #if LL_WINDOWS #include "lldir_win32.h" LLDir_Win32 gDirUtil; @@ -83,7 +85,9 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) std::string filename; std::string fullpath; S32 result; - while (getNextFileInDir(dirname, mask, filename)) + + LLDirIterator iter(dirname, mask); + while (iter.next(filename)) { fullpath = dirname; fullpath += getDirDelimiter(); diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 42996fd051b9f5cc8ed949645fa7fda5c4c58f74..5ee8bdb542da2ebc4ee3d10ce114a7df3c1e20b6 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -75,31 +75,6 @@ class LLDir // pure virtual functions virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0; - /// Walk the files in a directory, with file pattern matching - virtual BOOL getNextFileInDir(const std::string& dirname, ///< directory path - must end in trailing slash! - const std::string& mask, ///< file pattern string (use "*" for all) - std::string& fname ///< output: found file name - ) = 0; - /**< - * @returns true if a file was found, false if the entire directory has been scanned. - * - * @note that this function is NOT thread safe - * - * This function may not be used to scan part of a directory, then start a new search of a different - * directory, and then restart the first search where it left off; the entire search must run to - * completion or be abandoned - there is no restart. - * - * @bug: See http://jira.secondlife.com/browse/VWR-23697 - * and/or the tests in test/lldir_test.cpp - * This is known to fail with patterns that have both: - * a wildcard left of a . and more than one sequential ? right of a . - * the pattern foo.??x appears to work - * but *.??x or foo?.??x do not - * - * @todo this really should be rewritten as an iterator object, and the - * filtering should be done in a platform-independent way. - */ - virtual std::string getCurPath() = 0; virtual BOOL fileExists(const std::string &filename) const = 0; diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index 73f2336f94fa70bf2d43bc6b924ed6262b7bd2e8..4ba2f519b0f8080d700dd4c672abeac8ce803962 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -242,68 +242,6 @@ U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string & return (file_count); } -// get the next file in the directory -BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ - glob_t g; - BOOL result = FALSE; - fname = ""; - - if(!(dirname == mCurrentDir)) - { - // different dir specified, close old search - mCurrentDirIndex = -1; - mCurrentDirCount = -1; - mCurrentDir = dirname; - } - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - if(g.gl_pathc > 0) - { - if((int)g.gl_pathc != mCurrentDirCount) - { - // Number of matches has changed since the last search, meaning a file has been added or deleted. - // Reset the index. - mCurrentDirIndex = -1; - mCurrentDirCount = g.gl_pathc; - } - - mCurrentDirIndex++; - - if(mCurrentDirIndex < (int)g.gl_pathc) - { -// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; - - // The API wants just the filename, not the full path. - //fname = g.gl_pathv[mCurrentDirIndex]; - - char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); - - if(s == NULL) - s = g.gl_pathv[mCurrentDirIndex]; - else if(s[0] == '/') - s++; - - fname = s; - - result = TRUE; - } - } - - globfree(&g); - } - - return(result); -} - - - - std::string LLDir_Linux::getCurPath() { char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h index 451e81ae93c560114b83f556120f3fd42f6dbec9..ff4c48759a03327d6b04191d3b179451ad0fd3fd 100644 --- a/indra/llvfs/lldir_linux.h +++ b/indra/llvfs/lldir_linux.h @@ -43,7 +43,6 @@ class LLDir_Linux : public LLDir public: virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname); /*virtual*/ BOOL fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp index 445285aa43ac2c5dae2c11187e73280dc88614db..2d039527c06fa05286ddcbd04226a4425c0e85fb 100644 --- a/indra/llvfs/lldir_mac.cpp +++ b/indra/llvfs/lldir_mac.cpp @@ -258,67 +258,6 @@ U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &ma return (file_count); } -// get the next file in the directory -BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ - glob_t g; - BOOL result = FALSE; - fname = ""; - - if(!(dirname == mCurrentDir)) - { - // different dir specified, close old search - mCurrentDirIndex = -1; - mCurrentDirCount = -1; - mCurrentDir = dirname; - } - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - if(g.gl_pathc > 0) - { - if(g.gl_pathc != mCurrentDirCount) - { - // Number of matches has changed since the last search, meaning a file has been added or deleted. - // Reset the index. - mCurrentDirIndex = -1; - mCurrentDirCount = g.gl_pathc; - } - - mCurrentDirIndex++; - - if(mCurrentDirIndex < g.gl_pathc) - { -// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; - - // The API wants just the filename, not the full path. - //fname = g.gl_pathv[mCurrentDirIndex]; - - char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); - - if(s == NULL) - s = g.gl_pathv[mCurrentDirIndex]; - else if(s[0] == '/') - s++; - - fname = s; - - result = TRUE; - } - } - - globfree(&g); - } - - return(result); -} - - - S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask) { glob_t g; diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h index 4eac3c3ae6fce824624bc7c048b8922c6c86e517..e60d5e41c2deca2e9aaca01d8f34306fbb896c1a 100644 --- a/indra/llvfs/lldir_mac.h +++ b/indra/llvfs/lldir_mac.h @@ -43,7 +43,6 @@ class LLDir_Mac : public LLDir virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask); virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname); virtual BOOL fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp index 515fd66b6e9a9f4d2aef1647ad78134a15419f0c..21f8c3acdbeefa56272bac597cf5b1d1858ba46c 100644 --- a/indra/llvfs/lldir_solaris.cpp +++ b/indra/llvfs/lldir_solaris.cpp @@ -260,68 +260,6 @@ U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string return (file_count); } -// get the next file in the directory -BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ - glob_t g; - BOOL result = FALSE; - fname = ""; - - if(!(dirname == mCurrentDir)) - { - // different dir specified, close old search - mCurrentDirIndex = -1; - mCurrentDirCount = -1; - mCurrentDir = dirname; - } - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - if(g.gl_pathc > 0) - { - if((int)g.gl_pathc != mCurrentDirCount) - { - // Number of matches has changed since the last search, meaning a file has been added or deleted. - // Reset the index. - mCurrentDirIndex = -1; - mCurrentDirCount = g.gl_pathc; - } - - mCurrentDirIndex++; - - if(mCurrentDirIndex < (int)g.gl_pathc) - { -// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; - - // The API wants just the filename, not the full path. - //fname = g.gl_pathv[mCurrentDirIndex]; - - char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); - - if(s == NULL) - s = g.gl_pathv[mCurrentDirIndex]; - else if(s[0] == '/') - s++; - - fname = s; - - result = TRUE; - } - } - - globfree(&g); - } - - return(result); -} - - - - std::string LLDir_Solaris::getCurPath() { char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h index 4a1794f53950dab8f147dae3c4bc9cfe4e3b1088..f7e1a6301dbdc19a713e568d44cb28812b048427 100644 --- a/indra/llvfs/lldir_solaris.h +++ b/indra/llvfs/lldir_solaris.h @@ -43,7 +43,6 @@ class LLDir_Solaris : public LLDir public: virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname); /*virtual*/ BOOL fileExists(const std::string &filename) const; private: diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 33718e520d71b4c3e2595574187c22d0224c0ce7..2f96fbbbc10d2aeee4a78a3c29742aacad05c6e2 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -236,67 +236,6 @@ U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string & return (file_count); } - -// get the next file in the directory -BOOL LLDir_Win32::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ - BOOL fileFound = FALSE; - fname = ""; - - WIN32_FIND_DATAW FileData; - llutf16string pathname = utf8str_to_utf16str(dirname) + utf8str_to_utf16str(mask); - - if (pathname != mCurrentDir) - { - // different dir specified, close old search - if (mCurrentDir[0]) - { - FindClose(mDirSearch_h); - } - mCurrentDir = pathname; - - // and open new one - // Check error opening Directory structure - if ((mDirSearch_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE) - { - fileFound = TRUE; - } - } - - // Loop to skip over the current (.) and parent (..) directory entries - // (apparently returned in Win7 but not XP) - do - { - if ( fileFound - && ( (lstrcmp(FileData.cFileName, (LPCTSTR)TEXT(".")) == 0) - ||(lstrcmp(FileData.cFileName, (LPCTSTR)TEXT("..")) == 0) - ) - ) - { - fileFound = FALSE; - } - } while ( mDirSearch_h != INVALID_HANDLE_VALUE - && !fileFound - && (fileFound = FindNextFile(mDirSearch_h, &FileData) - ) - ); - - if (!fileFound && GetLastError() == ERROR_NO_MORE_FILES) - { - // No more files, so reset to beginning of directory - FindClose(mDirSearch_h); - mCurrentDir[0] = '\000'; - } - - if (fileFound) - { - // convert from TCHAR to char - fname = utf16str_to_utf8str(FileData.cFileName); - } - - return fileFound; -} - std::string LLDir_Win32::getCurPath() { WCHAR w_str[MAX_PATH]; diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h index 4c932c932c8f06d6015c106f2b2cd8c9bd50e7f6..19c610eb8b2f6aeee28622a62568a7e14df7517d 100644 --- a/indra/llvfs/lldir_win32.h +++ b/indra/llvfs/lldir_win32.h @@ -40,15 +40,12 @@ class LLDir_Win32 : public LLDir /*virtual*/ std::string getCurPath(); /*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname); /*virtual*/ BOOL fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); private: - BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname); - void* mDirSearch_h; llutf16string mCurrentDir; }; diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5536ed8f69a97c49721cf0242d8a97bf5d89ad1f --- /dev/null +++ b/indra/llvfs/lldiriterator.cpp @@ -0,0 +1,203 @@ +/** + * @file lldiriterator.cpp + * @brief Iterator through directory entries matching the search pattern. + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "lldiriterator.h" + +#include <boost/filesystem.hpp> +#include <boost/regex.hpp> + +namespace fs = boost::filesystem; + +static std::string glob_to_regex(const std::string& glob); + +class LLDirIterator::Impl +{ +public: + Impl(const std::string &dirname, const std::string &mask); + ~Impl(); + + bool next(std::string &fname); + +private: + boost::regex mFilterExp; + fs::directory_iterator mIter; + bool mIsValid; +}; + +LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) + : mIsValid(false) +{ + fs::path dir_path(dirname); + + // Check if path exists. + if (!fs::exists(dir_path)) + { + llerrs << "Invalid path: \"" << dir_path.string() << "\"" << llendl; + return; + } + + // Initialize the directory iterator for the given path. + try + { + mIter = fs::directory_iterator(dir_path); + } + catch (fs::basic_filesystem_error<fs::path>& e) + { + llerrs << e.what() << llendl; + return; + } + + // Convert the glob mask to a regular expression + std::string exp = glob_to_regex(mask); + + // Initialize boost::regex with the expression converted from + // the glob mask. + // An exception is thrown if the expression is not valid. + try + { + mFilterExp.assign(exp); + } + catch (boost::regex_error& e) + { + llerrs << "\"" << exp << "\" is not a valid regular expression: " + << e.what() << llendl; + return; + } + + mIsValid = true; +} + +LLDirIterator::Impl::~Impl() +{ +} + +bool LLDirIterator::Impl::next(std::string &fname) +{ + fname = ""; + + if (!mIsValid) + { + llerrs << "The iterator is not correctly initialized." << llendl; + return false; + } + + fs::directory_iterator end_itr; // default construction yields past-the-end + bool found = false; + while (mIter != end_itr && !found) + { + boost::smatch match; + std::string name = mIter->path().filename(); + if (found = boost::regex_match(name, match, mFilterExp)) + { + fname = name; + } + + ++mIter; + } + + return found; +} + +std::string glob_to_regex(const std::string& glob) +{ + std::string regex; + regex.reserve(glob.size()<<1); + S32 braces = 0; + bool escaped = false; + bool square_brace_open = false; + + for (std::string::const_iterator i = glob.begin(); i != glob.end(); ++i) + { + char c = *i; + + switch (c) + { + case '.': + regex+="\\."; + break; + case '*': + if (glob.begin() == i) + { + regex+="[^.].*"; + } + else + { + regex+= escaped ? "*" : ".*"; + } + break; + case '?': + regex+= escaped ? '?' : '.'; + break; + case '{': + braces++; + regex+='('; + break; + case '}': + if (!braces) + { + llerrs << "glob_to_regex: Closing brace without an equivalent opening brace: " << glob << llendl; + } + + regex+=')'; + braces--; + break; + case ',': + regex+= braces ? '|' : c; + break; + case '!': + regex+= square_brace_open ? '^' : c; + break; + default: + regex+=c; + break; + } + + escaped = ('\\' == c); + square_brace_open = ('[' == c); + } + + if (braces) + { + llerrs << "glob_to_regex: Unterminated brace expression: " << glob << llendl; + } + + return regex; +} + +LLDirIterator::LLDirIterator(const std::string &dirname, const std::string &mask) +{ + mImpl = new Impl(dirname, mask); +} + +LLDirIterator::~LLDirIterator() +{ + delete mImpl; +} + +bool LLDirIterator::next(std::string &fname) +{ + return mImpl->next(fname); +} diff --git a/indra/llvfs/lldiriterator.h b/indra/llvfs/lldiriterator.h new file mode 100644 index 0000000000000000000000000000000000000000..0b48be41b321c71935957773ea5a43494c9d5959 --- /dev/null +++ b/indra/llvfs/lldiriterator.h @@ -0,0 +1,87 @@ +/** + * @file lldiriterator.h + * @brief Iterator through directory entries matching the search pattern. + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDIRITERATOR_H +#define LL_LLDIRITERATOR_H + +#include "linden_common.h" + +/** + * Class LLDirIterator + * + * Iterates through directory entries matching the search pattern. + */ +class LLDirIterator +{ +public: + /** + * Constructs LLDirIterator object to search for glob pattern + * matches in a directory. + * + * @param dirname - name of a directory to search in. + * @param mask - search pattern, a glob expression + * + * Wildcards supported in glob expressions: + * -------------------------------------------------------------- + * | Wildcard | Matches | + * -------------------------------------------------------------- + * | * |zero or more characters | + * | ? |exactly one character | + * | [abcde] |exactly one character listed | + * | [a-e] |exactly one character in the given range | + * | [!abcde] |any character that is not listed | + * | [!a-e] |any character that is not in the given range | + * | {abc,xyz} |exactly one entire word in the options given | + * -------------------------------------------------------------- + */ + LLDirIterator(const std::string &dirname, const std::string &mask); + + ~LLDirIterator(); + + /** + * Searches for the next directory entry matching the glob mask + * specified upon iterator construction. + * Returns true if a match is found, sets fname + * parameter to the name of the matched directory entry and + * increments the iterator position. + * + * Typical usage: + * <code> + * LLDirIterator iter(directory, pattern); + * if ( iter.next(scanResult) ) + * </code> + * + * @param fname - name of the matched directory entry. + * @return true if a match is found, false otherwise. + */ + bool next(std::string &fname); + +protected: + class Impl; + Impl* mImpl; +}; + +#endif //LL_LLDIRITERATOR_H diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp index 8788bd63e87d2b8030324ffcd0e0434057844151..ea321c5ae958829d739137eae3548f5cbf07c540 100644 --- a/indra/llvfs/tests/lldir_test.cpp +++ b/indra/llvfs/tests/lldir_test.cpp @@ -28,6 +28,7 @@ #include "linden_common.h" #include "../lldir.h" +#include "../lldiriterator.h" #include "../test/lltut.h" @@ -259,13 +260,12 @@ namespace tut std::string makeTestFile( const std::string& dir, const std::string& file ) { - std::string delim = gDirUtilp->getDirDelimiter(); - std::string path = dir + delim + file; + std::string path = dir + file; LLFILE* handle = LLFile::fopen( path, "w" ); ensure("failed to open test file '"+path+"'", handle != NULL ); // Harbison & Steele, 4th ed., p. 366: "If an error occurs, fputs // returns EOF; otherwise, it returns some other, nonnegative value." - ensure("failed to write to test file '"+path+"'", fputs("test file", handle) >= 0); + ensure("failed to write to test file '"+path+"'", EOF != fputs("test file", handle) ); fclose(handle); return path; } @@ -290,7 +290,7 @@ namespace tut } static const char* DirScanFilename[5] = { "file1.abc", "file2.abc", "file1.xyz", "file2.xyz", "file1.mno" }; - + void scanTest(const std::string& directory, const std::string& pattern, bool correctResult[5]) { @@ -300,7 +300,8 @@ namespace tut bool filesFound[5] = { false, false, false, false, false }; //std::cerr << "searching '"+directory+"' for '"+pattern+"'\n"; - while ( found <= 5 && gDirUtilp->getNextFileInDir(directory, pattern, scanResult) ) + LLDirIterator iter(directory, pattern); + while ( found <= 5 && iter.next(scanResult) ) { found++; //std::cerr << " found '"+scanResult+"'\n"; @@ -334,15 +335,15 @@ namespace tut template<> template<> void LLDirTest_object_t::test<5>() - // getNextFileInDir + // LLDirIterator::next { std::string delim = gDirUtilp->getDirDelimiter(); std::string dirTemp = LLFile::tmpdir(); // Create the same 5 file names of the two directories - std::string dir1 = makeTestDir(dirTemp + "getNextFileInDir"); - std::string dir2 = makeTestDir(dirTemp + "getNextFileInDir"); + std::string dir1 = makeTestDir(dirTemp + "LLDirIterator"); + std::string dir2 = makeTestDir(dirTemp + "LLDirIterator"); std::string dir1files[5]; std::string dir2files[5]; for (int i=0; i<5; i++) @@ -380,19 +381,17 @@ namespace tut scanTest(dir2, "file?.x?z", expected7); // Scan dir2 and see if any file?.??c files are found - // THESE FAIL ON Mac and Windows, SO ARE COMMENTED OUT FOR NOW - // bool expected8[5] = { true, true, false, false, false }; - // scanTest(dir2, "file?.??c", expected8); - // scanTest(dir2, "*.??c", expected8); + bool expected8[5] = { true, true, false, false, false }; + scanTest(dir2, "file?.??c", expected8); + scanTest(dir2, "*.??c", expected8); // Scan dir1 and see if any *.?n? files are found bool expected9[5] = { false, false, false, false, true }; scanTest(dir1, "*.?n?", expected9); // Scan dir1 and see if any *.???? files are found - // THIS ONE FAILS ON WINDOWS (returns three charater suffixes) SO IS COMMENTED OUT FOR NOW - // bool expected10[5] = { false, false, false, false, false }; - // scanTest(dir1, "*.????", expected10); + bool expected10[5] = { false, false, false, false, false }; + scanTest(dir1, "*.????", expected10); // Scan dir1 and see if any ?????.* files are found bool expected11[5] = { true, true, true, true, true }; @@ -402,6 +401,15 @@ namespace tut bool expected12[5] = { false, false, true, true, false }; scanTest(dir1, "??l??.xyz", expected12); + bool expected13[5] = { true, false, true, false, false }; + scanTest(dir1, "file1.{abc,xyz}", expected13); + + bool expected14[5] = { true, true, false, false, false }; + scanTest(dir1, "file[0-9].abc", expected14); + + bool expected15[5] = { true, true, false, false, false }; + scanTest(dir1, "file[!a-z].abc", expected15); + // clean up all test files and directories for (int i=0; i<5; i++) { diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 77552663abd8d72458b8d9c86e6b7c0c8c00883c..7d908df5ceed5469064c52543e304114be028dc7 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -64,6 +64,7 @@ #include "lltool.h" #include "lltoolmgr.h" #include "lltrans.h" +#include "llurlentry.h" #include "llviewercontrol.h" #include "llviewerdisplay.h" #include "llviewerjoystick.h" @@ -649,6 +650,10 @@ void LLAgent::setRegion(LLViewerRegion *regionp) } mRegionp = regionp; + // Pass the region host to LLUrlEntryParcel to resolve parcel name + // with a server request. + LLUrlEntryParcel::setRegionHost(getRegionHost()); + // Must shift hole-covering water object locations because local // coordinate frame changed. LLWorld::getInstance()->updateWaterObjects(); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 80734b0d41ae5231d670a03cf50c2bb5ef8f5868..f40fed5ad3450010bbfbc964f2b0b0332592cb84 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1300,8 +1300,16 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) return false; } - // Check whether the outfit contains the full set of body parts (shape+skin+hair+eyes). - return getCanMakeFolderIntoOutfit(outfit_cat_id); + // Check whether the outfit contains any wearables we aren't wearing already (STORM-702). + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true); + gInventory.collectDescendentsIf(outfit_cat_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_worn); + return items.size() > 0; } void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8a3f3a14edf91ade03b586112aabc7fcb003cda7..fab6343864a6394db71fd24a8336bf072a80af40 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -90,10 +90,12 @@ // Linden library includes #include "llavatarnamecache.h" +#include "lldiriterator.h" #include "llimagej2c.h" #include "llmemory.h" #include "llprimitive.h" #include "llurlaction.h" +#include "llurlentry.h" #include "llvfile.h" #include "llvfsthread.h" #include "llvolumemgr.h" @@ -3301,7 +3303,9 @@ void LLAppViewer::migrateCacheDirectory() S32 file_count = 0; std::string file_name; std::string mask = delimiter + "*.*"; - while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name)) + + LLDirIterator iter(old_cache_dir, mask); + while (iter.next(file_name)) { if (file_name == "." || file_name == "..") continue; std::string source_path = old_cache_dir + delimiter + file_name; @@ -3520,7 +3524,8 @@ bool LLAppViewer::initCache() dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""); std::string found_file; - if (gDirUtilp->getNextFileInDir(dir, mask, found_file)) + LLDirIterator iter(dir, mask); + if (iter.next(found_file)) { old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file; @@ -4578,6 +4583,10 @@ void LLAppViewer::disconnectViewer() cleanup_xfer_manager(); gDisconnected = TRUE; + + // Pass the connection state to LLUrlEntryParcel not to attempt + // parcel info requests while disconnected. + LLUrlEntryParcel::setDisconnected(gDisconnected); } void LLAppViewer::forceErrorLLError() diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 898cc1c0ba8686bc615b685e2d17353c5d51dbb9..fc7a27e5e04ec302e8d0ff161e2de215c888717f 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -30,6 +30,7 @@ #include "llcommandlineparser.h" +#include "lldiriterator.h" #include "llmemtype.h" #include "llurldispatcher.h" // SLURL from other app instance #include "llviewernetwork.h" @@ -504,7 +505,9 @@ std::string LLAppViewerLinux::generateSerialNumber() // trawl /dev/disk/by-uuid looking for a good-looking UUID to grab std::string this_name; - while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name)) + + LLDirIterator iter(uuiddir, "*"); + while (iter.next(this_name)) { if (this_name.length() > best.length() || (this_name.length() == best.length() && diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index f12bc16d4b958eff310c64053081e92f15f93ab3..dd5bc74b2a7a2154b09d838c90850a1d162e40c6 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -126,6 +126,7 @@ void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason) break; } LLUploadDialog::modalUploadFinished(); + LLFilePicker::instance().reset(); // unlock file picker when bulk upload fails } //virtual diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 11b3379814a52d3de44e343675abd7196417e5e9..182d3d23f1a868355b19dfb6be4fe03959a2ade6 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -35,6 +35,7 @@ #include "llfloateruipreview.h" // Own header // Internal utility +#include "lldiriterator.h" #include "lleventtimer.h" #include "llexternaleditor.h" #include "llrender.h" @@ -481,9 +482,11 @@ BOOL LLFloaterUIPreview::postBuild() std::string language_directory; std::string xui_dir = get_xui_dir(); // directory containing localizations -- don't forget trailing delim mLanguageSelection->removeall(); // clear out anything temporarily in list from XML + + LLDirIterator iter(xui_dir, "*"); while(found) // for every directory { - if((found = gDirUtilp->getNextFileInDir(xui_dir, "*", language_directory))) // get next directory + if((found = iter.next(language_directory))) // get next directory { std::string full_path = xui_dir + language_directory; if(LLFile::isfile(full_path.c_str())) // if it's not a directory, skip it @@ -635,42 +638,51 @@ void LLFloaterUIPreview::refreshList() mFileList->clearRows(); // empty list std::string name; BOOL found = TRUE; + + LLDirIterator floater_iter(getLocalizedDirectory(), "floater_*.xml"); while(found) // for every floater file that matches the pattern { - if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "floater_*.xml", name))) // get next file matching pattern + if((found = floater_iter.next(name))) // get next file matching pattern { addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) } } found = TRUE; + + LLDirIterator inspect_iter(getLocalizedDirectory(), "inspect_*.xml"); while(found) // for every inspector file that matches the pattern { - if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "inspect_*.xml", name))) // get next file matching pattern + if((found = inspect_iter.next(name))) // get next file matching pattern { addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) } } found = TRUE; + + LLDirIterator menu_iter(getLocalizedDirectory(), "menu_*.xml"); while(found) // for every menu file that matches the pattern { - if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "menu_*.xml", name))) // get next file matching pattern + if((found = menu_iter.next(name))) // get next file matching pattern { addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) } } found = TRUE; + + LLDirIterator panel_iter(getLocalizedDirectory(), "panel_*.xml"); while(found) // for every panel file that matches the pattern { - if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "panel_*.xml", name))) // get next file matching pattern + if((found = panel_iter.next(name))) // get next file matching pattern { addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) } } - found = TRUE; + + LLDirIterator sidepanel_iter(getLocalizedDirectory(), "sidepanel_*.xml"); while(found) // for every sidepanel file that matches the pattern { - if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", name))) // get next file matching pattern + if((found = sidepanel_iter.next(name))) // get next file matching pattern { addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) } diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 51726112a0fccb2c2081a701a8ddf16e9d2016bd..058567492be7ad57ee9a8a14cfd6b812b3827788 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -1,402 +1,402 @@ -/** - * @file llfloaterwebcontent.cpp - * @brief floater for displaying web content - e.g. profiles and search (eventually) - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llcombobox.h" -#include "lliconctrl.h" -#include "llfloaterreg.h" -#include "lllayoutstack.h" -#include "llpluginclassmedia.h" -#include "llprogressbar.h" -#include "lltextbox.h" -#include "llurlhistory.h" -#include "llviewercontrol.h" -#include "llweb.h" -#include "llwindow.h" - -#include "llfloaterwebcontent.h" - -LLFloaterWebContent::LLFloaterWebContent( const LLSD& key ) - : LLFloater( key ) -{ - mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this )); - mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this )); - mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this )); - mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this )); - mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this )); - mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this )); -} - -BOOL LLFloaterWebContent::postBuild() -{ - // these are used in a bunch of places so cache them - mWebBrowser = getChild< LLMediaCtrl >( "webbrowser" ); - mAddressCombo = getChild< LLComboBox >( "address" ); - mStatusBarText = getChild< LLTextBox >( "statusbartext" ); - mStatusBarProgress = getChild<LLProgressBar>("statusbarprogress" ); - - // observe browser events - mWebBrowser->addObserver( this ); - - // these buttons are always enabled - getChildView("reload")->setEnabled( true ); - getChildView("popexternal")->setEnabled( true ); - - // cache image for secure browsing - mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag"); - - // initialize the URL history using the system URL History manager - initializeURLHistory(); - - return TRUE; -} - -void LLFloaterWebContent::initializeURLHistory() -{ - // start with an empty list - LLCtrlListInterface* url_list = childGetListInterface("address"); - if (url_list) - { - url_list->operateOnAll(LLCtrlListInterface::OP_DELETE); - } - - // Get all of the entries in the "browser" collection - LLSD browser_history = LLURLHistory::getURLHistory("browser"); - LLSD::array_iterator iter_history = - browser_history.beginArray(); - LLSD::array_iterator end_history = - browser_history.endArray(); - for(; iter_history != end_history; ++iter_history) - { - std::string url = (*iter_history).asString(); - if(! url.empty()) - url_list->addSimpleElement(url); - } -} - -//static -void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid ) -{ - lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl; - - std::string tag = target; - - if(target.empty() || target == "_blank") - { - if(!uuid.empty()) - { - tag = uuid; - } - else - { - // create a unique tag for this instance - LLUUID id; - id.generate(); - tag = id.asString(); - } - } - - S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit"); - - if(LLFloaterReg::findInstance("web_content", tag) != NULL) - { - // There's already a web browser for this tag, so we won't be opening a new window. - } - else if(browser_window_limit != 0) - { - // showInstance will open a new window. Figure out how many web browsers are already open, - // and close the least recently opened one if this will put us over the limit. - - LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("web_content"); - lldebugs << "total instance count is " << instances.size() << llendl; - - for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++) - { - lldebugs << " " << (*iter)->getKey() << llendl; - } - - if(instances.size() >= (size_t)browser_window_limit) - { - // Destroy the least recently opened instance - (*instances.begin())->closeFloater(); - } - } - - LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> (LLFloaterReg::showInstance("web_content", tag)); - llassert(browser); - if(browser) - { - browser->mUUID = uuid; - - // tell the browser instance to load the specified URL - browser->open_media(url, target); - LLViewerMedia::proxyWindowOpened(target, uuid); - } -} - -//static -void LLFloaterWebContent::closeRequest(const std::string &uuid) -{ - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); - lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) - { - LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter); - lldebugs << " " << i->mUUID << llendl; - if (i && i->mUUID == uuid) - { - i->closeFloater(false); - return; - } - } -} - -//static -void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height) -{ - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); - lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) - { - LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter); - lldebugs << " " << i->mUUID << llendl; - if (i && i->mUUID == uuid) - { - i->geometryChanged(x, y, width, height); - return; - } - } -} - -void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) -{ - // Make sure the layout of the browser control is updated, so this calculation is correct. - LLLayoutStack::updateClass(); - - // TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc. - LLCoordWindow window_size; - getWindow()->getSize(&window_size); - - // Adjust width and height for the size of the chrome on the web Browser window. - width += getRect().getWidth() - mWebBrowser->getRect().getWidth(); - height += getRect().getHeight() - mWebBrowser->getRect().getHeight(); - - LLRect geom; - geom.setOriginAndSize(x, window_size.mY - (y + height), width, height); - - lldebugs << "geometry change: " << geom << llendl; - - handleReshape(geom,false); -} - -void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target) -{ - // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. - mWebBrowser->setHomePageUrl(web_url, "text/html"); - mWebBrowser->setTarget(target); - mWebBrowser->navigateTo(web_url, "text/html"); - set_current_url(web_url); -} - -//virtual -void LLFloaterWebContent::onClose(bool app_quitting) -{ - LLViewerMedia::proxyWindowClosed(mUUID); - destroy(); -} - -// virtual -void LLFloaterWebContent::draw() -{ - // this is asychronous so we need to keep checking - getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() ); - getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() ); - - LLFloater::draw(); -} - -// virtual -void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) -{ - if(event == MEDIA_EVENT_LOCATION_CHANGED) - { - const std::string url = self->getLocation(); - - if ( url.length() ) - mStatusBarText->setText( url ); - - set_current_url( url ); - } - else if(event == MEDIA_EVENT_NAVIGATE_BEGIN) - { - // flags are sent with this event - getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); - getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); - - // toggle visibility of these buttons based on browser state - getChildView("reload")->setVisible( false ); - getChildView("stop")->setVisible( true ); - - // turn "on" progress bar now we're about to start loading - mStatusBarProgress->setVisible( true ); - } - else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) - { - // flags are sent with this event - getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); - getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); - - // toggle visibility of these buttons based on browser state - getChildView("reload")->setVisible( true ); - getChildView("stop")->setVisible( false ); - - // turn "off" progress bar now we're loaded - mStatusBarProgress->setVisible( false ); - - // we populate the status bar with URLs as they change so clear it now we're done - const std::string end_str = ""; - mStatusBarText->setText( end_str ); - - // decide if secure browsing icon should be displayed - std::string prefix = std::string("https://"); - std::string test_prefix = mCurrentURL.substr(0, prefix.length()); - LLStringUtil::toLower(test_prefix); - if(test_prefix == prefix) - { - mSecureLockIcon->setVisible(true); - } - else - { - mSecureLockIcon->setVisible(false); - } - } - else if(event == MEDIA_EVENT_CLOSE_REQUEST) - { - // The browser instance wants its window closed. - closeFloater(); - } - else if(event == MEDIA_EVENT_GEOMETRY_CHANGE) - { - geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight()); - } - else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED ) - { - const std::string text = self->getStatusText(); - if ( text.length() ) - mStatusBarText->setText( text ); - } - else if(event == MEDIA_EVENT_PROGRESS_UPDATED ) - { - int percent = (int)self->getProgressPercent(); - mStatusBarProgress->setValue( percent ); - } - else if(event == MEDIA_EVENT_NAME_CHANGED ) - { - std::string page_title = self->getMediaName(); - // simulate browser behavior - title is empty, use the current URL - if ( page_title.length() > 0 ) - setTitle( page_title ); - else - setTitle( mCurrentURL ); - } - else if(event == MEDIA_EVENT_LINK_HOVERED ) - { - const std::string link = self->getHoverLink(); - mStatusBarText->setText( link ); - } -} - -void LLFloaterWebContent::set_current_url(const std::string& url) -{ - mCurrentURL = url; - - // serialize url history into the system URL History manager - LLURLHistory::removeURL("browser", mCurrentURL); - LLURLHistory::addURL("browser", mCurrentURL); - - mAddressCombo->remove( mCurrentURL ); - mAddressCombo->add( mCurrentURL ); - mAddressCombo->selectByValue( mCurrentURL ); -} - -void LLFloaterWebContent::onClickForward() -{ - mWebBrowser->navigateForward(); -} - -void LLFloaterWebContent::onClickBack() -{ - mWebBrowser->navigateBack(); -} - -void LLFloaterWebContent::onClickReload() -{ - - if( mWebBrowser->getMediaPlugin() ) - { - bool ignore_cache = true; - mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache ); - } - else - { - mWebBrowser->navigateTo(mCurrentURL); - } -} - -void LLFloaterWebContent::onClickStop() -{ - if( mWebBrowser->getMediaPlugin() ) - mWebBrowser->getMediaPlugin()->browse_stop(); - - // still should happen when we catch the navigate complete event - // but sometimes (don't know why) that event isn't sent from Qt - // and we getto a point where the stop button stays active. - getChildView("reload")->setVisible( true ); - getChildView("stop")->setVisible( false ); -} - -void LLFloaterWebContent::onEnterAddress() -{ - // make sure there is at least something there. - // (perhaps this test should be for minimum length of a URL) - std::string url = mAddressCombo->getValue().asString(); - if ( url.length() > 0 ) - { - mWebBrowser->navigateTo( url, "text/html"); - }; -} - -void LLFloaterWebContent::onPopExternal() -{ - // make sure there is at least something there. - // (perhaps this test should be for minimum length of a URL) - std::string url = mAddressCombo->getValue().asString(); - if ( url.length() > 0 ) - { - LLWeb::loadURLExternal( url ); - }; -} +/** + * @file llfloaterwebcontent.cpp + * @brief floater for displaying web content - e.g. profiles and search (eventually) + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llcombobox.h" +#include "lliconctrl.h" +#include "llfloaterreg.h" +#include "lllayoutstack.h" +#include "llpluginclassmedia.h" +#include "llprogressbar.h" +#include "lltextbox.h" +#include "llurlhistory.h" +#include "llviewercontrol.h" +#include "llweb.h" +#include "llwindow.h" + +#include "llfloaterwebcontent.h" + +LLFloaterWebContent::LLFloaterWebContent( const LLSD& key ) + : LLFloater( key ) +{ + mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this )); + mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this )); + mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this )); + mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this )); + mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this )); + mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this )); +} + +BOOL LLFloaterWebContent::postBuild() +{ + // these are used in a bunch of places so cache them + mWebBrowser = getChild< LLMediaCtrl >( "webbrowser" ); + mAddressCombo = getChild< LLComboBox >( "address" ); + mStatusBarText = getChild< LLTextBox >( "statusbartext" ); + mStatusBarProgress = getChild<LLProgressBar>("statusbarprogress" ); + + // observe browser events + mWebBrowser->addObserver( this ); + + // these buttons are always enabled + getChildView("reload")->setEnabled( true ); + getChildView("popexternal")->setEnabled( true ); + + // cache image for secure browsing + mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag"); + + // initialize the URL history using the system URL History manager + initializeURLHistory(); + + return TRUE; +} + +void LLFloaterWebContent::initializeURLHistory() +{ + // start with an empty list + LLCtrlListInterface* url_list = childGetListInterface("address"); + if (url_list) + { + url_list->operateOnAll(LLCtrlListInterface::OP_DELETE); + } + + // Get all of the entries in the "browser" collection + LLSD browser_history = LLURLHistory::getURLHistory("browser"); + LLSD::array_iterator iter_history = + browser_history.beginArray(); + LLSD::array_iterator end_history = + browser_history.endArray(); + for(; iter_history != end_history; ++iter_history) + { + std::string url = (*iter_history).asString(); + if(! url.empty()) + url_list->addSimpleElement(url); + } +} + +//static +void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid ) +{ + lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl; + + std::string tag = target; + + if(target.empty() || target == "_blank") + { + if(!uuid.empty()) + { + tag = uuid; + } + else + { + // create a unique tag for this instance + LLUUID id; + id.generate(); + tag = id.asString(); + } + } + + S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit"); + + if(LLFloaterReg::findInstance("web_content", tag) != NULL) + { + // There's already a web browser for this tag, so we won't be opening a new window. + } + else if(browser_window_limit != 0) + { + // showInstance will open a new window. Figure out how many web browsers are already open, + // and close the least recently opened one if this will put us over the limit. + + LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("web_content"); + lldebugs << "total instance count is " << instances.size() << llendl; + + for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++) + { + lldebugs << " " << (*iter)->getKey() << llendl; + } + + if(instances.size() >= (size_t)browser_window_limit) + { + // Destroy the least recently opened instance + (*instances.begin())->closeFloater(); + } + } + + LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> (LLFloaterReg::showInstance("web_content", tag)); + llassert(browser); + if(browser) + { + browser->mUUID = uuid; + + // tell the browser instance to load the specified URL + browser->open_media(url, target); + LLViewerMedia::proxyWindowOpened(target, uuid); + } +} + +//static +void LLFloaterWebContent::closeRequest(const std::string &uuid) +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); + lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) + { + LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter); + lldebugs << " " << i->mUUID << llendl; + if (i && i->mUUID == uuid) + { + i->closeFloater(false); + return; + } + } +} + +//static +void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height) +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); + lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) + { + LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter); + lldebugs << " " << i->mUUID << llendl; + if (i && i->mUUID == uuid) + { + i->geometryChanged(x, y, width, height); + return; + } + } +} + +void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) +{ + // Make sure the layout of the browser control is updated, so this calculation is correct. + LLLayoutStack::updateClass(); + + // TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc. + LLCoordWindow window_size; + getWindow()->getSize(&window_size); + + // Adjust width and height for the size of the chrome on the web Browser window. + width += getRect().getWidth() - mWebBrowser->getRect().getWidth(); + height += getRect().getHeight() - mWebBrowser->getRect().getHeight(); + + LLRect geom; + geom.setOriginAndSize(x, window_size.mY - (y + height), width, height); + + lldebugs << "geometry change: " << geom << llendl; + + handleReshape(geom,false); +} + +void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target) +{ + // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. + mWebBrowser->setHomePageUrl(web_url, "text/html"); + mWebBrowser->setTarget(target); + mWebBrowser->navigateTo(web_url, "text/html"); + set_current_url(web_url); +} + +//virtual +void LLFloaterWebContent::onClose(bool app_quitting) +{ + LLViewerMedia::proxyWindowClosed(mUUID); + destroy(); +} + +// virtual +void LLFloaterWebContent::draw() +{ + // this is asychronous so we need to keep checking + getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() ); + getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() ); + + LLFloater::draw(); +} + +// virtual +void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + if(event == MEDIA_EVENT_LOCATION_CHANGED) + { + const std::string url = self->getLocation(); + + if ( url.length() ) + mStatusBarText->setText( url ); + + set_current_url( url ); + } + else if(event == MEDIA_EVENT_NAVIGATE_BEGIN) + { + // flags are sent with this event + getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); + getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); + + // toggle visibility of these buttons based on browser state + getChildView("reload")->setVisible( false ); + getChildView("stop")->setVisible( true ); + + // turn "on" progress bar now we're about to start loading + mStatusBarProgress->setVisible( true ); + } + else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) + { + // flags are sent with this event + getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); + getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); + + // toggle visibility of these buttons based on browser state + getChildView("reload")->setVisible( true ); + getChildView("stop")->setVisible( false ); + + // turn "off" progress bar now we're loaded + mStatusBarProgress->setVisible( false ); + + // we populate the status bar with URLs as they change so clear it now we're done + const std::string end_str = ""; + mStatusBarText->setText( end_str ); + + // decide if secure browsing icon should be displayed + std::string prefix = std::string("https://"); + std::string test_prefix = mCurrentURL.substr(0, prefix.length()); + LLStringUtil::toLower(test_prefix); + if(test_prefix == prefix) + { + mSecureLockIcon->setVisible(true); + } + else + { + mSecureLockIcon->setVisible(false); + } + } + else if(event == MEDIA_EVENT_CLOSE_REQUEST) + { + // The browser instance wants its window closed. + closeFloater(); + } + else if(event == MEDIA_EVENT_GEOMETRY_CHANGE) + { + geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight()); + } + else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED ) + { + const std::string text = self->getStatusText(); + if ( text.length() ) + mStatusBarText->setText( text ); + } + else if(event == MEDIA_EVENT_PROGRESS_UPDATED ) + { + int percent = (int)self->getProgressPercent(); + mStatusBarProgress->setValue( percent ); + } + else if(event == MEDIA_EVENT_NAME_CHANGED ) + { + std::string page_title = self->getMediaName(); + // simulate browser behavior - title is empty, use the current URL + if ( page_title.length() > 0 ) + setTitle( page_title ); + else + setTitle( mCurrentURL ); + } + else if(event == MEDIA_EVENT_LINK_HOVERED ) + { + const std::string link = self->getHoverLink(); + mStatusBarText->setText( link ); + } +} + +void LLFloaterWebContent::set_current_url(const std::string& url) +{ + mCurrentURL = url; + + // serialize url history into the system URL History manager + LLURLHistory::removeURL("browser", mCurrentURL); + LLURLHistory::addURL("browser", mCurrentURL); + + mAddressCombo->remove( mCurrentURL ); + mAddressCombo->add( mCurrentURL ); + mAddressCombo->selectByValue( mCurrentURL ); +} + +void LLFloaterWebContent::onClickForward() +{ + mWebBrowser->navigateForward(); +} + +void LLFloaterWebContent::onClickBack() +{ + mWebBrowser->navigateBack(); +} + +void LLFloaterWebContent::onClickReload() +{ + + if( mWebBrowser->getMediaPlugin() ) + { + bool ignore_cache = true; + mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache ); + } + else + { + mWebBrowser->navigateTo(mCurrentURL); + } +} + +void LLFloaterWebContent::onClickStop() +{ + if( mWebBrowser->getMediaPlugin() ) + mWebBrowser->getMediaPlugin()->browse_stop(); + + // still should happen when we catch the navigate complete event + // but sometimes (don't know why) that event isn't sent from Qt + // and we getto a point where the stop button stays active. + getChildView("reload")->setVisible( true ); + getChildView("stop")->setVisible( false ); +} + +void LLFloaterWebContent::onEnterAddress() +{ + // make sure there is at least something there. + // (perhaps this test should be for minimum length of a URL) + std::string url = mAddressCombo->getValue().asString(); + if ( url.length() > 0 ) + { + mWebBrowser->navigateTo( url, "text/html"); + }; +} + +void LLFloaterWebContent::onPopExternal() +{ + // make sure there is at least something there. + // (perhaps this test should be for minimum length of a URL) + std::string url = mAddressCombo->getValue().asString(); + if ( url.length() > 0 ) + { + LLWeb::loadURLExternal( url ); + }; +} diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 001d822ada48b918eb4b5e0b8243377984224c44..ecc7e970d865c5ac94f181abe08224e0962cdf7b 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -1,82 +1,82 @@ -/** - * @file llfloaterwebcontent.h - * @brief floater for displaying web content - e.g. profiles and search (eventually) - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLFLOATERWEBCONTENT_H -#define LL_LLFLOATERWEBCONTENT_H - -#include "llfloater.h" -#include "llmediactrl.h" - -class LLMediaCtrl; -class LLComboBox; -class LLTextBox; -class LLProgressBar; -class LLIconCtrl; - -class LLFloaterWebContent : - public LLFloater, - public LLViewerMediaObserver -{ -public: - LOG_CLASS(LLFloaterWebContent); - LLFloaterWebContent(const LLSD& key); - +/** + * @file llfloaterwebcontent.h + * @brief floater for displaying web content - e.g. profiles and search (eventually) + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERWEBCONTENT_H +#define LL_LLFLOATERWEBCONTENT_H + +#include "llfloater.h" +#include "llmediactrl.h" + +class LLMediaCtrl; +class LLComboBox; +class LLTextBox; +class LLProgressBar; +class LLIconCtrl; + +class LLFloaterWebContent : + public LLFloater, + public LLViewerMediaObserver +{ +public: + LOG_CLASS(LLFloaterWebContent); + LLFloaterWebContent(const LLSD& key); + void initializeURLHistory(); - - static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null); - - static void closeRequest(const std::string &uuid); - static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height); - void geometryChanged(S32 x, S32 y, S32 width, S32 height); - - /* virtual */ BOOL postBuild(); - /* virtual */ void onClose(bool app_quitting); - /* virtual */ void draw(); - - // inherited from LLViewerMediaObserver - /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); - - void onClickBack(); - void onClickForward(); - void onClickReload(); - void onClickStop(); - void onEnterAddress(); - void onPopExternal(); - -private: - void open_media(const std::string& media_url, const std::string& target); - void set_current_url(const std::string& url); - - LLMediaCtrl* mWebBrowser; - LLComboBox* mAddressCombo; - LLIconCtrl *mSecureLockIcon; - LLTextBox* mStatusBarText; - LLProgressBar* mStatusBarProgress; - std::string mCurrentURL; - std::string mUUID; -}; - -#endif // LL_LLFLOATERWEBCONTENT_H + + static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null); + + static void closeRequest(const std::string &uuid); + static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height); + void geometryChanged(S32 x, S32 y, S32 width, S32 height); + + /* virtual */ BOOL postBuild(); + /* virtual */ void onClose(bool app_quitting); + /* virtual */ void draw(); + + // inherited from LLViewerMediaObserver + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + + void onClickBack(); + void onClickForward(); + void onClickReload(); + void onClickStop(); + void onEnterAddress(); + void onPopExternal(); + +private: + void open_media(const std::string& media_url, const std::string& target); + void set_current_url(const std::string& url); + + LLMediaCtrl* mWebBrowser; + LLComboBox* mAddressCombo; + LLIconCtrl *mSecureLockIcon; + LLTextBox* mStatusBarText; + LLProgressBar* mStatusBarProgress; + std::string mCurrentURL; + std::string mUUID; +}; + +#endif // LL_LLFLOATERWEBCONTENT_H diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index ce305dcd89741303bfc567e4f87732987d8d78fb..afd565bb26424a7882edbb444ece40a2bb2b6afe 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -280,19 +280,19 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name) { if (av_name.mIsDummy) - { - S32 separator_index = mName.rfind(" "); - std::string name = mName.substr(0, separator_index); - ++separator_index; - std::string conference_word = mName.substr(separator_index, mName.length()); - - // additional check that session name is what we expected - if ("Conference" == conference_word) - { - LLStringUtil::format_map_t args; - args["[AGENT_NAME]"] = name; - LLTrans::findString(mName, "conference-title-incoming", args); - } + { + S32 separator_index = mName.rfind(" "); + std::string name = mName.substr(0, separator_index); + ++separator_index; + std::string conference_word = mName.substr(separator_index, mName.length()); + + // additional check that session name is what we expected + if ("Conference" == conference_word) + { + LLStringUtil::format_map_t args; + args["[AGENT_NAME]"] = name; + LLTrans::findString(mName, "conference-title-incoming", args); + } } else { diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index e765a8da2fe69167dfd88eb8c8828cdfda28aae7..a15776c20791c4ab1aad7b9ead90491640203ae0 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -100,7 +100,7 @@ class LLIMModel : public LLSingleton<LLIMModel> void onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name); - void onAdHocNameCache(const LLAvatarName& av_name); + void onAdHocNameCache(const LLAvatarName& av_name); //*TODO make private static std::string generateHash(const std::set<LLUUID>& sorted_uuids); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ef2086911401ccdcda96cdaf0d3196fdccdd1694..61d0a150b719603072987d96288f4fed97d4b559 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -686,6 +686,12 @@ bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* it return false; } + // Skip broken links. + if (vitem->getIsBrokenLink()) + { + return false; + } + return (bool) get_is_item_worn(item->getUUID()) == mIsWorn; } diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 1527f8f4c9484ca1a36fb9aaad701922b40d4061..55164f609494e7e1214fb29cc1b50b2f6faa196c 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -547,6 +547,10 @@ void LLLocationInputCtrl::onFocusLost() { LLUICtrl::onFocusLost(); refreshLocation(); + + // Setting cursor to 0 to show the left edge of the text. See STORM-370. + mTextEntry->setCursor(0); + if(mTextEntry->hasSelection()){ mTextEntry->deselect(); } diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 0121bbb1ed3dc88164c88cc39f66ee9c0aa1841c..b09cfbe90754f7db7186b2d637b6d9db01023f8e 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -32,6 +32,7 @@ #include "lltrans.h" #include "llviewercontrol.h" +#include "lldiriterator.h" #include "llinstantmessage.h" #include "llsingleton.h" // for LLSingleton @@ -89,15 +90,15 @@ const static boost::regex TIMESTAMP_AND_STUFF("^(\\[\\d{4}/\\d{1,2}/\\d{1,2}\\s+ */ const static boost::regex NAME_AND_TEXT("([^:]+[:]{1})?(\\s*)(.*)"); -/** - * These are recognizers for matching the names of ad-hoc conferences when generating the log file name - * On invited side, an ad-hoc is named like "<first name> <last name> Conference 2010/11/19 03:43 f0f4" - * On initiating side, an ad-hoc is named like Ad-hoc Conference hash<hash>" - * If the naming system for ad-hoc conferences are change in LLIMModel::LLIMSession::buildHistoryFileName() - * then these definition need to be adjusted as well. - */ -const static boost::regex INBOUND_CONFERENCE("^[a-zA-Z]{1,31} [a-zA-Z]{1,31} Conference [0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2} [0-9a-f]{4}"); -const static boost::regex OUTBOUND_CONFERENCE("^Ad-hoc Conference hash[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"); +/** + * These are recognizers for matching the names of ad-hoc conferences when generating the log file name + * On invited side, an ad-hoc is named like "<first name> <last name> Conference 2010/11/19 03:43 f0f4" + * On initiating side, an ad-hoc is named like Ad-hoc Conference hash<hash>" + * If the naming system for ad-hoc conferences are change in LLIMModel::LLIMSession::buildHistoryFileName() + * then these definition need to be adjusted as well. + */ +const static boost::regex INBOUND_CONFERENCE("^[a-zA-Z]{1,31} [a-zA-Z]{1,31} Conference [0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2} [0-9a-f]{4}"); +const static boost::regex OUTBOUND_CONFERENCE("^Ad-hoc Conference hash[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"); //is used to parse complex object names like "Xstreet SL Terminal v2.2.5 st" const static std::string NAME_TEXT_DIVIDER(": "); @@ -601,7 +602,8 @@ std::string LLLogChat::oldLogFileName(std::string filename) //LL_INFOS("") << "Checking:" << directory << " for " << pattern << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ std::vector<std::string> allfiles; - while (gDirUtilp->getNextFileInDir(directory, pattern, scanResult)) + LLDirIterator iter(directory, pattern); + while (iter.next(scanResult)) { //LL_INFOS("") << "Found :" << scanResult << LL_ENDL; allfiles.push_back(scanResult); diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp index 5ea94e06116c5546a4baf9f7a801f629acb54530..d3c9c3e1314014e3309d8a1631b52092d6872aef 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llpanelme.cpp @@ -76,17 +76,19 @@ void LLPanelMe::onOpen(const LLSD& key) { LLPanelProfile::onOpen(key); - // Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068) - bool opened = gSavedSettings.getBOOL("MePanelOpened"); - // In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this - // is the last time onOpen() is called - if( !opened && !LLSideTray::getInstance()->getCollapsed() ) - { - buildEditPanel(); - openPanel(mEditPanel, getAvatarId()); - - gSavedSettings.setBOOL("MePanelOpened", true); - } + // Removed this action as per SOCIAL-431 The first time a new resident opens the profile tab + // in the sidebar, they see the old profile editing panel + // + //// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068) + //bool opened = gSavedSettings.getBOOL("MePanelOpened"); + //// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this + //// is the last time onOpen() is called + //if( !opened && !LLSideTray::getInstance()->getCollapsed() ) + //{ + // buildEditPanel(); + // openPanel(mEditPanel, getAvatarId()); + // gSavedSettings.setBOOL("MePanelOpened", true); + //} } bool LLPanelMe::notifyChildren(const LLSD& info) diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index e5ef51bdd18c6b54c1ac0e801fa3567f6f15ec87..3862dac340d0db44d3ed0411a56c7cbee3a4ac01 100644 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -33,6 +33,7 @@ #include "llpanel.h" #include "llhttpclient.h" #include "llsdserialize.h" +#include "llurlentry.h" #include "llviewerregion.h" #include "llview.h" @@ -168,6 +169,18 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v { observers.erase(*i); } + + LLUrlEntryParcel::LLParcelData url_data; + url_data.parcel_id = parcel_data.parcel_id; + url_data.name = parcel_data.name; + url_data.sim_name = parcel_data.sim_name; + url_data.global_x = parcel_data.global_x; + url_data.global_y = parcel_data.global_y; + url_data.global_z = parcel_data.global_z; + + // Pass the parcel data to LLUrlEntryParcel to render + // human readable parcel name. + LLUrlEntryParcel::processParcelInfo(url_data); } void LLRemoteParcelInfoProcessor::sendParcelInfoRequest(const LLUUID& parcel_id) diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index aef665a35cd4db8079689d71296109b8f8dc4c40..19d1bdee862b5bafd624cae04bb367724fd0eb2d 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -498,8 +498,8 @@ class LLSideTrayButton : public LLButton LLSideTray::Params::Params() : collapsed("collapsed",false), - tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("sidebar_tab_left.tga")), - tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("button_enabled_selected_32x128.tga")), + tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Off.png")), + tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Selected.png")), default_button_width("tab_btn_width",32), default_button_height("tab_btn_height",32), default_button_margin("tab_btn_margin",0) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 611f9de2e6db8dcdb24f2edf9fe9789c0bcd6684..5617eea4c339a3763c1ad151c3ca47552307e488 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -139,6 +139,7 @@ #include "lltrans.h" #include "llui.h" #include "llurldispatcher.h" +#include "llurlentry.h" #include "llslurl.h" #include "llurlhistory.h" #include "llurlwhitelist.h" @@ -2882,9 +2883,17 @@ bool process_login_success_response() if(!text.empty()) gAgentID.set(text); gDebugInfo["AgentID"] = text; + // Agent id needed for parcel info request in LLUrlEntryParcel + // to resolve parcel name. + LLUrlEntryParcel::setAgentID(gAgentID); + text = response["session_id"].asString(); if(!text.empty()) gAgentSessionID.set(text); gDebugInfo["SessionID"] = text; + + // Session id needed for parcel info request in LLUrlEntryParcel + // to resolve parcel name. + LLUrlEntryParcel::setSessionID(gAgentSessionID); text = response["secure_session_id"].asString(); if(!text.empty()) gAgent.mSecureSessionID.set(text); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index d3b6dcd86f2f937121d61890f9c997ae0869fd08..8a0d0a6623b8138b67227c8225781656979a17be 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -54,6 +54,7 @@ #include "llfilepicker.h" #include "llnotifications.h" +#include "lldiriterator.h" #include "llevent.h" // LLSimpleListener #include "llnotificationsutil.h" #include "lluuid.h" @@ -1115,7 +1116,8 @@ void LLViewerMedia::clearAllCookies() } // the hard part: iterate over all user directories and delete the cookie file from each one - while(gDirUtilp->getNextFileInDir(base_dir, "*_*", filename)) + LLDirIterator dir_iter(base_dir, "*_*"); + while (dir_iter.next(filename)) { target = base_dir; target += filename; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3a37f0355f841b2bca13063da20a0c3079a54fdd..7cc04e0338a0e81e8be7c2c3831531e4b471dfed 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -557,7 +557,7 @@ class LLAdvancedCheckConsole : public view_listener_t new_value = get_visibility( (void*)gDebugView->mMemoryView ); } #endif - + return new_value; } }; @@ -4201,9 +4201,9 @@ class LLObjectEnableReturn : public view_listener_t { virtual bool apply(LLViewerObject* obj) { - return (obj->isOverAgentOwnedLand() || - obj->isOverGroupOwnedLand() || - obj->permModify()); + return + obj->permModify() || + obj->isReturnable(); } } func; const bool firstonly = true; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 4b7e518af388e743c7369e1871ada2e1d48d4ea8..48794c4c9d24b2a917017465aa439e83608f8255 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -518,20 +518,23 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list) // This method returns true if the object is over land owned by the // agent. -BOOL LLViewerObject::isOverAgentOwnedLand() const +bool LLViewerObject::isReturnable() { - return mRegionp - && mRegionp->getParcelOverlay() - && mRegionp->getParcelOverlay()->isOwnedSelf(getPositionRegion()); -} + if (isAttachment()) + { + return false; + } + std::vector<LLBBox> boxes; + boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned()); + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); + } -// This method returns true if the object is over land owned by the -// agent. -BOOL LLViewerObject::isOverGroupOwnedLand() const -{ - return mRegionp - && mRegionp->getParcelOverlay() - && mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion()); + return mRegionp + && mRegionp->objectIsReturnable(getPositionRegion(), boxes); } BOOL LLViewerObject::setParent(LLViewerObject* parent) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 78837ec0a1534b8d99b816445e7d5abbb8f23ba9..614a5e59fa20d586b083d23560626f1e9fa66c58 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -227,12 +227,9 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate virtual BOOL hasLightTexture() const { return FALSE; } // This method returns true if the object is over land owned by - // the agent. - BOOL isOverAgentOwnedLand() const; - - // True if over land owned by group of which the agent is - // either officer or member. - BOOL isOverGroupOwnedLand() const; + // the agent, one of its groups, or it encroaches and + // anti-encroachment is enabled + bool isReturnable(); /* // This method will scan through this object, and then query the diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index eee653b0c163775d9dd97a99734d5c0d5b3098fc..d07e06f6a7ed171e7864517bcc8b6eaa89f287cf 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -145,6 +145,35 @@ BOOL LLViewerParcelOverlay::isOwnedOther(const LLVector3& pos) const return (PARCEL_OWNED == overlay || PARCEL_FOR_SALE == overlay); } +bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) const +{ + // boxes are expected to already be axis aligned + for (U32 i = 0; i < boxes.size(); ++i) + { + LLVector3 min = boxes[i].getMinAgent(); + LLVector3 max = boxes[i].getMaxAgent(); + + S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 top = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + + for (S32 row = top; row <= bottom; row++) + { + for (S32 column = left; column <= right; column++) + { + U8 type = ownership(row, column); + if ((PARCEL_SELF == type) + || (PARCEL_GROUP == type)) + { + return true; + } + } + } + } + return false; +} + BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const { S32 row = S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS); diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 61be2203121ff9d842a223a42c2ed21d84b4f38a..c80baedda6c6256d2fe12af5bee53a3476e1e746 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -30,6 +30,7 @@ // The ownership data for land parcels. // One of these structures per region. +#include "llbbox.h" #include "lldarray.h" #include "llframetimer.h" #include "lluuid.h" @@ -54,6 +55,12 @@ class LLViewerParcelOverlay : public LLGLUpdate BOOL isOwnedSelf(const LLVector3& pos) const; BOOL isOwnedGroup(const LLVector3& pos) const; BOOL isOwnedOther(const LLVector3& pos) const; + + // "encroaches" means the prim hangs over the parcel, but its center + // might be in another parcel. for now, we simply test axis aligned + // bounding boxes which isn't perfect, but is close + bool encroachesOwned(const std::vector<LLBBox>& boxes) const; + BOOL isSoundLocal(const LLVector3& pos) const; BOOL isBuildCameraAllowed(const LLVector3& pos) const; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 5241ea4c07a58966e549f7252f9b74bab0c70d46..3b2cfe656f0475cc3ed5e83f7b48250bf90b7f77 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1407,7 +1407,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("SendUserReportWithScreenshot"); capabilityNames.append("ServerReleaseNotes"); capabilityNames.append("SetDisplayName"); - capabilityNames.append("SimConsole"); capabilityNames.append("SimConsoleAsync"); capabilityNames.append("StartGroupProposal"); capabilityNames.append("TextureStats"); @@ -1504,6 +1503,20 @@ LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) return NULL; } +// the viewer can not yet distinquish between normal- and estate-owned objects +// so we collapse these two bits and enable the UI if either are set +const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT + | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; + +bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const +{ + return (mParcelOverlay != NULL) + && (mParcelOverlay->isOwnedSelf(pos) + || mParcelOverlay->isOwnedGroup(pos) + || ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT) + && mParcelOverlay->encroachesOwned(boxes)) ); +} + void LLViewerRegion::showReleaseNotes() { std::string url = this->getCapability("ServerReleaseNotes"); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index dcefe87b6972f12ce54ff6b16c9c0652c2a6f10b..7c6559203e5fa7606685f67a5cc8b328e1ffdf4a 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -33,6 +33,7 @@ #include "lldarray.h" #include "llwind.h" +#include "llbbox.h" #include "llcloud.h" #include "llstat.h" #include "v3dmath.h" @@ -308,6 +309,8 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface std::string getHttpUrl() const { return mHttpUrl ;} LLSpatialPartition* getSpatialPartition(U32 type); + + bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const; public: struct CompareDistance { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index bb4c5b180416adbbeb2429aa66fc6efcb6eeb87a..fd89044995aab28a4d7107f698ed147bfcec6581 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2106,31 +2106,6 @@ void LLVOAvatar::computeBodySize() gAgent.sendAgentSetAppearance(); } } - -/* debug spam - std::cout << "skull = " << skull << std::endl; // adebug - std::cout << "head = " << head << std::endl; // adebug - std::cout << "head_scale = " << head_scale << std::endl; // adebug - std::cout << "neck = " << neck << std::endl; // adebug - std::cout << "neck_scale = " << neck_scale << std::endl; // adebug - std::cout << "chest = " << chest << std::endl; // adebug - std::cout << "chest_scale = " << chest_scale << std::endl; // adebug - std::cout << "torso = " << torso << std::endl; // adebug - std::cout << "torso_scale = " << torso_scale << std::endl; // adebug - std::cout << std::endl; // adebug - - std::cout << "pelvis_scale = " << pelvis_scale << std::endl;// adebug - std::cout << std::endl; // adebug - - std::cout << "hip = " << hip << std::endl; // adebug - std::cout << "hip_scale = " << hip_scale << std::endl; // adebug - std::cout << "ankle = " << ankle << std::endl; // adebug - std::cout << "ankle_scale = " << ankle_scale << std::endl; // adebug - std::cout << "foot = " << foot << std::endl; // adebug - std::cout << "mBodySize = " << mBodySize << std::endl; // adebug - std::cout << "mPelvisToFoot = " << mPelvisToFoot << std::endl; // adebug - std::cout << std::endl; // adebug -*/ } //------------------------------------------------------------------------ diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index d239347810648188b9b7dd2917a8030d8d6d99a7..4f6ec4ca616ccb4721b9eb7b82b016f97acf9817 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -33,6 +33,7 @@ #include "pipeline.h" #include "llsky.h" +#include "lldiriterator.h" #include "llfloaterreg.h" #include "llsliderctrl.h" #include "llspinctrl.h" @@ -85,11 +86,12 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name) std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", "")); LL_DEBUGS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL; - bool found = true; + bool found = true; + LLDirIterator app_settings_iter(path_name, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name); + found = app_settings_iter.next(name); if(found) { @@ -111,11 +113,12 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name) std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", "")); LL_DEBUGS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL; - found = true; + found = true; + LLDirIterator user_settings_iter(path_name2, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name); + found = user_settings_iter.next(name); if(found) { name=name.erase(name.length()-4); diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index e5f52dfc979b5ef4cd09c8366d6b5263d541b9ba..848efcbb49e5f8e28f3bd393df7767dd003b27ee 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -31,6 +31,7 @@ #include "pipeline.h" #include "llsky.h" +#include "lldiriterator.h" #include "llfloaterreg.h" #include "llsliderctrl.h" #include "llspinctrl.h" @@ -100,11 +101,12 @@ void LLWLParamManager::loadPresets(const std::string& file_name) std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", "")); LL_DEBUGS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL; - bool found = true; + bool found = true; + LLDirIterator app_settings_iter(path_name, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name); + found = app_settings_iter.next(name); if(found) { @@ -126,11 +128,12 @@ void LLWLParamManager::loadPresets(const std::string& file_name) std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", "")); LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL; - found = true; + found = true; + LLDirIterator user_settings_iter(path_name2, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name); + found = user_settings_iter.next(name); if(found) { name=name.erase(name.length()-4); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 62441fd9841df8d9ea98aa7b9f7423302d0c9dfd..75aec21f93b6c50732591715620b8d8e2bef8a97 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -114,9 +114,6 @@ <color name="AlertCautionTextColor" reference="LtYellow" /> - <color - name="AgentLinkColor" - reference="EmphasisColor" /> <color name="AlertTextColor" value="0.58 0.66 0.84 1" /> @@ -348,9 +345,6 @@ <color name="GridlineShadowColor" value="0 0 0 0.31" /> - <color - name="GroupLinkColor" - reference="White" /> <color name="GroupNotifyBoxColor" value="0.3344 0.5456 0.5159 1" /> diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml index 70299c61b4e8506ecc0bc07506a46179d6be2535..593e686d4c126da89574cedc0946567e368c84ee 100644 --- a/indra/newview/skins/default/xui/da/notifications.xml +++ b/indra/newview/skins/default/xui/da/notifications.xml @@ -1636,7 +1636,7 @@ Knappen vil blive vist nÃ¥r der er nok plads til den. <notification name="ShareItemsConfirmation"> Er du sikker pÃ¥ at du vil dele følgende genstande: -[ITEMS] +<nolink>[ITEMS]</nolink> Med følgende beboere: diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 06cc02cd847a5181d9ec94da8d9bbffe6b9310b7..a2d0b5a1702394375b508705f78c376017549bfd 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2747,7 +2747,7 @@ Die Schaltfläche wird angezeigt, wenn genügend Platz vorhanden ist. <notification name="ShareItemsConfirmation"> Möchten Sie diese Objekte wirklich für andere freigeben: -[ITEMS] +<nolink>[ITEMS]</nolink> Für folgende Einwohner: diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index 2ad46824c25def60bfef10ca725e16947a4184c4..d90d0feda9ae58a1d0216db2d3cc6446ecc40498 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -1,190 +1,190 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - legacy_header_height="18" - can_resize="true" - height="440" - layout="topleft" - min_height="140" - min_width="467" - name="floater_web_content" - help_topic="floater_web_content" - save_rect="true" - auto_tile="true" - title="" - initial_mime_type="text/html" - width="820"> - <layout_stack - bottom="440" - follows="left|right|top|bottom" - layout="topleft" - left="5" - name="stack1" - orientation="vertical" - top="20" - width="810"> - <layout_panel - auto_resize="false" - default_tab_group="1" - height="22" - layout="topleft" - left="0" - min_height="20" - name="nav_controls" - top="400" - user_resize="false" - width="800"> - <button - image_overlay="Arrow_Left_Off" - image_disabled="PushButton_Disabled" - image_disabled_selected="PushButton_Disabled" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" - hover_glow_amount="0.15" - tool_tip="Navigate back" - follows="left|top" - height="22" - layout="topleft" - left="1" - name="back" - top="0" - width="22"> - <button.commit_callback - function="WebContent.Back" /> - </button> - <button - image_overlay="Arrow_Right_Off" - image_disabled="PushButton_Disabled" - image_disabled_selected="PushButton_Disabled" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" - tool_tip="Navigate forward" - follows="left|top" - height="22" - layout="topleft" - left="27" - name="forward" - top_delta="0" - width="22"> - <button.commit_callback - function="WebContent.Forward" /> - </button> - <button - image_overlay="Stop_Off" - image_disabled="PushButton_Disabled" - image_disabled_selected="PushButton_Disabled" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" - tool_tip="Stop navigation" - enabled="true" - follows="left|top" - height="22" - layout="topleft" - left="51" - name="stop" - top_delta="0" - width="22"> - <button.commit_callback - function="WebContent.Stop" /> - </button> - <button - image_overlay="Refresh_Off" - image_disabled="PushButton_Disabled" - image_disabled_selected="PushButton_Disabled" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" - tool_tip="Reload page" - follows="left|top" - height="22" - layout="topleft" - left="51" - name="reload" - top_delta="0" - width="22"> - <button.commit_callback - function="WebContent.Reload" /> - </button> - <combo_box - allow_text_entry="true" - follows="left|top|right" - tab_group="1" - height="22" - layout="topleft" - left_pad="4" - max_chars="1024" - name="address" - combo_editor.select_on_focus="true" - tool_tip="Enter URL here" - top_delta="0" - width="702"> - <combo_box.commit_callback - function="WebContent.EnterAddress" /> - </combo_box> - <icon - name="media_secure_lock_flag" - height="16" - follows="top|right" - image_name="Lock2" - layout="topleft" - left_delta="656" - top_delta="2" - visible="false" - tool_tip="Secured Browsing" - width="16" /> - <button - image_overlay="ExternalBrowser_Off" - image_disabled="PushButton_Disabled" - image_disabled_selected="PushButton_Disabled" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" - tool_tip="Open current URL in your desktop browser" - follows="right|top" - enabled="true" - height="22" - layout="topleft" - name="popexternal" - right="800" - top_delta="-2" - width="22"> - <button.commit_callback - function="WebContent.PopExternal" /> - </button> - </layout_panel> - <layout_panel - height="40" - layout="topleft" - left_delta="0" - name="external_controls" - top_delta="0" - user_resize="false" - width="540"> - <web_browser - bottom="-22" - follows="all" - layout="topleft" - left="0" - name="webbrowser" - top="0"/> - <text - type="string" - length="100" - follows="bottom|left" - height="20" - layout="topleft" - left_delta="0" - name="statusbartext" - parse_urls="false" - text_color="0.4 0.4 0.4 1" - top_pad="5" - width="452"/> - <progress_bar - color_bar="0.3 1.0 0.3 1" - follows="bottom|right" - height="16" - top_delta="-1" - left_pad="24" - layout="topleft" - name="statusbarprogress" - width="64"/> - </layout_panel> - </layout_stack> -</floater> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_resize="true" + height="440" + layout="topleft" + min_height="140" + min_width="467" + name="floater_web_content" + help_topic="floater_web_content" + save_rect="true" + auto_tile="true" + title="" + initial_mime_type="text/html" + width="820"> + <layout_stack + bottom="440" + follows="left|right|top|bottom" + layout="topleft" + left="5" + name="stack1" + orientation="vertical" + top="20" + width="810"> + <layout_panel + auto_resize="false" + default_tab_group="1" + height="22" + layout="topleft" + left="0" + min_height="20" + name="nav_controls" + top="400" + user_resize="false" + width="800"> + <button + image_overlay="Arrow_Left_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + hover_glow_amount="0.15" + tool_tip="Navigate back" + follows="left|top" + height="22" + layout="topleft" + left="1" + name="back" + top="0" + width="22"> + <button.commit_callback + function="WebContent.Back" /> + </button> + <button + image_overlay="Arrow_Right_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + tool_tip="Navigate forward" + follows="left|top" + height="22" + layout="topleft" + left="27" + name="forward" + top_delta="0" + width="22"> + <button.commit_callback + function="WebContent.Forward" /> + </button> + <button + image_overlay="Stop_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + tool_tip="Stop navigation" + enabled="true" + follows="left|top" + height="22" + layout="topleft" + left="51" + name="stop" + top_delta="0" + width="22"> + <button.commit_callback + function="WebContent.Stop" /> + </button> + <button + image_overlay="Refresh_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + tool_tip="Reload page" + follows="left|top" + height="22" + layout="topleft" + left="51" + name="reload" + top_delta="0" + width="22"> + <button.commit_callback + function="WebContent.Reload" /> + </button> + <combo_box + allow_text_entry="true" + follows="left|top|right" + tab_group="1" + height="22" + layout="topleft" + left_pad="4" + max_chars="1024" + name="address" + combo_editor.select_on_focus="true" + tool_tip="Enter URL here" + top_delta="0" + width="702"> + <combo_box.commit_callback + function="WebContent.EnterAddress" /> + </combo_box> + <icon + name="media_secure_lock_flag" + height="16" + follows="top|right" + image_name="Lock2" + layout="topleft" + left_delta="656" + top_delta="2" + visible="false" + tool_tip="Secured Browsing" + width="16" /> + <button + image_overlay="ExternalBrowser_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + tool_tip="Open current URL in your desktop browser" + follows="right|top" + enabled="true" + height="22" + layout="topleft" + name="popexternal" + right="800" + top_delta="-2" + width="22"> + <button.commit_callback + function="WebContent.PopExternal" /> + </button> + </layout_panel> + <layout_panel + height="40" + layout="topleft" + left_delta="0" + name="external_controls" + top_delta="0" + user_resize="false" + width="540"> + <web_browser + bottom="-22" + follows="all" + layout="topleft" + left="0" + name="webbrowser" + top="0"/> + <text + type="string" + length="100" + follows="bottom|left" + height="20" + layout="topleft" + left_delta="0" + name="statusbartext" + parse_urls="false" + text_color="0.4 0.4 0.4 1" + top_pad="5" + width="452"/> + <progress_bar + color_bar="0.3 1.0 0.3 1" + follows="bottom|right" + height="16" + top_delta="-1" + left_pad="24" + layout="topleft" + name="statusbarprogress" + width="64"/> + </layout_panel> + </layout_stack> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml index c751aa4e0c2caa949e8530d5cc5237750ab70ebf..719509301b0a9486393c0c5490df6ab4244b1620 100644 --- a/indra/newview/skins/default/xui/en/menu_object.xml +++ b/indra/newview/skins/default/xui/en/menu_object.xml @@ -100,7 +100,7 @@ name="Object Attach HUD" /> </context_menu> <context_menu - label="Remove" + label="Manage" name="Remove"> <menu_item_call enabled="false" @@ -129,15 +129,6 @@ <menu_item_call.on_enable function="Object.EnableReturn" /> </menu_item_call> - <menu_item_call - enabled="false" - label="Delete" - name="Delete"> - <menu_item_call.on_click - function="Object.Delete" /> - <menu_item_call.on_enable - function="Object.EnableDelete" /> - </menu_item_call> </context_menu> <menu_item_separator layout="topleft" /> <menu_item_call @@ -176,4 +167,13 @@ <menu_item_call.on_enable function="Object.EnableBuy" /> </menu_item_call> + <menu_item_call + enabled="false" + label="Delete" + name="Delete"> + <menu_item_call.on_click + function="Object.Delete" /> + <menu_item_call.on_enable + function="Object.EnableDelete" /> + </menu_item_call> </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index a6c9fab217ab0228422f01849af0f91521dce5d0..2207e418c8dff036b8e58a3823378bb4cd10abd8 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2727,6 +2727,18 @@ function="Floater.Toggle" parameter="region_debug_console" /> </menu_item_check> + <menu_item_check + label="Region Debug Console" + name="Region Debug Console" + shortcut="control|shift|`" + use_mac_ctrl="true"> + <menu_item_check.on_check + function="Floater.Visible" + parameter="region_debug_console" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="region_debug_console" /> + </menu_item_check> <menu_item_separator /> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 3df53ac442120dd9872e5c2621a531037a1ab106..6f21938bdb0fd21f9543cec2305f3cfdebce4948 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6431,7 +6431,7 @@ Select residents to share with. type="alertmodal"> Are you sure you want to share the following items: -[ITEMS] +<nolink>[ITEMS]</nolink> With the following Residents: diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml index 61d6cbb2d0e1c0d0936a5a14eb7c6ff9897706f0..eff674c628af3d10d055b2c393788ca3271d5298 100644 --- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml @@ -67,23 +67,23 @@ <scroll_list.columns label="Parcel" name="name" - width="47" /> + relative_width="0.2" /> <scroll_list.columns label="Region" name="location" - width="47" /> + relative_width="0.2" /> <scroll_list.columns label="Type" name="type" - width="47" /> + relative_width="0.2" /> <scroll_list.columns label="Area" name="area" - width="47" /> + relative_width="0.2" /> <scroll_list.columns label="Hidden" name="hidden" - width="47" /> + relative_width="0.2" /> </scroll_list> <text type="string" diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml index 85d0c633af5fb362983869118c12a711f1550fe5..2e5ebafe46bf3dd3a1c21829ecb9a578d6badcdc 100644 --- a/indra/newview/skins/default/xui/en/widgets/floater.xml +++ b/indra/newview/skins/default/xui/en/widgets/floater.xml @@ -21,4 +21,5 @@ tear_off_pressed_image="tearoff_pressed.tga" dock_pressed_image="Icon_Dock_Press" help_pressed_image="Icon_Help_Press" + focus_root="true" /> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 2dd7a6b0f549de273aa8a827b7a1342fcefa2483..14ce39e8fc673c493d4442ebe5cc79db4bf06be5 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -2734,7 +2734,7 @@ Se mostrará cuando haya suficiente espacio. <notification name="ShareItemsConfirmation"> ¿Estás seguro de que quieres compartir los elementos siguientes? -[ITEMS] +<nolink>[ITEMS]</nolink> Con los siguientes residentes: diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index ec362d7f22f73a87e66df815fe5463757c9d098e..f0b0e63af0079ca4bac7786f1bdf29268a68901b 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -2730,7 +2730,7 @@ Le bouton sera affiché quand il y aura suffisamment de place. <notification name="ShareItemsConfirmation"> Voulez-vous vraiment partager les articles suivants : -[ITEMS] +<nolink>[ITEMS]</nolink> avec les résidents suivants : diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 32483881b2b6d07aa2a5f62210bf4ab6df776145..5e53080c77b312a87c8d54e4c31e591aeebc2a8e 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -2679,7 +2679,7 @@ Il pulsante verrà visualizzato quando lo spazio sarà sufficiente. <notification name="ShareItemsConfirmation"> Sei sicuro di volere condividere gli oggetti -[ITEMS] +<nolink>[ITEMS]</nolink> Con i seguenti residenti? diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index c0af0e03ff2edfddb4ddeb85b97272b97703b3fe..f133bb361afcaf578764b04fc60c07c0f25f1cad 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -2731,7 +2731,7 @@ M ã‚ーを押ã—ã¦å¤‰æ›´ã—ã¾ã™ã€‚ <notification name="ShareItemsConfirmation"> 次ã®ã‚¢ã‚¤ãƒ†ãƒ を共有ã—ã¾ã™ã‹ï¼š -[ITEMS] +<nolink>[ITEMS]</nolink> 次ã®ä½äººã¨å…±æœ‰ã—ã¾ã™ã‹ï¼š diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index 8151c7eb938304846d51f890b8b1d769879b4d9f..57a6b8b8ef9e6cfd258dff586746536f8c7d276c 100644 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -2691,7 +2691,7 @@ Przycisk zostanie wyÅ›wietlony w przypadku dostatecznej iloÅ›ci przestrzeni. <notification name="ShareItemsConfirmation"> JesteÅ› pewien/pewna, że chcesz udostÄ™pnić nastÄ™pujÄ…ce obiekty: -[ITEMS] +<nolink>[ITEMS]</nolink> nastÄ™pujÄ…cym Rezydentom: diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index dc38b740aaf54053ecb2bc2e575919a6937a26f0..a1855f2e892ce26b66be0a7b38aa19bf41fd6153 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -477,7 +477,7 @@ Para aumentar a qualidade do vÃdeo, vá para Preferências > VÃdeo. </notification> <notification name="CannotCopyWarning"> Você não tem autorização para copiar os itens abaixo: -[ITENS] +[ITEMS] ao dá-los, você ficará sem eles no seu inventário. Deseja realmente dar estes itens? <usetemplate name="okcancelbuttons" notext="Não" yestext="Sim"/> </notification> @@ -2714,7 +2714,7 @@ O botão será exibido quando houver espaço suficente. <notification name="ShareItemsConfirmation"> Tem certeza de que quer compartilhar os items abaixo? -[ITENS] +<nolink>[ITEMS]</nolink> Com os seguintes residentes: diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index a6c1f69c82a4784958da65c248613f320117ae61..7862cce3a1de667ec909a8f26751c9f55a64dd36 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -1,134 +1,136 @@ -/** - * @file llremoteparcelrequest_test.cpp - * @author Brad Kittenbrink <brad@lindenlab.com> - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "../test/lltut.h" - -#include "../llremoteparcelrequest.h" - -#include "../llagent.h" -#include "message.h" - -namespace { - LLControlGroup s_saved_settings("dummy_settings"); - const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111"); -} - -LLCurl::Responder::Responder() { } -LLCurl::Responder::~Responder() { } -void LLCurl::Responder::error(U32,std::string const &) { } -void LLCurl::Responder::result(LLSD const &) { } -void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { } -void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { } -void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { } -void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { } -void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { } -void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { } -void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { } -void LLMessageSystem::getString(char const *,char const *, std::string &,S32) { } -void LLMessageSystem::getUUID(char const *,char const *, LLUUID & out_id,S32) -{ - out_id = TEST_PARCEL_ID; -} -void LLMessageSystem::nextBlock(char const *) { } -void LLMessageSystem::addUUID(char const *,LLUUID const &) { } -void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { } -void LLMessageSystem::nextBlockFast(char const *) { } -void LLMessageSystem::newMessage(char const *) { } -LLMessageSystem * gMessageSystem; -char * _PREHASH_AgentID; -char * _PREHASH_AgentData; -LLAgent gAgent; -LLAgent::LLAgent() : mAgentAccess(s_saved_settings) { } -LLAgent::~LLAgent() { } -void LLAgent::sendReliableMessage(void) { } -LLUUID gAgentSessionID; -LLUUID gAgentID; -LLUIColor::LLUIColor(void) { } -LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { } -LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { } -LLControlGroup::~LLControlGroup(void) { } - -namespace tut -{ - struct TestObserver : public LLRemoteParcelInfoObserver { - TestObserver() : mProcessed(false) { } - - virtual void processParcelInfo(const LLParcelData& parcel_data) - { - mProcessed = true; - } - - virtual void setParcelID(const LLUUID& parcel_id) { } - - virtual void setErrorStatus(U32 status, const std::string& reason) { } - - bool mProcessed; - }; - - struct RemoteParcelRequestData - { - RemoteParcelRequestData() - { - } - }; - - typedef test_group<RemoteParcelRequestData> remoteparcelrequest_t; - typedef remoteparcelrequest_t::object remoteparcelrequest_object_t; - tut::remoteparcelrequest_t tut_remoteparcelrequest("LLRemoteParcelRequest"); - - template<> template<> - void remoteparcelrequest_object_t::test<1>() - { - set_test_name("observer pointer"); - - boost::scoped_ptr<TestObserver> observer(new TestObserver()); - - LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance(); - processor.addObserver(LLUUID(TEST_PARCEL_ID), observer.get()); - - processor.processParcelInfoReply(gMessageSystem, NULL); - - ensure(observer->mProcessed); - } - - template<> template<> - void remoteparcelrequest_object_t::test<2>() - { - set_test_name("CHOP-220: dangling observer pointer"); - - LLRemoteParcelInfoObserver * observer = new TestObserver(); - - LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance(); - processor.addObserver(LLUUID(TEST_PARCEL_ID), observer); - - delete observer; - observer = NULL; - - processor.processParcelInfoReply(gMessageSystem, NULL); - } -} +/** + * @file llremoteparcelrequest_test.cpp + * @author Brad Kittenbrink <brad@lindenlab.com> + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "../test/lltut.h" + +#include "../llremoteparcelrequest.h" + +#include "../llagent.h" +#include "message.h" +#include "llurlentry.h" + +namespace { + LLControlGroup s_saved_settings("dummy_settings"); + const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111"); +} + +LLCurl::Responder::Responder() { } +LLCurl::Responder::~Responder() { } +void LLCurl::Responder::error(U32,std::string const &) { } +void LLCurl::Responder::result(LLSD const &) { } +void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { } +void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { } +void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { } +void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { } +void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { } +void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { } +void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { } +void LLMessageSystem::getString(char const *,char const *, std::string &,S32) { } +void LLMessageSystem::getUUID(char const *,char const *, LLUUID & out_id,S32) +{ + out_id = TEST_PARCEL_ID; +} +void LLMessageSystem::nextBlock(char const *) { } +void LLMessageSystem::addUUID(char const *,LLUUID const &) { } +void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { } +void LLMessageSystem::nextBlockFast(char const *) { } +void LLMessageSystem::newMessage(char const *) { } +LLMessageSystem * gMessageSystem; +char * _PREHASH_AgentID; +char * _PREHASH_AgentData; +LLAgent gAgent; +LLAgent::LLAgent() : mAgentAccess(s_saved_settings) { } +LLAgent::~LLAgent() { } +void LLAgent::sendReliableMessage(void) { } +LLUUID gAgentSessionID; +LLUUID gAgentID; +LLUIColor::LLUIColor(void) { } +LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { } +LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { } +LLControlGroup::~LLControlGroup(void) { } +void LLUrlEntryParcel::processParcelInfo(const LLUrlEntryParcel::LLParcelData& parcel_data) { } + +namespace tut +{ + struct TestObserver : public LLRemoteParcelInfoObserver { + TestObserver() : mProcessed(false) { } + + virtual void processParcelInfo(const LLParcelData& parcel_data) + { + mProcessed = true; + } + + virtual void setParcelID(const LLUUID& parcel_id) { } + + virtual void setErrorStatus(U32 status, const std::string& reason) { } + + bool mProcessed; + }; + + struct RemoteParcelRequestData + { + RemoteParcelRequestData() + { + } + }; + + typedef test_group<RemoteParcelRequestData> remoteparcelrequest_t; + typedef remoteparcelrequest_t::object remoteparcelrequest_object_t; + tut::remoteparcelrequest_t tut_remoteparcelrequest("LLRemoteParcelRequest"); + + template<> template<> + void remoteparcelrequest_object_t::test<1>() + { + set_test_name("observer pointer"); + + boost::scoped_ptr<TestObserver> observer(new TestObserver()); + + LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance(); + processor.addObserver(LLUUID(TEST_PARCEL_ID), observer.get()); + + processor.processParcelInfoReply(gMessageSystem, NULL); + + ensure(observer->mProcessed); + } + + template<> template<> + void remoteparcelrequest_object_t::test<2>() + { + set_test_name("CHOP-220: dangling observer pointer"); + + LLRemoteParcelInfoObserver * observer = new TestObserver(); + + LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance(); + processor.addObserver(LLUUID(TEST_PARCEL_ID), observer); + + delete observer; + observer = NULL; + + processor.processParcelInfoReply(gMessageSystem, NULL); + } +} diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 5f8cd28f2976501f23f6eef2360ce4c228f6d215..e19d5724f172b5bdc552d2243007611b285076e6 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -1,200 +1,194 @@ -/** - * @file llupdaterservice_test.cpp - * @brief Tests of llupdaterservice.cpp. - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -// Precompiled header -#include "linden_common.h" -// associated header -#include "../llupdaterservice.h" -#include "../llupdatechecker.h" -#include "../llupdatedownloader.h" -#include "../llupdateinstaller.h" - -#include "../../../test/lltut.h" -//#define DEBUG_ON -#include "../../../test/debug.h" - -#include "llevents.h" -#include "lldir.h" - -/***************************************************************************** -* MOCK'd -*****************************************************************************/ -LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client) -{} -void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version) -{} -LLUpdateDownloader::LLUpdateDownloader(Client & ) {} -void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){} - -class LLDir_Mock : public LLDir -{ - void initAppDirs(const std::string &app_name, - const std::string& app_read_only_data_dir = "") {} - U32 countFilesInDir(const std::string &dirname, const std::string &mask) - { - return 0; - } - - BOOL getNextFileInDir(const std::string &dirname, - const std::string &mask, - std::string &fname) - { - return false; - } - void getRandomFileInDir(const std::string &dirname, - const std::string &mask, - std::string &fname) {} - std::string getCurPath() { return ""; } - BOOL fileExists(const std::string &filename) const { return false; } - std::string getLLPluginLauncher() { return ""; } - std::string getLLPluginFilename(std::string base_name) { return ""; } - -} gDirUtil; -LLDir* gDirUtilp = &gDirUtil; -LLDir::LLDir() {} -LLDir::~LLDir() {} -S32 LLDir::deleteFilesInDir(const std::string &dirname, - const std::string &mask) -{ return 0; } - -void LLDir::setChatLogsDir(const std::string &path){} -void LLDir::setPerAccountChatLogsDir(const std::string &username){} -void LLDir::setLindenUserDir(const std::string &username){} -void LLDir::setSkinFolder(const std::string &skin_folder){} -bool LLDir::setCacheDir(const std::string &path){ return true; } -void LLDir::dumpCurrentDirectories() {} - -std::string LLDir::getExpandedFilename(ELLPath location, - const std::string &filename) const -{ - return ""; -} - -std::string LLUpdateDownloader::downloadMarkerPath(void) -{ - return ""; -} - -void LLUpdateDownloader::resume(void) {} -void LLUpdateDownloader::cancel(void) {} -void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) {} - -int ll_install_update(std::string const &, std::string const &, bool, LLInstallScriptMode) -{ - return 0; -} - -std::string const & ll_install_failed_marker_path() -{ - static std::string wubba; - return wubba; -} - -/* -#pragma warning(disable: 4273) -llus_mock_llifstream::llus_mock_llifstream(const std::string& _Filename, - ios_base::openmode _Mode, - int _Prot) : - std::basic_istream<char,std::char_traits< char > >(NULL,true) -{} - -llus_mock_llifstream::~llus_mock_llifstream() {} -bool llus_mock_llifstream::is_open() const {return true;} -void llus_mock_llifstream::close() {} -*/ - -/***************************************************************************** -* TUT -*****************************************************************************/ -namespace tut -{ - struct llupdaterservice_data - { - llupdaterservice_data() : - pumps(LLEventPumps::instance()), - test_url("dummy_url"), - test_channel("dummy_channel"), - test_version("dummy_version") - {} - LLEventPumps& pumps; - std::string test_url; - std::string test_channel; - std::string test_version; - }; - - typedef test_group<llupdaterservice_data> llupdaterservice_group; - typedef llupdaterservice_group::object llupdaterservice_object; - llupdaterservice_group llupdaterservicegrp("LLUpdaterService"); - - template<> template<> - void llupdaterservice_object::test<1>() - { - DEBUG; - LLUpdaterService updater; - bool got_usage_error = false; - try - { - updater.startChecking(); - } - catch(LLUpdaterService::UsageError) - { - got_usage_error = true; - } - ensure("Caught start before params", got_usage_error); - } - - template<> template<> - void llupdaterservice_object::test<2>() - { - DEBUG; - LLUpdaterService updater; - bool got_usage_error = false; - try - { - updater.initialize("1.0",test_url, "update" ,test_channel, test_version); - updater.startChecking(); - updater.initialize("1.0", "other_url", "update", test_channel, test_version); - } - catch(LLUpdaterService::UsageError) - { - got_usage_error = true; - } - ensure("Caught params while running", got_usage_error); - } - - template<> template<> - void llupdaterservice_object::test<3>() - { - DEBUG; - LLUpdaterService updater; - updater.initialize("1.0", test_url, "update", test_channel, test_version); - updater.startChecking(); - ensure(updater.isChecking()); - updater.stopChecking(); - ensure(!updater.isChecking()); - } -} +/** + * @file llupdaterservice_test.cpp + * @brief Tests of llupdaterservice.cpp. + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "../llupdaterservice.h" +#include "../llupdatechecker.h" +#include "../llupdatedownloader.h" +#include "../llupdateinstaller.h" + +#include "../../../test/lltut.h" +//#define DEBUG_ON +#include "../../../test/debug.h" + +#include "llevents.h" +#include "lldir.h" + +/***************************************************************************** +* MOCK'd +*****************************************************************************/ +LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client) +{} +void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl, + std::string const & servicePath, std::string channel, std::string version) +{} +LLUpdateDownloader::LLUpdateDownloader(Client & ) {} +void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){} + +class LLDir_Mock : public LLDir +{ + void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir = "") {} + U32 countFilesInDir(const std::string &dirname, const std::string &mask) + { + return 0; + } + + void getRandomFileInDir(const std::string &dirname, + const std::string &mask, + std::string &fname) {} + std::string getCurPath() { return ""; } + BOOL fileExists(const std::string &filename) const { return false; } + std::string getLLPluginLauncher() { return ""; } + std::string getLLPluginFilename(std::string base_name) { return ""; } + +} gDirUtil; +LLDir* gDirUtilp = &gDirUtil; +LLDir::LLDir() {} +LLDir::~LLDir() {} +S32 LLDir::deleteFilesInDir(const std::string &dirname, + const std::string &mask) +{ return 0; } + +void LLDir::setChatLogsDir(const std::string &path){} +void LLDir::setPerAccountChatLogsDir(const std::string &username){} +void LLDir::setLindenUserDir(const std::string &username){} +void LLDir::setSkinFolder(const std::string &skin_folder){} +bool LLDir::setCacheDir(const std::string &path){ return true; } +void LLDir::dumpCurrentDirectories() {} + +std::string LLDir::getExpandedFilename(ELLPath location, + const std::string &filename) const +{ + return ""; +} + +std::string LLUpdateDownloader::downloadMarkerPath(void) +{ + return ""; +} + +void LLUpdateDownloader::resume(void) {} +void LLUpdateDownloader::cancel(void) {} +void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) {} + +int ll_install_update(std::string const &, std::string const &, bool, LLInstallScriptMode) +{ + return 0; +} + +std::string const & ll_install_failed_marker_path() +{ + static std::string wubba; + return wubba; +} + +/* +#pragma warning(disable: 4273) +llus_mock_llifstream::llus_mock_llifstream(const std::string& _Filename, + ios_base::openmode _Mode, + int _Prot) : + std::basic_istream<char,std::char_traits< char > >(NULL,true) +{} + +llus_mock_llifstream::~llus_mock_llifstream() {} +bool llus_mock_llifstream::is_open() const {return true;} +void llus_mock_llifstream::close() {} +*/ + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llupdaterservice_data + { + llupdaterservice_data() : + pumps(LLEventPumps::instance()), + test_url("dummy_url"), + test_channel("dummy_channel"), + test_version("dummy_version") + {} + LLEventPumps& pumps; + std::string test_url; + std::string test_channel; + std::string test_version; + }; + + typedef test_group<llupdaterservice_data> llupdaterservice_group; + typedef llupdaterservice_group::object llupdaterservice_object; + llupdaterservice_group llupdaterservicegrp("LLUpdaterService"); + + template<> template<> + void llupdaterservice_object::test<1>() + { + DEBUG; + LLUpdaterService updater; + bool got_usage_error = false; + try + { + updater.startChecking(); + } + catch(LLUpdaterService::UsageError) + { + got_usage_error = true; + } + ensure("Caught start before params", got_usage_error); + } + + template<> template<> + void llupdaterservice_object::test<2>() + { + DEBUG; + LLUpdaterService updater; + bool got_usage_error = false; + try + { + updater.initialize("1.0",test_url, "update" ,test_channel, test_version); + updater.startChecking(); + updater.initialize("1.0", "other_url", "update", test_channel, test_version); + } + catch(LLUpdaterService::UsageError) + { + got_usage_error = true; + } + ensure("Caught params while running", got_usage_error); + } + + template<> template<> + void llupdaterservice_object::test<3>() + { + DEBUG; + LLUpdaterService updater; + updater.initialize("1.0", test_url, "update", test_channel, test_version); + updater.startChecking(); + ensure(updater.isChecking()); + updater.stopChecking(); + ensure(!updater.isChecking()); + } +}