summaryrefslogtreecommitdiff
path: root/indra/llvfs
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llvfs')
-rw-r--r--indra/llvfs/CMakeLists.txt6
-rw-r--r--indra/llvfs/lldir.cpp218
-rw-r--r--indra/llvfs/lldir.h35
-rw-r--r--indra/llvfs/lldir_linux.cpp2
-rw-r--r--indra/llvfs/lldir_linux.h2
-rw-r--r--indra/llvfs/lldir_mac.cpp239
-rw-r--r--indra/llvfs/lldir_mac.h10
-rw-r--r--indra/llvfs/lldir_solaris.cpp2
-rw-r--r--indra/llvfs/lldir_solaris.h2
-rw-r--r--indra/llvfs/lldir_win32.cpp2
-rw-r--r--indra/llvfs/lldir_win32.h2
-rw-r--r--indra/llvfs/lldiriterator.cpp7
-rw-r--r--indra/llvfs/llvfs_objc.h43
-rw-r--r--indra/llvfs/llvfs_objc.mm108
-rw-r--r--indra/llvfs/tests/lldir_test.cpp89
15 files changed, 438 insertions, 329 deletions
diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
index a819d12861..3c68b279f7 100644
--- a/indra/llvfs/CMakeLists.txt
+++ b/indra/llvfs/CMakeLists.txt
@@ -36,6 +36,8 @@ set(llvfs_HEADER_FILES
if (DARWIN)
LIST(APPEND llvfs_SOURCE_FILES lldir_mac.cpp)
LIST(APPEND llvfs_HEADER_FILES lldir_mac.h)
+ LIST(APPEND llvfs_SOURCE_FILES llvfs_objc.mm)
+ LIST(APPEND llvfs_HEADER_FILES llvfs_objc.h)
endif (DARWIN)
if (LINUX)
@@ -73,8 +75,8 @@ target_link_libraries(llvfs
if (DARWIN)
include(CMakeFindFrameworks)
- find_library(CARBON_LIBRARY Carbon)
- target_link_libraries(llvfs ${CARBON_LIBRARY})
+ find_library(COCOA_LIBRARY Cocoa)
+ target_link_libraries(llvfs ${COCOA_LIBRARY})
endif (DARWIN)
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index a7d12476a4..5e5aeefba1 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -45,8 +45,13 @@
#include <boost/foreach.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/bind.hpp>
+#include <boost/ref.hpp>
#include <algorithm>
-#include <iomanip>
+
+using boost::assign::list_of;
+using boost::assign::map_list_of;
#if LL_WINDOWS
#include "lldir_win32.h"
@@ -343,37 +348,35 @@ const std::string &LLDir::getLLPluginDir() const
static std::string ELLPathToString(ELLPath location)
{
- typedef std::map<ELLPath, const char*> ELLPathMap;
-#define ENT(symbol) ELLPathMap::value_type(symbol, #symbol)
- static ELLPathMap::value_type init[] =
- {
- ENT(LL_PATH_NONE),
- ENT(LL_PATH_USER_SETTINGS),
- ENT(LL_PATH_APP_SETTINGS),
- ENT(LL_PATH_PER_SL_ACCOUNT), // returns/expands to blank string if we don't know the account name yet
- ENT(LL_PATH_CACHE),
- ENT(LL_PATH_CHARACTER),
- ENT(LL_PATH_HELP),
- ENT(LL_PATH_LOGS),
- ENT(LL_PATH_TEMP),
- ENT(LL_PATH_SKINS),
- ENT(LL_PATH_TOP_SKIN),
- ENT(LL_PATH_CHAT_LOGS),
- ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS),
- ENT(LL_PATH_USER_SKIN),
- ENT(LL_PATH_LOCAL_ASSETS),
- ENT(LL_PATH_EXECUTABLE),
- ENT(LL_PATH_DEFAULT_SKIN),
- ENT(LL_PATH_FONTS),
- ENT(LL_PATH_LAST)
- };
+ typedef std::map<ELLPath, const char*> ELLPathMap;
+#define ENT(symbol) (symbol, #symbol)
+ static const ELLPathMap sMap = map_list_of
+ ENT(LL_PATH_NONE)
+ ENT(LL_PATH_USER_SETTINGS)
+ ENT(LL_PATH_APP_SETTINGS)
+ ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet
+ ENT(LL_PATH_CACHE)
+ ENT(LL_PATH_CHARACTER)
+ ENT(LL_PATH_HELP)
+ ENT(LL_PATH_LOGS)
+ ENT(LL_PATH_TEMP)
+ ENT(LL_PATH_SKINS)
+ ENT(LL_PATH_TOP_SKIN)
+ ENT(LL_PATH_CHAT_LOGS)
+ ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS)
+ ENT(LL_PATH_USER_SKIN)
+ ENT(LL_PATH_LOCAL_ASSETS)
+ ENT(LL_PATH_EXECUTABLE)
+ ENT(LL_PATH_DEFAULT_SKIN)
+ ENT(LL_PATH_FONTS)
+ ENT(LL_PATH_LAST)
+ ;
#undef ENT
- static const ELLPathMap sMap(boost::begin(init), boost::end(init));
- ELLPathMap::const_iterator found = sMap.find(location);
- if (found != sMap.end())
- return found->second;
- return STRINGIZE("Invalid ELLPath value " << location);
+ ELLPathMap::const_iterator found = sMap.find(location);
+ if (found != sMap.end())
+ return found->second;
+ return STRINGIZE("Invalid ELLPath value " << location);
}
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const
@@ -544,10 +547,10 @@ std::string LLDir::getExtension(const std::string& filepath) const
std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir,
const std::string &filename,
- bool merge) const
+ ESkinConstraint constraint) const
{
// This implementation is basically just as described in the declaration comments.
- std::vector<std::string> found(findSkinnedFilenames(subdir, filename, merge));
+ std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint));
if (found.empty())
{
return "";
@@ -557,10 +560,10 @@ std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir,
std::string LLDir::findSkinnedFilename(const std::string &subdir,
const std::string &filename,
- bool merge) const
+ ESkinConstraint constraint) const
{
// This implementation is basically just as described in the declaration comments.
- std::vector<std::string> found(findSkinnedFilenames(subdir, filename, merge));
+ std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint));
if (found.empty())
{
return "";
@@ -568,30 +571,65 @@ std::string LLDir::findSkinnedFilename(const std::string &subdir,
return found.back();
}
+// This method exists because the two code paths for
+// findSkinnedFilenames(ALL_SKINS) and findSkinnedFilenames(CURRENT_SKIN) must
+// generate the list of candidate pathnames in identical ways. The only
+// difference is in the body of the inner loop.
+template <typename FUNCTION>
+void LLDir::walkSearchSkinDirs(const std::string& subdir,
+ const std::vector<std::string>& subsubdirs,
+ const std::string& filename,
+ const FUNCTION& function) const
+{
+ BOOST_FOREACH(std::string skindir, mSearchSkinDirs)
+ {
+ std::string subdir_path(add(skindir, subdir));
+ BOOST_FOREACH(std::string subsubdir, subsubdirs)
+ {
+ std::string full_path(add(add(subdir_path, subsubdir), filename));
+ if (fileExists(full_path))
+ {
+ function(subsubdir, full_path);
+ }
+ }
+ }
+}
+
+// ridiculous little helper function that should go away when we can use lambda
+inline void push_back(std::vector<std::string>& vector, const std::string& value)
+{
+ vector.push_back(value);
+}
+
+typedef std::map<std::string, std::string> StringMap;
+// ridiculous little helper function that should go away when we can use lambda
+inline void store_in_map(StringMap& map, const std::string& key, const std::string& value)
+{
+ map[key] = value;
+}
+
std::vector<std::string> LLDir::findSkinnedFilenames(const std::string& subdir,
const std::string& filename,
- bool merge) const
+ ESkinConstraint constraint) const
{
// Recognize subdirs that have no localization.
- static const char* sUnlocalizedData[] =
- {
- "", // top-level directory not localized
- "textures" // textures not localized
- };
- static const std::set<std::string> sUnlocalized(boost::begin(sUnlocalizedData),
- boost::end(sUnlocalizedData));
+ static const std::set<std::string> sUnlocalized = list_of
+ ("") // top-level directory not localized
+ ("textures") // textures not localized
+ ;
LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename
- << "', merge " << std::boolalpha << merge << LL_ENDL;
+ << "', constraint "
+ << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS")
+ << LL_ENDL;
// Cache the default language directory for each subdir we've encountered.
// A cache entry whose value is the empty string means "not localized,
// don't bother checking again."
- typedef std::map<std::string, std::string> LocalizedMap;
- static LocalizedMap sLocalized;
+ static StringMap sLocalized;
// Check whether we've already discovered if this subdir is localized.
- LocalizedMap::const_iterator found = sLocalized.find(subdir);
+ StringMap::const_iterator found = sLocalized.find(subdir);
if (found == sLocalized.end())
{
// We have not yet determined that. Is it one of the subdirs "known"
@@ -599,7 +637,7 @@ std::vector<std::string> LLDir::findSkinnedFilenames(const std::string& subdir,
if (sUnlocalized.find(subdir) != sUnlocalized.end())
{
// This subdir is known to be unlocalized. Remember that.
- found = sLocalized.insert(LocalizedMap::value_type(subdir, "")).first;
+ found = sLocalized.insert(StringMap::value_type(subdir, "")).first;
}
else
{
@@ -608,20 +646,20 @@ std::vector<std::string> LLDir::findSkinnedFilenames(const std::string& subdir,
if (fileExists(add(subdir_path, "en")))
{
// defaultSkinDir/subdir contains subdir "en". That's our
- // default language; this subdir is localized.
- found = sLocalized.insert(LocalizedMap::value_type(subdir, "en")).first;
+ // default language; this subdir is localized.
+ found = sLocalized.insert(StringMap::value_type(subdir, "en")).first;
}
else if (fileExists(add(subdir_path, "en-us")))
{
// defaultSkinDir/subdir contains subdir "en-us" but not "en".
// Set as default language; this subdir is localized.
- found = sLocalized.insert(LocalizedMap::value_type(subdir, "en-us")).first;
+ found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first;
}
else
{
// defaultSkinDir/subdir contains neither "en" nor "en-us".
// Assume it's not localized. Remember that assumption.
- found = sLocalized.insert(LocalizedMap::value_type(subdir, "")).first;
+ found = sLocalized.insert(StringMap::value_type(subdir, "")).first;
}
}
}
@@ -648,48 +686,52 @@ std::vector<std::string> LLDir::findSkinnedFilenames(const std::string& subdir,
subsubdirs.push_back(mLanguage);
}
}
- // Code below relies on subsubdirs not being empty: more specifically, on
- // front() being valid. There may or may not be additional entries, but we
- // have at least one. For an unlocalized subdir, it's the only one; for a
- // localized subdir, it's the default one.
- llassert(! subsubdirs.empty());
// Build results vector.
std::vector<std::string> results;
- BOOST_FOREACH(std::string skindir, mSearchSkinDirs)
- {
- std::string subdir_path(add(skindir, subdir));
- // Does subdir_path/subsubdirs[0]/filename exist? If there's more than
- // one entry in subsubdirs, the first is the default language ("en"),
- // the second is the current language. A skin that contains
- // subdir/language/filename without also containing subdir/en/filename
- // is ill-formed: skip any such skin. So to decide whether to keep
- // this skin dir or skip it, we need only check for the existence of
- // the first subsubdir entry ("en" or only).
- std::string subsubdir_path(add(add(subdir_path, subsubdirs.front()), filename));
- if (! fileExists(subsubdir_path))
- continue;
-
- // Here the desired filename exists in the first subsubdir. That means
- // this is a skindir we want to record in results. But if the caller
- // passed merge=false, we must discard all previous skindirs.
- if (! merge)
- {
- results.clear();
- }
-
- // Now add every subsubdir in which filename exists. We already know
- // it exists in the first one.
- results.push_back(subsubdir_path);
-
- // Append all remaining subsubdirs in which filename exists.
- for (std::vector<std::string>::const_iterator ssdi(subsubdirs.begin() + 1), ssdend(subsubdirs.end());
- ssdi != ssdend; ++ssdi)
+ // The process we use depends on 'constraint'.
+ if (constraint != CURRENT_SKIN) // meaning ALL_SKINS
+ {
+ // ALL_SKINS is simpler: just return every pathname generated by
+ // walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its
+ // FUNCTION the subsubdir as well as the full pathname. We just want
+ // the full pathname.
+ walkSearchSkinDirs(subdir, subsubdirs, filename,
+ boost::bind(push_back, boost::ref(results), _2));
+ }
+ else // CURRENT_SKIN
+ {
+ // CURRENT_SKIN turns out to be a bit of a misnomer because we might
+ // still return files from two different skins. In any case, this
+ // value of 'constraint' means we will return at most two paths: one
+ // for the default language, one for the current language (supposing
+ // those differ).
+ // It is important to allow a user to override only the localization
+ // for a particular file, for all viewer installs, without also
+ // overriding the default-language file.
+ // It is important to allow a user to override only the default-
+ // language file, for all viewer installs, without also overriding the
+ // applicable localization of that file.
+ // Therefore, treat the default language and the current language as
+ // two separate cases. For each, capture the most-specialized file
+ // that exists.
+ // Use a map keyed by subsubdir (i.e. language code). This allows us
+ // to handle the case of a single subsubdirs entry with the same logic
+ // that handles two. For every real file path generated by
+ // walkSearchSkinDirs(), update the map entry for its subsubdir.
+ StringMap path_for;
+ walkSearchSkinDirs(subdir, subsubdirs, filename,
+ boost::bind(store_in_map, boost::ref(path_for), _1, _2));
+ // Now that we have a path for each of the default language and the
+ // current language, copy them -- in proper order -- into results.
+ // Don't drive this by walking the map itself: it matters that we
+ // generate results in the same order as subsubdirs.
+ BOOST_FOREACH(std::string subsubdir, subsubdirs)
{
- subsubdir_path = add(add(subdir_path, *ssdi), filename);
- if (fileExists(subsubdir_path))
+ StringMap::const_iterator found(path_for.find(subsubdir));
+ if (found != path_for.end())
{
- results.push_back(subsubdir_path);
+ results.push_back(found->second);
}
}
}
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index a242802979..300ff1eef6 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lldir.h
* @brief Definition of directory utilities class
*
@@ -73,10 +73,8 @@ class LLDir
virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
// pure virtual functions
- virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0;
-
virtual std::string getCurPath() = 0;
- virtual BOOL fileExists(const std::string &filename) const = 0;
+ virtual bool fileExists(const std::string &filename) const = 0;
const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const;
const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const;
@@ -119,6 +117,8 @@ class LLDir
// these methods search the various skin paths for the specified file in the following order:
// getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir()
+ /// param value for findSkinnedFilenames(), explained below
+ enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS };
/**
* Given a filename within skin, return an ordered sequence of paths to
* search. Nonexistent files will be filtered out -- which means that the
@@ -130,25 +130,25 @@ class LLDir
* level of skin subdirectory).
* @param filename Desired filename within subdir within skin, e.g.
* "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language.
- * @param merge Callers perform two different kinds of processing. When
- * fetching a XUI file, for instance, the existence of @a filename in the
- * specified skin completely supercedes any @a filename in the default
- * skin. For that case, leave the default @a merge=false. The returned
- * vector will contain only
+ * @param constraint Callers perform two different kinds of processing.
+ * When fetching a XUI file, for instance, the existence of @a filename in
+ * the specified skin completely supercedes any @a filename in the default
+ * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The
+ * returned vector will contain only
* ".../<i>current_skin</i>/xui/en/<i>filename</i>",
* ".../<i>current_skin</i>/xui/<i>current_language</i>/<i>filename</i>".
* But for (e.g.) "strings.xml", we want a given skin to be able to
* override only specific entries from the default skin. Any string not
* defined in the specified skin will be sought in the default skin. For
- * that case, pass @a merge=true. The returned vector will contain at
- * least ".../default/xui/en/strings.xml",
+ * that case, pass @a constraint=ALL_SKINS. The returned vector will
+ * contain at least ".../default/xui/en/strings.xml",
* ".../default/xui/<i>current_language</i>/strings.xml",
* ".../<i>current_skin</i>/xui/en/strings.xml",
* ".../<i>current_skin</i>/xui/<i>current_language</i>/strings.xml".
*/
std::vector<std::string> findSkinnedFilenames(const std::string& subdir,
const std::string& filename,
- bool merge=false) const;
+ ESkinConstraint constraint=CURRENT_SKIN) const;
/// Values for findSkinnedFilenames(subdir) parameter
static const char *XUI, *TEXTURES, *SKINBASE;
/**
@@ -160,7 +160,7 @@ class LLDir
*/
std::string findSkinnedFilenameBaseLang(const std::string &subdir,
const std::string &filename,
- bool merge=false) const;
+ ESkinConstraint constraint=CURRENT_SKIN) const;
/**
* Return the "most localized" pathname from findSkinnedFilenames(), or
* the empty string if no such file exists. Parameters are identical to
@@ -170,7 +170,7 @@ class LLDir
*/
std::string findSkinnedFilename(const std::string &subdir,
const std::string &filename,
- bool merge=false) const;
+ ESkinConstraint constraint=CURRENT_SKIN) const;
// random filename in common temporary directory
std::string getTempFilename() const;
@@ -206,6 +206,13 @@ protected:
// build mSearchSkinDirs without adding duplicates
void addSearchSkinDir(const std::string& skindir);
+ // Internal to findSkinnedFilenames()
+ template <typename FUNCTION>
+ void walkSearchSkinDirs(const std::string& subdir,
+ const std::vector<std::string>& subsubdirs,
+ const std::string& filename,
+ const FUNCTION& function) const;
+
std::string mAppName; // install directory under progams/ ie "SecondLife"
std::string mExecutablePathAndName; // full path + Filename of .exe
std::string mExecutableFilename; // Filename of .exe
diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp
index 407f3b93fb..4edd078640 100644
--- a/indra/llvfs/lldir_linux.cpp
+++ b/indra/llvfs/lldir_linux.cpp
@@ -254,7 +254,7 @@ std::string LLDir_Linux::getCurPath()
}
-BOOL LLDir_Linux::fileExists(const std::string &filename) const
+bool LLDir_Linux::fileExists(const std::string &filename) const
{
struct stat stat_data;
// Check the age of the file
diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h
index 7603239867..e83a020ba4 100644
--- a/indra/llvfs/lldir_linux.h
+++ b/indra/llvfs/lldir_linux.h
@@ -47,7 +47,7 @@ public:
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
- /*virtual*/ BOOL fileExists(const std::string &filename) const;
+ /*virtual*/ bool fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index 489bc3e4a7..c5041d434c 100644
--- a/indra/llvfs/lldir_mac.cpp
+++ b/indra/llvfs/lldir_mac.cpp
@@ -22,7 +22,7 @@
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
- */
+ */
#if LL_DARWIN
@@ -35,73 +35,27 @@
#include <sys/stat.h>
#include <unistd.h>
#include <glob.h>
-
-#include <Carbon/Carbon.h>
-
-// --------------------------------------------------------------------------------
-
-static OSStatus CFCreateDirectory(FSRef *parentRef, CFStringRef name, FSRef *newRef)
-{
- OSStatus result = noErr;
- HFSUniStr255 uniStr;
-
- uniStr.length = CFStringGetLength(name);
- CFStringGetCharacters(name, CFRangeMake(0, uniStr.length), uniStr.unicode);
- result = FSMakeFSRefUnicode(parentRef, uniStr.length, uniStr.unicode, kTextEncodingMacRoman, newRef);
- if (result != noErr)
- {
- result = FSCreateDirectoryUnicode(parentRef, uniStr.length, uniStr.unicode, 0, NULL, newRef, NULL, NULL);
- }
-
- return result;
-}
+#include <boost/filesystem.hpp>
+#include "llvfs_objc.h"
// --------------------------------------------------------------------------------
-static void CFStringRefToLLString(CFStringRef stringRef, std::string &llString, bool releaseWhenDone)
+static bool CreateDirectory(const std::string &parent,
+ const std::string &child,
+ std::string *fullname)
{
- if (stringRef)
- {
- long stringSize = CFStringGetLength(stringRef) + 1;
- long bufferSize = CFStringGetMaximumSizeForEncoding(stringSize,kCFStringEncodingUTF8);
- char* buffer = new char[bufferSize];
- memset(buffer, 0, bufferSize);
- if (CFStringGetCString(stringRef, buffer, bufferSize, kCFStringEncodingUTF8))
- llString = buffer;
- delete[] buffer;
- if (releaseWhenDone)
- CFRelease(stringRef);
- }
-}
-
-// --------------------------------------------------------------------------------
-
-static void CFURLRefToLLString(CFURLRef urlRef, std::string &llString, bool releaseWhenDone)
-{
- if (urlRef)
- {
- CFURLRef absoluteURLRef = CFURLCopyAbsoluteURL(urlRef);
- if (absoluteURLRef)
- {
- CFStringRef stringRef = CFURLCopyFileSystemPath(absoluteURLRef, kCFURLPOSIXPathStyle);
- CFStringRefToLLString(stringRef, llString, true);
- CFRelease(absoluteURLRef);
- }
- if (releaseWhenDone)
- CFRelease(urlRef);
- }
-}
-
-// --------------------------------------------------------------------------------
-
-static void FSRefToLLString(FSRef *fsRef, std::string &llString)
-{
- OSStatus error = noErr;
- char path[MAX_PATH];
-
- error = FSRefMakePath(fsRef, (UInt8*) path, sizeof(path));
- if (error == noErr)
- llString = path;
+
+ boost::filesystem::path p(parent);
+ p /= child;
+
+ if (fullname)
+ *fullname = std::string(p.string());
+
+ if (! boost::filesystem::create_directory(p))
+ {
+ return (boost::filesystem::is_directory(p));
+ }
+ return true;
}
// --------------------------------------------------------------------------------
@@ -109,35 +63,28 @@ static void FSRefToLLString(FSRef *fsRef, std::string &llString)
LLDir_Mac::LLDir_Mac()
{
mDirDelimiter = "/";
- mCurrentDirIndex = -1;
- mCurrentDirCount = -1;
-
- CFBundleRef mainBundleRef = NULL;
- CFURLRef executableURLRef = NULL;
- CFStringRef stringRef = NULL;
- OSStatus error = noErr;
- FSRef fileRef;
- CFStringRef secondLifeString = CFSTR("SecondLife");
-
- mainBundleRef = CFBundleGetMainBundle();
-
- executableURLRef = CFBundleCopyExecutableURL(mainBundleRef);
-
- if (executableURLRef != NULL)
+
+ const std::string secondLifeString = "SecondLife";
+
+ std::string *executablepathstr = getSystemExecutableFolder();
+
+ //NOTE: LLINFOS/LLERRS will not output to log here. The streams are not initialized.
+
+ if (executablepathstr)
{
// mExecutablePathAndName
- CFURLRefToLLString(executableURLRef, mExecutablePathAndName, false);
-
- // mExecutableFilename
- stringRef = CFURLCopyLastPathComponent(executableURLRef);
- CFStringRefToLLString(stringRef, mExecutableFilename, true);
-
- // mExecutableDir
- CFURLRef executableParentURLRef = CFURLCreateCopyDeletingLastPathComponent(NULL, executableURLRef);
- CFURLRefToLLString(executableParentURLRef, mExecutableDir, true);
+ mExecutablePathAndName = *executablepathstr;
+
+ boost::filesystem::path executablepath(*executablepathstr);
+
+# ifndef BOOST_SYSTEM_NO_DEPRECATED
+#endif
+ mExecutableFilename = executablepath.filename().string();
+ mExecutableDir = executablepath.parent_path().string();
// mAppRODataDir
-
+ std::string *resourcepath = getSystemResourceFolder();
+ mAppRODataDir = *resourcepath;
// *NOTE: When running in a dev tree, use the copy of
// skins in indra/newview/ rather than in the application bundle. This
@@ -146,10 +93,7 @@ LLDir_Mac::LLDir_Mac()
// MBW -- This keeps the mac application from finding other things.
// If this is really for skins, it should JUST apply to skins.
-
- CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef);
- CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true);
-
+
U32 build_dir_pos = mExecutableDir.rfind("/build-darwin-");
if (build_dir_pos != std::string::npos)
{
@@ -166,55 +110,50 @@ LLDir_Mac::LLDir_Mac()
}
// mOSUserDir
- error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef);
- if (error == noErr)
- {
- FSRef newFileRef;
-
- // Create the directory
- error = CFCreateDirectory(&fileRef, secondLifeString, &newFileRef);
- if (error == noErr)
- {
- // Save the full path to the folder
- FSRefToLLString(&newFileRef, mOSUserDir);
-
- // Create our sub-dirs
- (void) CFCreateDirectory(&newFileRef, CFSTR("data"), NULL);
- //(void) CFCreateDirectory(&newFileRef, CFSTR("cache"), NULL);
- (void) CFCreateDirectory(&newFileRef, CFSTR("logs"), NULL);
- (void) CFCreateDirectory(&newFileRef, CFSTR("user_settings"), NULL);
- (void) CFCreateDirectory(&newFileRef, CFSTR("browser_profile"), NULL);
- }
- }
-
+ std::string *appdir = getSystemApplicationSupportFolder();
+ std::string rootdir;
+
+ //Create root directory
+ if (CreateDirectory(*appdir, secondLifeString, &rootdir))
+ {
+
+ // Save the full path to the folder
+ mOSUserDir = rootdir;
+
+ // Create our sub-dirs
+ CreateDirectory(rootdir, std::string("data"), NULL);
+ CreateDirectory(rootdir, std::string("logs"), NULL);
+ CreateDirectory(rootdir, std::string("user_settings"), NULL);
+ CreateDirectory(rootdir, std::string("browser_profile"), NULL);
+ }
+
//mOSCacheDir
- FSRef cacheDirRef;
- error = FSFindFolder(kUserDomain, kCachedDataFolderType, true, &cacheDirRef);
- if (error == noErr)
+ std::string *cachedir = getSystemCacheFolder();
+
+ if (cachedir)
+
{
- FSRefToLLString(&cacheDirRef, mOSCacheDir);
- (void)CFCreateDirectory(&cacheDirRef, CFSTR("SecondLife"),NULL);
+ mOSCacheDir = *cachedir;
+ //SPATTERS TODO: This changes from ~/Library/Cache/Secondlife to ~/Library/Cache/com.app.secondlife/Secondlife. Last dir level could go away.
+ CreateDirectory(mOSCacheDir, secondLifeString, NULL);
}
// mOSUserAppDir
mOSUserAppDir = mOSUserDir;
// mTempDir
- error = FSFindFolder(kOnAppropriateDisk, kTemporaryFolderType, true, &fileRef);
- if (error == noErr)
- {
- FSRef tempRef;
- error = CFCreateDirectory(&fileRef, secondLifeString, &tempRef);
- if (error == noErr)
- FSRefToLLString(&tempRef, mTempDir);
- }
+ //Aura 120920 boost::filesystem::temp_directory_path() not yet implemented on mac. :(
+ std::string *tmpdir = getSystemTempFolder();
+ if (tmpdir)
+ {
+
+ CreateDirectory(*tmpdir, secondLifeString, &mTempDir);
+ if (tmpdir) delete tmpdir;
+ }
mWorkingDir = getCurPath();
mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin";
-
- CFRelease(executableURLRef);
- executableURLRef = NULL;
}
}
@@ -235,52 +174,18 @@ void LLDir_Mac::initAppDirs(const std::string &app_name,
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
}
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
-
- //dumpCurrentDirectories();
-}
-
-U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &mask)
-{
- U32 file_count = 0;
- glob_t g;
-
- std::string tmp_str;
- tmp_str = dirname;
- tmp_str += mask;
-
- if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
- {
- file_count = g.gl_pathc;
-
- globfree(&g);
- }
-
- return (file_count);
}
std::string LLDir_Mac::getCurPath()
{
- char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */
- getcwd(tmp_str, LL_MAX_PATH);
- return tmp_str;
+ return boost::filesystem::path( boost::filesystem::current_path() ).string();
}
-BOOL LLDir_Mac::fileExists(const std::string &filename) const
+bool LLDir_Mac::fileExists(const std::string &filename) const
{
- struct stat stat_data;
- // Check the age of the file
- // Now, we see if the files we've gathered are recent...
- int res = stat(filename.c_str(), &stat_data);
- if (!res)
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ return boost::filesystem::exists(filename);
}
diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h
index d190d70be4..558727ebbc 100644
--- a/indra/llvfs/lldir_mac.h
+++ b/indra/llvfs/lldir_mac.h
@@ -22,7 +22,7 @@
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
- */
+ */
#if !LL_DARWIN
#error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead.
@@ -45,16 +45,10 @@ public:
const std::string& app_read_only_data_dir);
virtual std::string getCurPath();
- virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
- virtual BOOL fileExists(const std::string &filename) const;
+ virtual bool fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
-
-private:
- int mCurrentDirIndex;
- int mCurrentDirCount;
- std::string mCurrentDir;
};
#endif // LL_LLDIR_MAC_H
diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp
index 21f8c3acdb..a97d72d539 100644
--- a/indra/llvfs/lldir_solaris.cpp
+++ b/indra/llvfs/lldir_solaris.cpp
@@ -272,7 +272,7 @@ std::string LLDir_Solaris::getCurPath()
}
-BOOL LLDir_Solaris::fileExists(const std::string &filename) const
+bool LLDir_Solaris::fileExists(const std::string &filename) const
{
struct stat stat_data;
// Check the age of the file
diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h
index 0b58a45b15..c6dac57e14 100644
--- a/indra/llvfs/lldir_solaris.h
+++ b/indra/llvfs/lldir_solaris.h
@@ -47,7 +47,7 @@ public:
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
- /*virtual*/ BOOL fileExists(const std::string &filename) const;
+ /*virtual*/ bool fileExists(const std::string &filename) const;
private:
DIR *mDirp;
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 7709945123..462d1cce06 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -249,7 +249,7 @@ std::string LLDir_Win32::getCurPath()
}
-BOOL LLDir_Win32::fileExists(const std::string &filename) const
+bool LLDir_Win32::fileExists(const std::string &filename) const
{
llstat stat_data;
// Check the age of the file
diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h
index 62fb4713ab..450efaf9da 100644
--- a/indra/llvfs/lldir_win32.h
+++ b/indra/llvfs/lldir_win32.h
@@ -44,7 +44,7 @@ public:
/*virtual*/ std::string getCurPath();
/*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask);
- /*virtual*/ BOOL fileExists(const std::string &filename) const;
+ /*virtual*/ bool fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp
index ff92cbb7fd..460d2a8b4f 100644
--- a/indra/llvfs/lldiriterator.cpp
+++ b/indra/llvfs/lldiriterator.cpp
@@ -26,6 +26,7 @@
#include "lldiriterator.h"
+#include "fix_macros.h"
#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
@@ -59,7 +60,7 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask)
{
is_dir = fs::is_directory(dir_path);
}
- catch (fs::basic_filesystem_error<fs::path>& e)
+ catch (const fs::filesystem_error& e)
{
llwarns << e.what() << llendl;
return;
@@ -76,7 +77,7 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask)
{
mIter = fs::directory_iterator(dir_path);
}
- catch (fs::basic_filesystem_error<fs::path>& e)
+ catch (const fs::filesystem_error& e)
{
llwarns << e.what() << llendl;
return;
@@ -121,7 +122,7 @@ bool LLDirIterator::Impl::next(std::string &fname)
while (mIter != end_itr && !found)
{
boost::smatch match;
- std::string name = mIter->path().filename();
+ std::string name = mIter->path().filename().string();
if (found = boost::regex_match(name, match, mFilterExp))
{
fname = name;
diff --git a/indra/llvfs/llvfs_objc.h b/indra/llvfs/llvfs_objc.h
new file mode 100644
index 0000000000..90101eb2e9
--- /dev/null
+++ b/indra/llvfs/llvfs_objc.h
@@ -0,0 +1,43 @@
+/**
+ * @file llvfs_objc.h
+ * @brief Definition of directory utilities class for Mac OS X
+ *
+ * $LicenseInfo:firstyear=2000&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$
+ */
+
+#if !LL_DARWIN
+#error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead.
+#endif // !LL_DARWIN
+
+#ifndef LL_LLVFS_OBJC_H
+#define LL_LLVFS_OBJC_H
+
+#include <iostream>
+
+std::string* getSystemTempFolder();
+std::string* getSystemCacheFolder();
+std::string* getSystemApplicationSupportFolder();
+std::string* getSystemResourceFolder();
+std::string* getSystemExecutableFolder();
+
+
+#endif LL_LLVFS_OBJC_H
diff --git a/indra/llvfs/llvfs_objc.mm b/indra/llvfs/llvfs_objc.mm
new file mode 100644
index 0000000000..4f9e2f81e9
--- /dev/null
+++ b/indra/llvfs/llvfs_objc.mm
@@ -0,0 +1,108 @@
+/**
+ * @file llvfs_objc.cpp
+ * @brief Cocoa implementation of directory utilities for Mac OS X
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+#if LL_DARWIN
+
+//WARNING: This file CANNOT use standard linden includes due to conflicts between definitions of BOOL
+
+#include "llvfs_objc.h"
+#import <Cocoa/Cocoa.h>
+
+std::string* getSystemTempFolder()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSString * tempDir = NSTemporaryDirectory();
+ if (tempDir == nil)
+ tempDir = @"/tmp";
+ std::string *result = ( new std::string([tempDir UTF8String]) );
+ [pool release];
+
+ return result;
+}
+
+//findSystemDirectory scoped exclusively to this file.
+std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory,
+ NSSearchPathDomainMask domainMask)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ std::string *result;
+ NSString *path = nil;
+
+ // Search for the path
+ NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory,
+ domainMask,
+ YES);
+ if ([paths count])
+ {
+ path = [paths objectAtIndex:0];
+ //SPATTERS HACK: Always attempt to create directory, ignore errors.
+ NSError *error = nil;
+
+ [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error];
+
+
+ result = new std::string([path UTF8String]);
+ }
+ [pool release];
+ return result;
+}
+
+std::string* getSystemExecutableFolder()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSString *bundlePath = [[NSBundle mainBundle] executablePath];
+ std::string *result = (new std::string([bundlePath UTF8String]));
+ [pool release];
+
+ return result;
+}
+
+std::string* getSystemResourceFolder()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
+ std::string *result = (new std::string([bundlePath UTF8String]));
+ [pool release];
+
+ return result;
+}
+
+std::string* getSystemCacheFolder()
+{
+ return findSystemDirectory (NSCachesDirectory,
+ NSUserDomainMask);
+}
+
+std::string* getSystemApplicationSupportFolder()
+{
+ return findSystemDirectory (NSApplicationSupportDirectory,
+ NSUserDomainMask);
+
+}
+
+#endif // LL_DARWIN
diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp
index a00fc8684c..3cff622a4b 100644
--- a/indra/llvfs/tests/lldir_test.cpp
+++ b/indra/llvfs/tests/lldir_test.cpp
@@ -73,35 +73,41 @@ struct LLDir_Dummy: public LLDir
// the real one.
static const char* preload[] =
{
+ // We group these fixture-data pathnames by basename, rather than
+ // sorting by full path as you might expect, because the outcome
+ // of each test strongly depends on which skins/languages provide
+ // a given basename.
"install/skins/default/colors.xml",
+ "install/skins/steam/colors.xml",
+ "user/skins/default/colors.xml",
+ "user/skins/steam/colors.xml",
+
"install/skins/default/xui/en/strings.xml",
"install/skins/default/xui/fr/strings.xml",
+ "install/skins/steam/xui/en/strings.xml",
+ "install/skins/steam/xui/fr/strings.xml",
+ "user/skins/default/xui/en/strings.xml",
+ "user/skins/default/xui/fr/strings.xml",
+ "user/skins/steam/xui/en/strings.xml",
+ "user/skins/steam/xui/fr/strings.xml",
+
"install/skins/default/xui/en/floater.xml",
"install/skins/default/xui/fr/floater.xml",
+ "user/skins/default/xui/fr/floater.xml",
+
"install/skins/default/xui/en/newfile.xml",
"install/skins/default/xui/fr/newfile.xml",
+ "user/skins/default/xui/en/newfile.xml",
+
"install/skins/default/html/en-us/welcome.html",
"install/skins/default/html/fr/welcome.html",
+
"install/skins/default/textures/only_default.jpeg",
- "install/skins/default/future/somefile.txt",
- "install/skins/steam/colors.xml",
- "install/skins/steam/xui/en/strings.xml",
- "install/skins/steam/xui/fr/strings.xml",
"install/skins/steam/textures/only_steam.jpeg",
- "user/skins/default/colors.xml",
- "user/skins/default/xui/en/strings.xml",
- "user/skins/default/xui/fr/strings.xml",
- // This is an attempted override that doesn't work: for a
- // localized subdir, a skin must have subdir/en/filename as well
- // as subdir/language/filename.
- "user/skins/default/xui/fr/floater.xml",
- // This is an override that only specifies the "en" version
- "user/skins/default/xui/en/newfile.xml",
"user/skins/default/textures/only_user_default.jpeg",
- "user/skins/steam/colors.xml",
- "user/skins/steam/xui/en/strings.xml",
- "user/skins/steam/xui/fr/strings.xml",
- "user/skins/steam/textures/only_user_steam.jpeg"
+ "user/skins/steam/textures/only_user_steam.jpeg",
+
+ "install/skins/default/future/somefile.txt"
};
BOOST_FOREACH(const char* path, preload)
{
@@ -128,7 +134,7 @@ struct LLDir_Dummy: public LLDir
return 0;
}
- virtual BOOL fileExists(const std::string& pathname) const
+ virtual bool fileExists(const std::string& pathname) const
{
// Record fileExists() calls so we can check whether caching is
// working right. Certain LLDir calls should be able to make decisions
@@ -584,7 +590,7 @@ namespace tut
ensure_equals(lldir.getLanguage(), "en");
// top-level directory of a skin isn't localized
- ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", true),
+ ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS),
vec(list_of("install/skins/default/colors.xml")
("user/skins/default/colors.xml")));
// We should not have needed to check for skins/default/en. We should
@@ -594,18 +600,18 @@ namespace tut
ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_default.jpeg"),
vec(list_of("install/skins/default/textures/only_default.jpeg")));
// Nor should we have needed to check skins/default/textures/en
- // because textures is known to be unlocalized.
+ // because textures is known not to be localized.
lldir.ensure_not_checked("install/skins/default/textures/en");
StringVec expected(vec(list_of("install/skins/default/xui/en/strings.xml")
("user/skins/default/xui/en/strings.xml")));
- ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true),
+ ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS),
expected);
// The first time, we had to probe to find out whether xui was localized.
lldir.ensure_checked("install/skins/default/xui/en");
lldir.clear_checked();
// Now make the same call again -- should return same result --
- ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true),
+ ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS),
expected);
// but this time it should remember that xui is localized.
lldir.ensure_not_checked("install/skins/default/xui/en");
@@ -648,7 +654,7 @@ namespace tut
ensure_equals(lldir.getLanguage(), "fr");
// pass merge=true to request this filename in all relevant skins
- ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true),
+ ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS),
vec(list_of
("install/skins/default/xui/en/strings.xml")
("install/skins/default/xui/fr/strings.xml")
@@ -661,20 +667,21 @@ namespace tut
("user/skins/default/xui/en/strings.xml")
("user/skins/default/xui/fr/strings.xml")));
- // The most specific skin for our dummy floater.xml is the installed
- // default. Although we have a user xui/fr/floater.xml, we would also
- // need a xui/en/floater.xml file to consider the user skin for this.
+ // Our dummy floater.xml has a user localization (for "fr") but no
+ // English override. This is a case in which CURRENT_SKIN nonetheless
+ // returns paths from two different skins.
ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "floater.xml"),
vec(list_of
("install/skins/default/xui/en/floater.xml")
- ("install/skins/default/xui/fr/floater.xml")));
+ ("user/skins/default/xui/fr/floater.xml")));
- // The user override for the default skin does define newfile.xml, but
- // only an "en" version, not a "fr" version as well. Nonetheless
- // that's the most specific skin we have, regardless of the existence
- // of a "fr" version in the installed default skin.
+ // Our dummy newfile.xml has an English override but no user
+ // localization. This is another case in which CURRENT_SKIN
+ // nonetheless returns paths from two different skins.
ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "newfile.xml"),
- vec(list_of("user/skins/default/xui/en/newfile.xml")));
+ vec(list_of
+ ("user/skins/default/xui/en/newfile.xml")
+ ("install/skins/default/xui/fr/newfile.xml")));
ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"),
vec(list_of
@@ -683,15 +690,15 @@ namespace tut
/*------------------------ "default", "zh" -------------------------*/
lldir.setSkinFolder("default", "zh");
- // Because the user default skins strings.xml has only a "fr" override
- // but not a "zh" override, the most localized version we can find is "en".
+ // Because strings.xml has only a "fr" override but no "zh" override
+ // in any skin, the most localized version we can find is "en".
ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"),
vec(list_of("user/skins/default/xui/en/strings.xml")));
/*------------------------- "steam", "en" --------------------------*/
lldir.setSkinFolder("steam", "en");
- ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", true),
+ ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS),
vec(list_of
("install/skins/default/colors.xml")
("install/skins/steam/colors.xml")
@@ -710,12 +717,12 @@ namespace tut
ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_user_steam.jpeg"),
vec(list_of("user/skins/steam/textures/only_user_steam.jpeg")));
- // merge=false
+ // CURRENT_SKIN
ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"),
vec(list_of("user/skins/steam/xui/en/strings.xml")));
- // pass merge=true to request this filename in all relevant skins
- ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true),
+ // pass constraint=ALL_SKINS to request this filename in all relevant skins
+ ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS),
vec(list_of
("install/skins/default/xui/en/strings.xml")
("install/skins/steam/xui/en/strings.xml")
@@ -725,14 +732,14 @@ namespace tut
/*------------------------- "steam", "fr" --------------------------*/
lldir.setSkinFolder("steam", "fr");
- // pass merge=true to request this filename in all relevant skins
+ // pass CURRENT_SKIN to request only the most specialized files
ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"),
vec(list_of
("user/skins/steam/xui/en/strings.xml")
("user/skins/steam/xui/fr/strings.xml")));
- // pass merge=true to request this filename in all relevant skins
- ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true),
+ // pass ALL_SKINS to request this filename in all relevant skins
+ ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", LLDir::ALL_SKINS),
vec(list_of
("install/skins/default/xui/en/strings.xml")
("install/skins/default/xui/fr/strings.xml")