Merge latest from lindenlab/viewer-development

master
Dave SIMmONs 2010-11-19 13:22:07 -08:00
commit 2eec4949cc
109 changed files with 2306 additions and 1292 deletions

View File

@ -35,3 +35,4 @@ b0cd7e150009809a0b5b0a9d5785cd4bb230413a 2.2.0-beta3
a3c12342b1af0951b8aa3b828aacef17fcea8178 2.3.0-beta1
db0fe9bb65187f365e58a717dd23d0f4754a9c1d 2.3.0-beta2
6ad3d6fa35a4e320e9ce442fce2bf9c7fc852556 2.3.0-beta3
6ad3d6fa35a4e320e9ce442fce2bf9c7fc852556 2.3.0-release

View File

@ -51,7 +51,7 @@ viewer-release.viewer_channel = "Second Life Release"
viewer-release.login_channel = "Second Life Release"
viewer-release.build_debug_release_separately = true
viewer-release.build_viewer_update_version_manager = true
viewer-release.release-viewer.jira = DRTVWR-13
# ========================================
# aimee

View File

@ -177,6 +177,7 @@ Boroondas Gupte
SNOW-610
SNOW-624
SNOW-737
STORM-318
VWR-233
VWR-20583
VWR-20891
@ -414,6 +415,7 @@ McCabe Maxsted
VWR-8689
VWR-9007
Michelle2 Zenovka
STORM-477
VWR-2652
VWR-2662
VWR-2834
@ -759,6 +761,17 @@ Whoops Babii
VWR-8298
Wilton Lundquist
VWR-7682
WolfPup Lowenhar
SNOW-622
SNOW-772
STORM-102
STORM-103
STORM-143
STORM-535
STORM-544
STORM-654
VWR-20741
VWR-20933
Zai Lynch
VWR-19505
Wolfpup Lowenhar

View File

@ -442,6 +442,14 @@
<boolean>true</boolean>
</map>
<key>SimConsoleResponse</key>
<map>
<key>flavor</key>
<string>llsd</string>
<key>trusted-sender</key>
<boolean>true</boolean>
</map>
<key>DirLandReply</key>
<map>
<key>flavor</key>

View File

@ -9,10 +9,12 @@ if (WINDOWS)
NAMES python25.exe python23.exe python.exe
NO_DEFAULT_PATH # added so that cmake does not find cygwin python
PATHS
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]

View File

@ -7,8 +7,9 @@ macro (check_message_template _target)
TARGET ${_target}
POST_BUILD
COMMAND ${PYTHON_EXECUTABLE}
ARGS ${SCRIPTS_DIR}/template_verifier.py
--mode=development --cache_master
COMMENT "Verifying message template"
ARGS ${SCRIPTS_DIR}/md5check.py
3f19d130400c547de36278a6b6f9b028
${SCRIPTS_DIR}/messages/message_template.msg
COMMENT "Verifying message template - See http://wiki.secondlife.com/wiki/Template_verifier.py"
)
endmacro (check_message_template)

View File

@ -3,7 +3,7 @@ include(Prebuilt)
if (NOT STANDALONE)
use_prebuilt_binary(libuuid)
use_prebuilt_binary(vivox)
use_prebuilt_binary(slvoice)
use_prebuilt_binary(fontconfig)
endif(NOT STANDALONE)

View File

@ -174,7 +174,7 @@ 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, false))
while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename))
{
if (filename.find("_new.xml") != std::string::npos)
{

View File

@ -216,7 +216,7 @@ gboolean rotate_image_cb(gpointer data)
std::string next_image_filename(std::string& image_path)
{
std::string image_filename;
gDirUtilp->getNextFileInDir(image_path, "/*.jpg", image_filename, true);
gDirUtilp->getNextFileInDir(image_path, "/*.jpg", image_filename);
return image_path + "/" + image_filename;
}

View File

@ -58,6 +58,11 @@ void LLProcessLauncher::setWorkingDirectory(const std::string &dir)
mWorkingDir = dir;
}
const std::string& LLProcessLauncher::getExecutable() const
{
return mExecutable;
}
void LLProcessLauncher::clearArguments()
{
mLaunchArguments.clear();

View File

@ -47,6 +47,8 @@ public:
void setExecutable(const std::string &executable);
void setWorkingDirectory(const std::string &dir);
const std::string& getExecutable() const;
void clearArguments();
void addArgument(const std::string &arg);
void addArgument(const char *arg);

View File

@ -1304,7 +1304,7 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
// handle ctrl-uparrow if we have a history enabled line editor.
case KEY_UP:
if( mHaveHistory && ( MASK_CONTROL == mask ) )
if( mHaveHistory && ((mIgnoreArrowKeys == false) || ( MASK_CONTROL == mask )) )
{
if( mCurrentHistoryLine > mLineHistory.begin() )
{
@ -1319,9 +1319,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
}
break;
// handle ctrl-downarrow if we have a history enabled line editor
// handle [ctrl]-downarrow if we have a history enabled line editor
case KEY_DOWN:
if( mHaveHistory && ( MASK_CONTROL == mask ) )
if( mHaveHistory && ((mIgnoreArrowKeys == false) || ( MASK_CONTROL == mask )) )
{
if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.end() - 1 )
{

View File

@ -1591,7 +1591,10 @@ void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params&
// appendText modifies mCursorPos...
appendText(text, false, input_params);
// ...so move cursor to top after appending text
startOfDoc();
if (!mTrackEnd)
{
startOfDoc();
}
onValueChange(0, getLength());
}

View File

@ -83,7 +83,7 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
std::string filename;
std::string fullpath;
S32 result;
while (getNextFileInDir(dirname, mask, filename, FALSE))
while (getNextFileInDir(dirname, mask, filename))
{
fullpath = dirname;
fullpath += getDirDelimiter();

View File

@ -74,8 +74,32 @@ class LLDir
// pure virtual functions
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0;
virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) = 0;
virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) = 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;

View File

@ -243,8 +243,7 @@ U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string &
}
// get the next file in the directory
// automatically wrap if we've hit the end
BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
glob_t g;
BOOL result = FALSE;
@ -276,11 +275,6 @@ BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string
mCurrentDirIndex++;
if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap)
{
mCurrentDirIndex = 0;
}
if(mCurrentDirIndex < (int)g.gl_pathc)
{
// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
@ -308,47 +302,7 @@ BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string
}
// get a random file in the directory
// automatically wrap if we've hit the end
void LLDir_Linux::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
S32 num_files;
S32 which_file;
DIR *dirp;
dirent *entryp = NULL;
fname = "";
num_files = countFilesInDir(dirname,mask);
if (!num_files)
{
return;
}
which_file = ll_rand(num_files);
// llinfos << "Random select file #" << which_file << llendl;
// which_file now indicates the (zero-based) index to which file to play
if (!((dirp = opendir(dirname.c_str()))))
{
while (which_file--)
{
if (!((entryp = readdir(dirp))))
{
return;
}
}
if ((!which_file) && entryp)
{
fname = entryp->d_name;
}
closedir(dirp);
}
}
std::string LLDir_Linux::getCurPath()
{

View File

@ -43,8 +43,7 @@ public:
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, BOOL wrap);
virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
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();

View File

@ -259,8 +259,7 @@ U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &ma
}
// get the next file in the directory
// automatically wrap if we've hit the end
BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
glob_t g;
BOOL result = FALSE;
@ -292,11 +291,6 @@ BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &
mCurrentDirIndex++;
if((mCurrentDirIndex >= g.gl_pathc) && wrap)
{
mCurrentDirIndex = 0;
}
if(mCurrentDirIndex < g.gl_pathc)
{
// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
@ -323,41 +317,7 @@ BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &
return(result);
}
// get a random file in the directory
void LLDir_Mac::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
S32 which_file;
glob_t g;
fname = "";
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)
{
which_file = ll_rand(g.gl_pathc);
// llinfos << "getRandomFileInDir: returning number " << which_file << ", path is " << g.gl_pathv[which_file] << llendl;
// The API wants just the filename, not the full path.
//fname = g.gl_pathv[which_file];
char *s = strrchr(g.gl_pathv[which_file], '/');
if(s == NULL)
s = g.gl_pathv[which_file];
else if(s[0] == '/')
s++;
fname = s;
}
globfree(&g);
}
}
S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask)
{

View File

@ -43,8 +43,7 @@ public:
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, BOOL wrap);
virtual void getRandomFileInDir(const std::string &dirname, const std::string &ask, std::string &fname);
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();

View File

@ -261,8 +261,7 @@ U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string
}
// get the next file in the directory
// automatically wrap if we've hit the end
BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
glob_t g;
BOOL result = FALSE;
@ -294,11 +293,6 @@ BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::stri
mCurrentDirIndex++;
if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap)
{
mCurrentDirIndex = 0;
}
if(mCurrentDirIndex < (int)g.gl_pathc)
{
// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
@ -326,47 +320,7 @@ BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::stri
}
// get a random file in the directory
// automatically wrap if we've hit the end
void LLDir_Solaris::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
S32 num_files;
S32 which_file;
DIR *dirp;
dirent *entryp = NULL;
fname = "";
num_files = countFilesInDir(dirname,mask);
if (!num_files)
{
return;
}
which_file = ll_rand(num_files);
// llinfos << "Random select file #" << which_file << llendl;
// which_file now indicates the (zero-based) index to which file to play
if (!((dirp = opendir(dirname.c_str()))))
{
while (which_file--)
{
if (!((entryp = readdir(dirp))))
{
return;
}
}
if ((!which_file) && entryp)
{
fname = entryp->d_name;
}
closedir(dirp);
}
}
std::string LLDir_Solaris::getCurPath()
{

View File

@ -43,8 +43,7 @@ public:
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, BOOL wrap);
virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*virtual*/ BOOL fileExists(const std::string &filename) const;
private:

View File

@ -246,21 +246,13 @@ U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &
// get the next file in the directory
// automatically wrap if we've hit the end
BOOL LLDir_Win32::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
BOOL LLDir_Win32::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
llutf16string dirnamew = utf8str_to_utf16str(dirname);
return getNextFileInDir(dirnamew, mask, fname, wrap);
}
BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
{
WIN32_FIND_DATAW FileData;
BOOL fileFound = FALSE;
fname = "";
llutf16string pathname = dirname;
pathname += utf8str_to_utf16str(mask);
WIN32_FIND_DATAW FileData;
llutf16string pathname = utf8str_to_utf16str(dirname) + utf8str_to_utf16str(mask);
if (pathname != mCurrentDir)
{
@ -273,91 +265,44 @@ BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::stri
// and open new one
// Check error opening Directory structure
if ((mDirSearch_h = FindFirstFile(pathname.c_str(), &FileData)) == INVALID_HANDLE_VALUE)
if ((mDirSearch_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)
{
// llinfos << "Unable to locate first file" << llendl;
return(FALSE);
}
}
else // get next file in list
{
// Find next entry
if (!FindNextFile(mDirSearch_h, &FileData))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
// No more files, so reset to beginning of directory
FindClose(mDirSearch_h);
mCurrentDir[0] = NULL;
if (wrap)
{
return(getNextFileInDir(pathname,"",fname,TRUE));
}
else
{
fname[0] = 0;
return(FALSE);
}
}
else
{
// Error
// llinfos << "Unable to locate next file" << llendl;
return(FALSE);
}
fileFound = TRUE;
}
}
// convert from TCHAR to char
fname = utf16str_to_utf8str(FileData.cFileName);
// fname now first name in list
return(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';
}
// get a random file in the directory
// automatically wrap if we've hit the end
void LLDir_Win32::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
S32 num_files;
S32 which_file;
HANDLE random_search_h;
fname = "";
llutf16string pathname = utf8str_to_utf16str(dirname);
pathname += utf8str_to_utf16str(mask);
WIN32_FIND_DATA FileData;
fname[0] = NULL;
num_files = countFilesInDir(dirname,mask);
if (!num_files)
{
return;
}
which_file = ll_rand(num_files);
// llinfos << "Random select mp3 #" << which_file << llendl;
// which_file now indicates the (zero-based) index to which file to play
if ((random_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)
{
while (which_file--)
{
if (!FindNextFile(random_search_h, &FileData))
{
return;
}
}
FindClose(random_search_h);
fname = utf16str_to_utf8str(llutf16string(FileData.cFileName));
if (fileFound)
{
// convert from TCHAR to char
fname = utf16str_to_utf8str(FileData.cFileName);
}
return fileFound;
}
std::string LLDir_Win32::getCurPath()

View File

@ -40,15 +40,14 @@ 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, BOOL wrap);
/*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*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, BOOL wrap);
BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname);
void* mDirSearch_h;
llutf16string mCurrentDir;

View File

@ -256,5 +256,158 @@ namespace tut
gDirUtilp->getExtension(dottedPathExt),
"ext");
}
std::string makeTestFile( const std::string& dir, const std::string& file )
{
std::string delim = gDirUtilp->getDirDelimiter();
std::string path = dir + delim + file;
LLFILE* handle = LLFile::fopen( path, "w" );
ensure("failed to open test file '"+path+"'", handle != NULL );
ensure("failed to write to test file '"+path+"'", !fputs("test file", handle) );
fclose(handle);
return path;
}
std::string makeTestDir( const std::string& dirbase )
{
int counter;
std::string uniqueDir;
bool foundUnused;
std::string delim = gDirUtilp->getDirDelimiter();
for (counter=0, foundUnused=false; !foundUnused; counter++ )
{
char counterStr[3];
sprintf(counterStr, "%02d", counter);
uniqueDir = dirbase + counterStr;
foundUnused = ! ( LLFile::isdir(uniqueDir) || LLFile::isfile(uniqueDir) );
}
ensure("test directory '" + uniqueDir + "' creation failed", !LLFile::mkdir(uniqueDir));
return uniqueDir + delim; // HACK - apparently, the trailing delimiter is needed...
}
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])
{
// Scan directory and see if any file1.* files are found
std::string scanResult;
int found = 0;
bool filesFound[5] = { false, false, false, false, false };
//std::cerr << "searching '"+directory+"' for '"+pattern+"'\n";
while ( found <= 5 && gDirUtilp->getNextFileInDir(directory, pattern, scanResult) )
{
found++;
//std::cerr << " found '"+scanResult+"'\n";
int check;
for (check=0; check < 5 && ! ( scanResult == DirScanFilename[check] ); check++)
{
}
// check is now either 5 (not found) or the index of the matching name
if (check < 5)
{
ensure( "found file '"+(std::string)DirScanFilename[check]+"' twice", ! filesFound[check] );
filesFound[check] = true;
}
else // check is 5 - should not happen
{
fail( "found unknown file '"+scanResult+"'");
}
}
for (int i=0; i<5; i++)
{
if (correctResult[i])
{
ensure("scan of '"+directory+"' using '"+pattern+"' did not return '"+DirScanFilename[i]+"'", filesFound[i]);
}
else
{
ensure("scan of '"+directory+"' using '"+pattern+"' incorrectly returned '"+DirScanFilename[i]+"'", !filesFound[i]);
}
}
}
template<> template<>
void LLDirTest_object_t::test<5>()
// getNextFileInDir
{
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 dir1files[5];
std::string dir2files[5];
for (int i=0; i<5; i++)
{
dir1files[i] = makeTestFile(dir1, DirScanFilename[i]);
dir2files[i] = makeTestFile(dir2, DirScanFilename[i]);
}
// Scan dir1 and see if each of the 5 files is found exactly once
bool expected1[5] = { true, true, true, true, true };
scanTest(dir1, "*", expected1);
// Scan dir2 and see if only the 2 *.xyz files are found
bool expected2[5] = { false, false, true, true, false };
scanTest(dir1, "*.xyz", expected2);
// Scan dir2 and see if only the 1 *.mno file is found
bool expected3[5] = { false, false, false, false, true };
scanTest(dir2, "*.mno", expected3);
// Scan dir1 and see if any *.foo files are found
bool expected4[5] = { false, false, false, false, false };
scanTest(dir1, "*.foo", expected4);
// Scan dir1 and see if any file1.* files are found
bool expected5[5] = { true, false, true, false, true };
scanTest(dir1, "file1.*", expected5);
// Scan dir1 and see if any file1.* files are found
bool expected6[5] = { true, true, false, false, false };
scanTest(dir1, "file?.abc", expected6);
// Scan dir2 and see if any file?.x?z files are found
bool expected7[5] = { false, false, true, true, false };
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);
// 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);
// Scan dir1 and see if any ?????.* files are found
bool expected11[5] = { true, true, true, true, true };
scanTest(dir1, "?????.*", expected11);
// Scan dir1 and see if any ??l??.xyz files are found
bool expected12[5] = { false, false, true, true, false };
scanTest(dir1, "??l??.xyz", expected12);
// clean up all test files and directories
for (int i=0; i<5; i++)
{
LLFile::remove(dir1files[i]);
LLFile::remove(dir2files[i]);
}
LLFile::rmdir(dir1);
LLFile::rmdir(dir2);
}
}

View File

@ -143,6 +143,7 @@ set(viewer_SOURCE_FILES
lleventnotifier.cpp
lleventpoll.cpp
llexpandabletextbox.cpp
llexternaleditor.cpp
llface.cpp
llfasttimerview.cpp
llfavoritesbar.cpp
@ -200,6 +201,7 @@ set(viewer_SOURCE_FILES
llfloaterpostprocess.cpp
llfloaterpreference.cpp
llfloaterproperties.cpp
llfloaterregiondebugconsole.cpp
llfloaterregioninfo.cpp
llfloaterreporter.cpp
llfloaterscriptdebug.cpp
@ -674,6 +676,7 @@ set(viewer_HEADER_FILES
lleventnotifier.h
lleventpoll.h
llexpandabletextbox.h
llexternaleditor.h
llface.h
llfasttimerview.h
llfavoritesbar.h
@ -731,6 +734,7 @@ set(viewer_HEADER_FILES
llfloaterpostprocess.h
llfloaterpreference.h
llfloaterproperties.h
llfloaterregiondebugconsole.h
llfloaterregioninfo.h
llfloaterreporter.h
llfloaterscriptdebug.h

View File

@ -8340,6 +8340,17 @@
<key>Value</key>
<real>1.0</real>
</map>
<key>RenderTransparentWater</key>
<map>
<key>Comment</key>
<string>Render water as transparent. Setting to false renders water as opaque with a simple texture applied.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>RenderTreeLODFactor</key>
<map>
<key>Comment</key>
@ -11905,10 +11916,10 @@
<key>Value</key>
<real>150000.0</real>
</map>
<key>XUIEditor</key>
<key>ExternalEditor</key>
<map>
<key>Comment</key>
<string>Path to program used to edit XUI files</string>
<string>Path to program used to edit LSL scripts and XUI files, e.g.: /usr/bin/gedit --new-window "%s"</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>

View File

@ -110,7 +110,17 @@
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map>
<key>LogFileNamewithDate</key>
<map>
<key>Comment</key>
<string>Add Date Stamp to chat and IM Logs with format chat-YYYY-MM-DD and 'IM file name'-YYYY-MM. To view old logs goto ..\Second Life\[login name]</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<!-- Settings below are for back compatibility only.
They are not used in current viewer anymore. But they can't be removed to avoid
influence on previous versions of the viewer in case of settings are not used or default value

View File

@ -42,6 +42,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
@ -80,6 +81,7 @@ RenderObjectBump 1 0
RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 0.5
@ -108,6 +110,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@ -135,6 +138,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 2
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@ -162,6 +166,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 2.0

View File

@ -42,6 +42,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
@ -79,6 +80,7 @@ RenderObjectBump 1 0
RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 0.5
@ -107,6 +109,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@ -134,6 +137,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 2
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@ -161,6 +165,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 2.0

View File

@ -43,6 +43,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 3
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
@ -80,6 +81,7 @@ RenderObjectBump 1 0
RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 0.5
@ -107,6 +109,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@ -133,6 +136,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 2
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@ -159,6 +163,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 3
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 2.0

View File

@ -42,6 +42,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
@ -80,6 +81,7 @@ RenderObjectBump 1 0
RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 0.5
@ -108,6 +110,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@ -135,6 +138,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 2
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@ -162,6 +166,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 2.0

View File

@ -3036,7 +3036,7 @@ void LLAppViewer::migrateCacheDirectory()
S32 file_count = 0;
std::string file_name;
std::string mask = delimiter + "*.*";
while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name, false))
while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name))
{
if (file_name == "." || file_name == "..") continue;
std::string source_path = old_cache_dir + delimiter + file_name;
@ -3255,7 +3255,7 @@ bool LLAppViewer::initCache()
dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
std::string found_file;
if (gDirUtilp->getNextFileInDir(dir, mask, found_file, false))
if (gDirUtilp->getNextFileInDir(dir, mask, found_file))
{
old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file;

View File

@ -504,8 +504,7 @@ std::string LLAppViewerLinux::generateSerialNumber()
// trawl /dev/disk/by-uuid looking for a good-looking UUID to grab
std::string this_name;
BOOL wrap = FALSE;
while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name, wrap))
while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name))
{
if (this_name.length() > best.length() ||
(this_name.length() == best.length() &&

View File

@ -798,9 +798,14 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log)
{
LLStyle::Params link_params(style_params);
link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID));
// Setting is_link = true for agent SLURL to avoid applying default style to it.
// See LLTextBase::appendTextImpl().
link_params.is_link = true;
link_params.link_href = LLSLURL("agent", chat.mFromID, "inspect").getSLURLString();
// Add link to avatar's inspector and delimiter to message.
mEditor->appendText(link_params.link_href, false, style_params);
mEditor->appendText(chat.mFromName, false, link_params);
mEditor->appendText(delimiter, false, style_params);
}
else

View File

@ -213,7 +213,6 @@ void LLNearbyChatToastPanel::init(LLSD& notification)
{
LLStyle::Params style_params_name;
LLColor4 userNameColor = LLUIColorTable::instance().getColor("ChatToastAgentNameColor");
std::string href;
if (mSourceType == CHAT_SOURCE_AGENT)
@ -225,7 +224,7 @@ void LLNearbyChatToastPanel::init(LLSD& notification)
href = LLSLURL("object", mFromID, "inspect").getSLURLString();
}
style_params_name.color(userNameColor);
style_params_name.color(textColor);
std::string font_name = LLFontGL::nameFromFont(messageFont);
std::string font_style_size = LLFontGL::sizeFromFont(messageFont);

View File

@ -48,7 +48,8 @@
#include "llviewershadermgr.h"
#include "llwaterparammanager.h"
const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004");
const LLUUID TRANSPARENT_WATER_TEXTURE("2bfd3884-7e27-69b9-ba3a-3e673f680004");
const LLUUID OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf86315de055");
static float sTime;
@ -71,10 +72,14 @@ LLDrawPoolWater::LLDrawPoolWater() :
gGL.getTexUnit(0)->bind(mHBTex[1]);
mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
mWaterImagep = LLViewerTextureManager::getFetchedTexture(WATER_TEST);
mWaterImagep->setNoDelete() ;
mWaterImagep = LLViewerTextureManager::getFetchedTexture(TRANSPARENT_WATER_TEXTURE);
llassert(mWaterImagep);
mWaterImagep->setNoDelete();
mOpaqueWaterImagep = LLViewerTextureManager::getFetchedTexture(OPAQUE_WATER_TEXTURE);
llassert(mOpaqueWaterImagep);
mWaterNormp = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL);
mWaterNormp->setNoDelete() ;
mWaterNormp->setNoDelete();
restoreGL();
}
@ -161,6 +166,14 @@ void LLDrawPoolWater::render(S32 pass)
std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater());
// See if we are rendering water as opaque or not
if (!gSavedSettings.getBOOL("RenderTransparentWater"))
{
// render water for low end hardware
renderOpaqueLegacyWater();
return;
}
LLGLEnable blend(GL_BLEND);
if ((mVertexShaderLevel > 0) && !sSkipScreenCopy)
@ -314,6 +327,87 @@ void LLDrawPoolWater::render(S32 pass)
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
}
// for low end hardware
void LLDrawPoolWater::renderOpaqueLegacyWater()
{
LLVOSky *voskyp = gSky.mVOSkyp;
stop_glerror();
// Depth sorting and write to depth buffer
// since this is opaque, we should see nothing
// behind the water. No blending because
// of no transparency. And no face culling so
// that the underside of the water is also opaque.
LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
LLGLDisable no_cull(GL_CULL_FACE);
LLGLDisable no_blend(GL_BLEND);
gPipeline.disableLights();
mOpaqueWaterImagep->addTextureStats(1024.f*1024.f);
// Activate the texture binding and bind one
// texture since all images will have the same texture
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->bind(mOpaqueWaterImagep);
// Automatically generate texture coords for water texture
glEnable(GL_TEXTURE_GEN_S); //texture unit 0
glEnable(GL_TEXTURE_GEN_T); //texture unit 0
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
// Use the fact that we know all water faces are the same size
// to save some computation
// Slowly move texture coordinates over time so the watter appears
// to be moving.
F32 movement_period_secs = 50.f;
F32 offset = fmod(gFrameTimeSeconds, movement_period_secs);
if (movement_period_secs != 0)
{
offset /= movement_period_secs;
}
else
{
offset = 0;
}
F32 tp0[4] = { 16.f / 256.f, 0.0f, 0.0f, offset };
F32 tp1[4] = { 0.0f, 16.f / 256.f, 0.0f, offset };
glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1);
glColor3f(1.f, 1.f, 1.f);
for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
iter != mDrawFace.end(); iter++)
{
LLFace *face = *iter;
if (voskyp->isReflFace(face))
{
continue;
}
face->renderIndexed();
}
stop_glerror();
// Reset the settings back to expected values
glDisable(GL_TEXTURE_GEN_S); //texture unit 0
glDisable(GL_TEXTURE_GEN_T); //texture unit 0
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
}
void LLDrawPoolWater::renderReflection(LLFace* face)
{
LLVOSky *voskyp = gSky.mVOSkyp;

View File

@ -39,6 +39,7 @@ class LLDrawPoolWater: public LLFacePool
protected:
LLPointer<LLViewerTexture> mHBTex[2];
LLPointer<LLViewerTexture> mWaterImagep;
LLPointer<LLViewerTexture> mOpaqueWaterImagep;
LLPointer<LLViewerTexture> mWaterNormp;
public:
@ -80,6 +81,9 @@ public:
void renderReflection(LLFace* face);
void shade();
protected:
void renderOpaqueLegacyWater();
};
void cgErrorCallback();

View File

@ -0,0 +1,192 @@
/**
* @file llexternaleditor.cpp
* @brief A convenient class to run external editor.
*
* $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 "llviewerprecompiledheaders.h"
#include "llexternaleditor.h"
#include "llui.h"
// static
const std::string LLExternalEditor::sFilenameMarker = "%s";
// static
const std::string LLExternalEditor::sSetting = "ExternalEditor";
bool LLExternalEditor::setCommand(const std::string& env_var, const std::string& override)
{
std::string cmd = findCommand(env_var, override);
if (cmd.empty())
{
llwarns << "Empty editor command" << llendl;
return false;
}
// Add the filename marker if missing.
if (cmd.find(sFilenameMarker) == std::string::npos)
{
cmd += " \"" + sFilenameMarker + "\"";
llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl;
}
string_vec_t tokens;
if (tokenize(tokens, cmd) < 2) // 2 = bin + at least one arg (%s)
{
llwarns << "Error parsing editor command" << llendl;
return false;
}
// Check executable for existence.
std::string bin_path = tokens[0];
if (!LLFile::isfile(bin_path))
{
llwarns << "Editor binary [" << bin_path << "] not found" << llendl;
return false;
}
// Save command.
mProcess.setExecutable(bin_path);
mArgs.clear();
for (size_t i = 1; i < tokens.size(); ++i)
{
if (i > 1) mArgs += " ";
mArgs += "\"" + tokens[i] + "\"";
}
llinfos << "Setting command [" << bin_path << " " << mArgs << "]" << llendl;
return true;
}
bool LLExternalEditor::run(const std::string& file_path)
{
std::string args = mArgs;
if (mProcess.getExecutable().empty() || args.empty())
{
llwarns << "Editor command not set" << llendl;
return false;
}
// Substitute the filename marker in the command with the actual passed file name.
LLStringUtil::replaceString(args, sFilenameMarker, file_path);
// Split command into separate tokens.
string_vec_t tokens;
tokenize(tokens, args);
// Set process arguments taken from the command.
mProcess.clearArguments();
for (string_vec_t::const_iterator arg_it = tokens.begin(); arg_it != tokens.end(); ++arg_it)
{
mProcess.addArgument(*arg_it);
}
// Run the editor.
llinfos << "Running editor command [" << mProcess.getExecutable() + " " + args << "]" << llendl;
int result = mProcess.launch();
if (result == 0)
{
// Prevent killing the process in destructor (will add it to the zombies list).
mProcess.orphan();
}
return result == 0;
}
// static
size_t LLExternalEditor::tokenize(string_vec_t& tokens, const std::string& str)
{
tokens.clear();
// Split the argument string into separate strings for each argument
typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep("", "\" ", boost::drop_empty_tokens);
tokenizer tokens_list(str, sep);
tokenizer::iterator token_iter;
BOOL inside_quotes = FALSE;
BOOL last_was_space = FALSE;
for (token_iter = tokens_list.begin(); token_iter != tokens_list.end(); ++token_iter)
{
if (!strncmp("\"",(*token_iter).c_str(),2))
{
inside_quotes = !inside_quotes;
}
else if (!strncmp(" ",(*token_iter).c_str(),2))
{
if(inside_quotes)
{
tokens.back().append(std::string(" "));
last_was_space = TRUE;
}
}
else
{
std::string to_push = *token_iter;
if (last_was_space)
{
tokens.back().append(to_push);
last_was_space = FALSE;
}
else
{
tokens.push_back(to_push);
}
}
}
return tokens.size();
}
// static
std::string LLExternalEditor::findCommand(
const std::string& env_var,
const std::string& override)
{
std::string cmd;
// Get executable path.
if (!override.empty()) // try the supplied override first
{
cmd = override;
llinfos << "Using override" << llendl;
}
else if (!LLUI::sSettingGroups["config"]->getString(sSetting).empty())
{
cmd = LLUI::sSettingGroups["config"]->getString(sSetting);
llinfos << "Using setting" << llendl;
}
else // otherwise use the path specified by the environment variable
{
char* env_var_val = getenv(env_var.c_str());
if (env_var_val)
{
cmd = env_var_val;
llinfos << "Using env var " << env_var << llendl;
}
}
llinfos << "Found command [" << cmd << "]" << llendl;
return cmd;
}

View File

@ -0,0 +1,91 @@
/**
* @file llexternaleditor.h
* @brief A convenient class to run external editor.
*
* $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_LLEXTERNALEDITOR_H
#define LL_LLEXTERNALEDITOR_H
#include <llprocesslauncher.h>
/**
* Usage:
* LLExternalEditor ed;
* ed.setCommand("MY_EXTERNAL_EDITOR_VAR");
* ed.run("/path/to/file1");
* ed.run("/other/path/to/file2");
*/
class LLExternalEditor
{
typedef std::vector<std::string> string_vec_t;
public:
/**
* Set editor command.
*
* @param env_var Environment variable of the same purpose.
* @param override Optional override.
*
* First tries the override, then a predefined setting (sSetting),
* then the environment variable.
*
* @return Command if found, empty string otherwise.
*
* @see sSetting
*/
bool setCommand(const std::string& env_var, const std::string& override = LLStringUtil::null);
/**
* Run the editor with the given file.
*
* @param file_path File to edit.
* @return true on success, false on error.
*/
bool run(const std::string& file_path);
private:
static std::string findCommand(
const std::string& env_var,
const std::string& override);
static size_t tokenize(string_vec_t& tokens, const std::string& str);
/**
* Filename placeholder that gets replaced with an actual file name.
*/
static const std::string sFilenameMarker;
/**
* Setting that can specify the editor command.
*/
static const std::string sSetting;
std::string mArgs;
LLProcessLauncher mProcess;
};
#endif // LL_LLEXTERNALEDITOR_H

View File

@ -282,7 +282,8 @@ std::string LLFloaterPreference::sSkin = "";
LLFloaterPreference::LLFloaterPreference(const LLSD& key)
: LLFloater(key),
mGotPersonalInfo(false),
mOriginalIMViaEmail(false)
mOriginalIMViaEmail(false),
mDoubleClickActionDirty(false)
{
//Build Floater is now Called from LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
@ -320,6 +321,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.getUIColor", boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2));
mCommitCallbackRegistrar.add("Pref.MaturitySettings", boost::bind(&LLFloaterPreference::onChangeMaturity, this));
mCommitCallbackRegistrar.add("Pref.BlockList", boost::bind(&LLFloaterPreference::onClickBlockList, this));
mCommitCallbackRegistrar.add("Pref.CommitDoubleClickChekbox", boost::bind(&LLFloaterPreference::onDoubleClickCheckBox, this, _1));
mCommitCallbackRegistrar.add("Pref.CommitRadioDoubleClick", boost::bind(&LLFloaterPreference::onDoubleClickRadio, this));
sSkin = gSavedSettings.getString("SkinCurrent");
@ -342,6 +345,8 @@ BOOL LLFloaterPreference::postBuild()
if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab")))
tabcontainer->selectFirstTab();
updateDoubleClickControls();
getChild<LLUICtrl>("cache_location")->setEnabled(FALSE); // make it read-only but selectable (STORM-227)
std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
setCacheLocation(cache_location);
@ -475,6 +480,12 @@ void LLFloaterPreference::apply()
gAgent.sendAgentUpdateUserInfo(new_im_via_email,mDirectoryVisibility);
}
}
if (mDoubleClickActionDirty)
{
updateDoubleClickSettings();
mDoubleClickActionDirty = false;
}
}
void LLFloaterPreference::cancel()
@ -501,6 +512,12 @@ void LLFloaterPreference::cancel()
// reverts any changes to current skin
gSavedSettings.setString("SkinCurrent", sSkin);
if (mDoubleClickActionDirty)
{
updateDoubleClickControls();
mDoubleClickActionDirty = false;
}
}
void LLFloaterPreference::onOpen(const LLSD& key)
@ -1246,7 +1263,7 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im
getChildView("show_timestamps_check_im")->setEnabled(TRUE);
getChildView("log_path_string")->setEnabled(FALSE);// LineEditor becomes readonly in this case.
getChildView("log_path_button")->setEnabled(TRUE);
childEnable("logfile_name_datestamp");
std::string display_email(email);
getChild<LLUICtrl>("email_address")->setValue(display_email);
@ -1318,6 +1335,68 @@ void LLFloaterPreference::onClickBlockList()
}
}
void LLFloaterPreference::onDoubleClickCheckBox(LLUICtrl* ctrl)
{
if (!ctrl) return;
mDoubleClickActionDirty = true;
LLRadioGroup* radio_double_click_action = getChild<LLRadioGroup>("double_click_action");
if (!radio_double_click_action) return;
// select default value("teleport") in radio-group.
radio_double_click_action->setSelectedIndex(0);
// set radio-group enabled depending on state of checkbox
radio_double_click_action->setEnabled(ctrl->getValue());
}
void LLFloaterPreference::onDoubleClickRadio()
{
mDoubleClickActionDirty = true;
}
void LLFloaterPreference::updateDoubleClickSettings()
{
LLCheckBoxCtrl* double_click_action_cb = getChild<LLCheckBoxCtrl>("double_click_chkbox");
if (!double_click_action_cb) return;
bool enable = double_click_action_cb->getValue().asBoolean();
LLRadioGroup* radio_double_click_action = getChild<LLRadioGroup>("double_click_action");
if (!radio_double_click_action) return;
// enable double click radio-group depending on state of checkbox
radio_double_click_action->setEnabled(enable);
if (!enable)
{
// set double click action settings values to false if checkbox was unchecked
gSavedSettings.setBOOL("DoubleClickAutoPilot", false);
gSavedSettings.setBOOL("DoubleClickTeleport", false);
}
else
{
std::string selected = radio_double_click_action->getValue().asString();
bool teleport_selected = selected == "radio_teleport";
// set double click action settings values depending on chosen radio-button
gSavedSettings.setBOOL( "DoubleClickTeleport", teleport_selected );
gSavedSettings.setBOOL( "DoubleClickAutoPilot", !teleport_selected );
}
}
void LLFloaterPreference::updateDoubleClickControls()
{
// check is one of double-click actions settings enabled
bool double_click_action_enabled = gSavedSettings.getBOOL("DoubleClickAutoPilot") || gSavedSettings.getBOOL("DoubleClickTeleport");
LLCheckBoxCtrl* double_click_action_cb = getChild<LLCheckBoxCtrl>("double_click_chkbox");
if (double_click_action_cb)
{
// check checkbox if one of double-click actions settings enabled, uncheck otherwise
double_click_action_cb->setValue(double_click_action_enabled);
}
LLRadioGroup* double_click_action_radio = getChild<LLRadioGroup>("double_click_action");
if (!double_click_action_radio) return;
// set radio-group enabled if one of double-click actions settings enabled
double_click_action_radio->setEnabled(double_click_action_enabled);
// select button in radio-group depending on setting
double_click_action_radio->setSelectedIndex(gSavedSettings.getBOOL("DoubleClickAutoPilot"));
}
void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param)
{

View File

@ -95,6 +95,14 @@ protected:
void setHardwareDefaults();
// callback for when client turns on shaders
void onVertexShaderEnable();
// callback for changing double click action checkbox
void onDoubleClickCheckBox(LLUICtrl* ctrl);
// callback for selecting double click action radio-button
void onDoubleClickRadio();
// updates double-click action settings depending on controls from preferences
void updateDoubleClickSettings();
// updates double-click action controls depending on values from settings.xml
void updateDoubleClickControls();
// This function squirrels away the current values of the controls so that
// cancel() can restore them.
@ -145,6 +153,9 @@ public:
static void refreshSkin(void* data);
private:
static std::string sSkin;
// set true if state of double-click action checkbox or radio-group was changed by user
// (reset back to false on apply or cancel)
bool mDoubleClickActionDirty;
bool mGotPersonalInfo;
bool mOriginalIMViaEmail;

View File

@ -0,0 +1,227 @@
/**
* @file llfloaterregiondebugconsole.h
* @author Brad Kittenbrink <brad@lindenlab.com>
* @brief Quick and dirty console for region debug settings
*
* $LicenseInfo:firstyear=2010&license=viewergpl$
*
* Copyright (c) 2010-2010, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterregiondebugconsole.h"
#include "llagent.h"
#include "llhttpclient.h"
#include "llhttpnode.h"
#include "lllineeditor.h"
#include "lltexteditor.h"
#include "llviewerregion.h"
// Two versions of the sim console API are supported.
//
// SimConsole capability (deprecated):
// This is the initial implementation that is supported by some versions of the
// simulator. It is simple and straight forward, just POST a command and the
// body of the response has the result. This API is deprecated because it
// doesn't allow the sim to use any asynchronous API.
//
// SimConsoleAsync capability:
// This capability replaces the original SimConsole capability. It is similar
// in that the command is POSTed to the SimConsoleAsync cap, but the response
// comes in through the event poll, which gives the simulator more flexibility
// and allows it to perform complex operations without blocking any frames.
//
// We will assume the SimConsoleAsync capability is available, and fall back to
// the SimConsole cap if it is not. The simulator will only support one or the
// other.
namespace
{
// Signal used to notify the floater of responses from the asynchronous
// API.
typedef boost::signals2::signal<
void (const std::string& output)> console_reply_signal_t;
console_reply_signal_t sConsoleReplySignal;
const std::string PROMPT("\n\n> ");
const std::string UNABLE_TO_SEND_COMMAND(
"ERROR: The last command was not received by the server.");
const std::string CONSOLE_UNAVAILABLE(
"ERROR: No console available for this region/simulator.");
const std::string CONSOLE_NOT_SUPPORTED(
"This region does not support the simulator console.");
// This responder handles the initial response. Unless error() is called
// we assume that the simulator has received our request. Error will be
// called if this request times out.
class AsyncConsoleResponder : public LLHTTPClient::Responder
{
public:
/* virtual */
void error(U32 status, const std::string& reason)
{
sConsoleReplySignal(UNABLE_TO_SEND_COMMAND);
}
};
class ConsoleResponder : public LLHTTPClient::Responder
{
public:
ConsoleResponder(LLTextEditor *output) : mOutput(output)
{
}
/*virtual*/
void error(U32 status, const std::string& reason)
{
if (mOutput)
{
mOutput->appendText(
UNABLE_TO_SEND_COMMAND + PROMPT,
false);
}
}
/*virtual*/
void result(const LLSD& content)
{
if (mOutput)
{
mOutput->appendText(
content.asString() + PROMPT, false);
}
}
LLTextEditor * mOutput;
};
// This handles responses for console commands sent via the asynchronous
// API.
class ConsoleResponseNode : public LLHTTPNode
{
public:
/* virtual */
void post(
LLHTTPNode::ResponsePtr reponse,
const LLSD& context,
const LLSD& input) const
{
llinfos << "Received response from the debug console: "
<< input << llendl;
sConsoleReplySignal(input["body"].asString());
}
};
}
LLFloaterRegionDebugConsole::LLFloaterRegionDebugConsole(LLSD const & key)
: LLFloater(key), mOutput(NULL)
{
mReplySignalConnection = sConsoleReplySignal.connect(
boost::bind(
&LLFloaterRegionDebugConsole::onReplyReceived,
this,
_1));
}
LLFloaterRegionDebugConsole::~LLFloaterRegionDebugConsole()
{
mReplySignalConnection.disconnect();
}
BOOL LLFloaterRegionDebugConsole::postBuild()
{
LLLineEditor* input = getChild<LLLineEditor>("region_debug_console_input");
input->setEnableLineHistory(true);
input->setCommitCallback(boost::bind(&LLFloaterRegionDebugConsole::onInput, this, _1, _2));
input->setFocus(true);
input->setCommitOnFocusLost(false);
mOutput = getChild<LLTextEditor>("region_debug_console_output");
std::string url = gAgent.getRegion()->getCapability("SimConsoleAsync");
if (url.empty())
{
// Fall back to see if the old API is supported.
url = gAgent.getRegion()->getCapability("SimConsole");
if (url.empty())
{
mOutput->appendText(
CONSOLE_NOT_SUPPORTED + PROMPT,
false);
return TRUE;
}
}
mOutput->appendText("> ", false);
return TRUE;
}
void LLFloaterRegionDebugConsole::onInput(LLUICtrl* ctrl, const LLSD& param)
{
LLLineEditor* input = static_cast<LLLineEditor*>(ctrl);
std::string text = input->getText() + "\n";
std::string url = gAgent.getRegion()->getCapability("SimConsoleAsync");
if (url.empty())
{
// Fall back to the old API
url = gAgent.getRegion()->getCapability("SimConsole");
if (url.empty())
{
text += CONSOLE_UNAVAILABLE + PROMPT;
}
else
{
// Using SimConsole (deprecated)
LLHTTPClient::post(
url,
LLSD(input->getText()),
new ConsoleResponder(mOutput));
}
}
else
{
// Using SimConsoleAsync
LLHTTPClient::post(
url,
LLSD(input->getText()),
new AsyncConsoleResponder);
}
mOutput->appendText(text, false);
input->clear();
}
void LLFloaterRegionDebugConsole::onReplyReceived(const std::string& output)
{
mOutput->appendText(output + PROMPT, false);
}
LLHTTPRegistration<ConsoleResponseNode>
gHTTPRegistrationMessageDebugConsoleResponse(
"/message/SimConsoleResponse");

View File

@ -0,0 +1,63 @@
/**
* @file llfloaterregiondebugconsole.h
* @author Brad Kittenbrink <brad@lindenlab.com>
* @brief Quick and dirty console for region debug settings
*
* $LicenseInfo:firstyear=2010&license=viewergpl$
*
* Copyright (c) 2010-2010, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLFLOATERREGIONDEBUGCONSOLE_H
#define LL_LLFLOATERREGIONDEBUGCONSOLE_H
#include <boost/signals2.hpp>
#include "llfloater.h"
#include "llhttpclient.h"
class LLTextEditor;
class LLFloaterRegionDebugConsole : public LLFloater, public LLHTTPClient::Responder
{
public:
LLFloaterRegionDebugConsole(LLSD const & key);
virtual ~LLFloaterRegionDebugConsole();
// virtual
BOOL postBuild();
void onInput(LLUICtrl* ctrl, const LLSD& param);
LLTextEditor * mOutput;
private:
void onReplyReceived(const std::string& output);
boost::signals2::connection mReplySignalConnection;
};
#endif // LL_LLFLOATERREGIONDEBUGCONSOLE_H

View File

@ -36,6 +36,7 @@
// Internal utility
#include "lleventtimer.h"
#include "llexternaleditor.h"
#include "llrender.h"
#include "llsdutil.h"
#include "llxmltree.h"
@ -160,6 +161,8 @@ public:
DiffMap mDiffsMap; // map, of filename to pair of list of changed element paths and list of errors
private:
LLExternalEditor mExternalEditor;
// XUI elements for this floater
LLScrollListCtrl* mFileList; // scroll list control for file list
LLLineEditor* mEditorPathTextBox; // text field for path to editor executable
@ -185,7 +188,7 @@ private:
std::string mSavedDiffPath; // stored diff file path so closing this floater doesn't reset it
// Internal functionality
static void popupAndPrintWarning(std::string& warning); // pop up a warning
static void popupAndPrintWarning(const std::string& warning); // pop up a warning
std::string getLocalizedDirectory(); // build and return the path to the XUI directory for the currently-selected localization
void scanDiffFile(LLXmlTreeNode* file_node); // scan a given XML node for diff entries and highlight them in its associated file
void highlightChangedElements(); // look up the list of elements to highlight and highlight them in the current floater
@ -480,7 +483,7 @@ BOOL LLFloaterUIPreview::postBuild()
mLanguageSelection->removeall(); // clear out anything temporarily in list from XML
while(found) // for every directory
{
if((found = gDirUtilp->getNextFileInDir(xui_dir, "*", language_directory, FALSE))) // get next directory
if((found = gDirUtilp->getNextFileInDir(xui_dir, "*", 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
@ -597,7 +600,7 @@ void LLFloaterUIPreview::onClose(bool app_quitting)
// Error handling (to avoid code repetition)
// *TODO: this is currently unlocalized. Add to alerts/notifications.xml, someday, maybe.
void LLFloaterUIPreview::popupAndPrintWarning(std::string& warning)
void LLFloaterUIPreview::popupAndPrintWarning(const std::string& warning)
{
llwarns << warning << llendl;
LLSD args;
@ -634,7 +637,7 @@ void LLFloaterUIPreview::refreshList()
BOOL found = TRUE;
while(found) // for every floater file that matches the pattern
{
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "floater_*.xml", name, FALSE))) // get next file matching pattern
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "floater_*.xml", 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)
}
@ -642,7 +645,7 @@ void LLFloaterUIPreview::refreshList()
found = TRUE;
while(found) // for every inspector file that matches the pattern
{
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "inspect_*.xml", name, FALSE))) // get next file matching pattern
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "inspect_*.xml", 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)
}
@ -650,7 +653,7 @@ void LLFloaterUIPreview::refreshList()
found = TRUE;
while(found) // for every menu file that matches the pattern
{
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "menu_*.xml", name, FALSE))) // get next file matching pattern
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "menu_*.xml", 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)
}
@ -658,7 +661,7 @@ void LLFloaterUIPreview::refreshList()
found = TRUE;
while(found) // for every panel file that matches the pattern
{
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "panel_*.xml", name, FALSE))) // get next file matching pattern
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "panel_*.xml", 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)
}
@ -667,7 +670,7 @@ void LLFloaterUIPreview::refreshList()
found = TRUE;
while(found) // for every sidepanel file that matches the pattern
{
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", name, FALSE))) // get next file matching pattern
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", 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)
}
@ -998,190 +1001,55 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)
// Respond to button click to edit currently-selected floater
void LLFloaterUIPreview::onClickEditFloater()
{
std::string file_name = mFileList->getSelectedItemLabel(1); // get the file name of the currently-selected floater
if(std::string("") == file_name) // if no item is selected
// Determine file to edit.
std::string file_path;
{
return; // ignore click
}
std::string path = getLocalizedDirectory() + file_name;
std::string file_name = mFileList->getSelectedItemLabel(1); // get the file name of the currently-selected floater
if (file_name.empty()) // if no item is selected
{
llwarns << "No file selected" << llendl;
return; // ignore click
}
file_path = getLocalizedDirectory() + file_name;
// stat file to see if it exists (some localized versions may not have it there are no diffs, and then we try to open an nonexistent file)
llstat dummy;
if(LLFile::stat(path.c_str(), &dummy)) // if the file does not exist
{
std::string warning = "No file for this floater exists in the selected localization. Opening the EN version instead.";
popupAndPrintWarning(warning);
path = get_xui_dir() + mDelim + "en" + mDelim + file_name; // open the en version instead, by default
// stat file to see if it exists (some localized versions may not have it there are no diffs, and then we try to open an nonexistent file)
llstat dummy;
if(LLFile::stat(file_path.c_str(), &dummy)) // if the file does not exist
{
popupAndPrintWarning("No file for this floater exists in the selected localization. Opening the EN version instead.");
file_path = get_xui_dir() + mDelim + "en" + mDelim + file_name; // open the en version instead, by default
}
}
// get executable path
const char* exe_path_char;
std::string path_in_textfield = mEditorPathTextBox->getText();
if(std::string("") != path_in_textfield) // if the text field is not emtpy, use its path
// Set the editor command.
std::string cmd_override;
{
exe_path_char = path_in_textfield.c_str();
}
else if (!LLUI::sSettingGroups["config"]->getString("XUIEditor").empty())
{
exe_path_char = LLUI::sSettingGroups["config"]->getString("XUIEditor").c_str();
}
else // otherwise use the path specified by the environment variable
{
exe_path_char = getenv("LL_XUI_EDITOR");
}
std::string bin = mEditorPathTextBox->getText();
if (!bin.empty())
{
// surround command with double quotes for the case if the path contains spaces
if (bin.find("\"") == std::string::npos)
{
bin = "\"" + bin + "\"";
}
// error check executable path
if(NULL == exe_path_char)
std::string args = mEditorArgsTextBox->getText();
cmd_override = bin + " " + args;
}
}
if (!mExternalEditor.setCommand("LL_XUI_EDITOR", cmd_override))
{
std::string warning = "Select an editor by setting the environment variable LL_XUI_EDITOR or specifying its path in the \"Editor Path\" field.";
std::string warning = "Select an editor by setting the environment variable LL_XUI_EDITOR "
"or the ExternalEditor setting or specifying its path in the \"Editor Path\" field.";
popupAndPrintWarning(warning);
return;
}
std::string exe_path = exe_path_char; // do this after error check, otherwise internal strlen call fails on bad char*
// remove any quotes; they're added back in later where necessary
int found_at;
while((found_at = exe_path.find("\"")) != -1 || (found_at = exe_path.find("'")) != -1)
// Run the editor.
if (!mExternalEditor.run(file_path))
{
exe_path.erase(found_at,1);
}
llstat s;
if(!LLFile::stat(exe_path.c_str(), &s)) // If the executable exists
{
// build paths and arguments
std::string quote = std::string("\"");
std::string args;
std::string custom_args = mEditorArgsTextBox->getText();
int position_of_file = custom_args.find(std::string("%FILE%"), 0); // prepare to replace %FILE% with actual file path
std::string first_part_of_args = "";
std::string second_part_of_args = "";
if(-1 == position_of_file) // default: Executable.exe File.xml
{
args = quote + path + quote; // execute the command Program.exe "File.xml"
}
else // use advanced command-line arguments, e.g. "Program.exe -safe File.xml" -windowed for "-safe %FILE% -windowed"
{
first_part_of_args = custom_args.substr(0,position_of_file); // get part of args before file name
second_part_of_args = custom_args.substr(position_of_file+6,custom_args.length()); // get part of args after file name
custom_args = first_part_of_args + std::string("\"") + path + std::string("\"") + second_part_of_args; // replace %FILE% with "<file path>" and put back together
args = custom_args; // and save in the variable that is actually used
}
// find directory in which executable resides by taking everything after last slash
int last_slash_position = exe_path.find_last_of(mDelim);
if(-1 == last_slash_position)
{
std::string warning = std::string("Unable to find a valid path to the specified executable for XUI XML editing: ") + exe_path;
popupAndPrintWarning(warning);
return;
}
std::string exe_dir = exe_path.substr(0,last_slash_position); // strip executable off, e.g. get "C:\Program Files\TextPad 5" (with or without trailing slash)
#if LL_WINDOWS
PROCESS_INFORMATION pinfo;
STARTUPINFOA sinfo;
memset(&sinfo, 0, sizeof(sinfo));
memset(&pinfo, 0, sizeof(pinfo));
std::string exe_name = exe_path.substr(last_slash_position+1);
args = quote + exe_name + quote + std::string(" ") + args; // and prepend the executable name, so we get 'Program.exe "Arg1"'
char *args2 = new char[args.size() + 1]; // Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
strcpy(args2, args.c_str());
// we don't want the current directory to be the executable directory, since the file path is now relative. By using
// NULL for the current directory instead of exe_dir.c_str(), the path to the target file will work.
if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo))
{
// DWORD dwErr = GetLastError();
std::string warning = "Creating editor process failed!";
popupAndPrintWarning(warning);
}
else
{
// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
// sGatewayHandle = pinfo.hProcess;
CloseHandle(pinfo.hThread); // stops leaks - nothing else
}
delete[] args2;
#else // if !LL_WINDOWS
// This code was copied from the code to run SLVoice, with some modification; should work in UNIX (Mac/Darwin or Linux)
{
std::vector<std::string> arglist;
arglist.push_back(exe_path.c_str());
// Split the argument string into separate strings for each argument
typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep("","\" ", boost::drop_empty_tokens);
tokenizer tokens(args, sep);
tokenizer::iterator token_iter;
BOOL inside_quotes = FALSE;
BOOL last_was_space = FALSE;
for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
{
if(!strncmp("\"",(*token_iter).c_str(),2))
{
inside_quotes = !inside_quotes;
}
else if(!strncmp(" ",(*token_iter).c_str(),2))
{
if(inside_quotes)
{
arglist.back().append(std::string(" "));
last_was_space = TRUE;
}
}
else
{
std::string to_push = *token_iter;
if(last_was_space)
{
arglist.back().append(to_push);
last_was_space = FALSE;
}
else
{
arglist.push_back(to_push);
}
}
}
// create an argv vector for the child process
char **fakeargv = new char*[arglist.size() + 1];
int i;
for(i=0; i < arglist.size(); i++)
fakeargv[i] = const_cast<char*>(arglist[i].c_str());
fakeargv[i] = NULL;
fflush(NULL); // flush all buffers before the child inherits them
pid_t id = vfork();
if(id == 0)
{
// child
execv(exe_path.c_str(), fakeargv);
// If we reach this point, the exec failed.
// Use _exit() instead of exit() per the vfork man page.
std::string warning = "Creating editor process failed (vfork/execv)!";
popupAndPrintWarning(warning);
_exit(0);
}
// parent
delete[] fakeargv;
// sGatewayPID = id;
}
#endif // LL_WINDOWS
}
else
{
std::string warning = "Unable to find path to external XML editor for XUI preview tool";
popupAndPrintWarning(warning);
popupAndPrintWarning("Failed to run editor");
return;
}
}

View File

@ -680,8 +680,6 @@ void LLIMFloater::updateMessages()
if (messages.size())
{
// LLUIColor chat_color = LLUIColorTable::instance().getColor("IMChatColor");
LLSD chat_args;
chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history;

View File

@ -537,15 +537,14 @@ bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
void LLIMModel::LLIMSession::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name)
{
if (av_name.mLegacyFirstName.empty())
if (av_name.mUsername.empty())
{
// if mLegacyFirstName is empty it means display names is off and the
// data came from the gCacheName, mDisplayName will be the legacy name
mHistoryFileName = LLCacheName::cleanFullName(av_name.mDisplayName);
// display names is off, use mDisplayName which will be the legacy name
mHistoryFileName = LLCacheName::buildUsername(av_name.mDisplayName);
}
else
{
mHistoryFileName = LLCacheName::cleanFullName(av_name.getLegacyName());
mHistoryFileName = av_name.mUsername;
}
}

View File

@ -182,15 +182,31 @@ private:
//static
std::string LLLogChat::makeLogFileName(std::string filename)
{
if( gSavedPerAccountSettings.getBOOL("LogFileNamewithDate") )
{
time_t now;
time(&now);
char dbuffer[20]; /* Flawfinder: ignore */
if (filename == "chat")
{
strftime(dbuffer, 20, "-%Y-%m-%d", localtime(&now));
}
else
{
strftime(dbuffer, 20, "-%Y-%m", localtime(&now));
}
filename += dbuffer;
}
filename = cleanFileName(filename);
filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename);
filename += ".txt";
//LL_INFOS("") << "Current:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
return filename;
}
std::string LLLogChat::cleanFileName(std::string filename)
{
std::string invalidChars = "\"\'\\/?*:<>|";
std::string invalidChars = "\"\'\\/?*:.<>|";
std::string::size_type position = filename.find_first_of(invalidChars);
while (position != filename.npos)
{
@ -354,10 +370,19 @@ void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& me
llwarns << "Session name is Empty!" << llendl;
return ;
}
LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r"); /*Flawfinder: ignore*/
if (!fptr) return; //No previous conversation with this name.
//LL_INFOS("") << "Loading:" << file_name << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
//LL_INFOS("") << "Current:" << makeLogFileName(file_name) << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
if (!fptr)
{
fptr = LLFile::fopen(oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
if (!fptr)
{
if (!fptr) return; //No previous conversation with this name.
}
}
//LL_INFOS("") << "Reading:" << file_name << LL_ENDL;
char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/
char *bptr;
S32 len;
@ -544,3 +569,32 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im)
im[IM_TEXT] = name_and_text[IDX_TEXT];
return true; //parsed name and message text, maybe have a timestamp too
}
std::string LLLogChat::oldLogFileName(std::string filename)
{
std::string scanResult;
std::string directory = gDirUtilp->getPerAccountChatLogsDir();/* get Users log directory */
directory += gDirUtilp->getDirDelimiter();/* add final OS dependent delimiter */
filename=cleanFileName(filename);/* lest make shure the file name has no invalad charecters befor making the pattern */
std::string pattern = (filename+(( filename == "chat" ) ? "-???\?-?\?-??.txt" : "-???\?-??.txt"));/* create search pattern*/
//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))
{
//LL_INFOS("") << "Found :" << scanResult << LL_ENDL;
allfiles.push_back(scanResult);
}
if (allfiles.size() == 0) // if no result from date search, return generic filename
{
scanResult = directory + filename + ".txt";
}
else
{
std::sort(allfiles.begin(), allfiles.end());
scanResult = directory + allfiles.back();
// thisfile is now the most recent version of the file.
}
//LL_INFOS("") << "Reading:" << scanResult << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
return scanResult;
}

View File

@ -41,6 +41,10 @@ public:
};
static std::string timestamp(bool withdate = false);
static std::string makeLogFileName(std::string(filename));
/**
*Add functions to get old and non date stamped file names when needed
*/
static std::string oldLogFileName(std::string(filename));
static void saveHistory(const std::string& filename,
const std::string& from,
const LLUUID& from_id,

View File

@ -329,15 +329,23 @@ void LLPanelMainInventory::setSortBy(const LLSD& userdata)
if (sort_field == "name")
{
U32 order = getActivePanel()->getSortOrder();
getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
order &= ~LLInventoryFilter::SO_DATE;
getActivePanel()->setSortOrder( order );
gSavedSettings.setU32("InventorySortOrder", order);
gSavedSettings.setBOOL("Inventory.SortByName", TRUE );
gSavedSettings.setBOOL("Inventory.SortByDate", FALSE );
}
else if (sort_field == "date")
{
U32 order = getActivePanel()->getSortOrder();
getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE );
order |= LLInventoryFilter::SO_DATE;
getActivePanel()->setSortOrder( order );
gSavedSettings.setU32("InventorySortOrder", order);
gSavedSettings.setBOOL("Inventory.SortByName", FALSE );
gSavedSettings.setBOOL("Inventory.SortByDate", TRUE );
@ -375,6 +383,8 @@ void LLPanelMainInventory::setSortBy(const LLSD& userdata)
gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", TRUE );
}
getActivePanel()->setSortOrder( order );
gSavedSettings.setU32("InventorySortOrder", order);
}
}
@ -915,6 +925,7 @@ void LLPanelMainInventory::initListCommandsHandlers()
));
mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2));
mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mGearMenuButton->setMenu(mMenuGearDefault);
@ -1000,6 +1011,11 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
const LLSD arg = "date";
setSortBy(arg);
}
if (command_name == "sort_system_folders_to_top")
{
const LLSD arg = "systemfolderstotop";
setSortBy(arg);
}
if (command_name == "show_filters")
{
toggleFindOptions();
@ -1173,6 +1189,31 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
return TRUE;
}
BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata)
{
const std::string command_name = userdata.asString();
if (command_name == "sort_by_name")
{
U32 order = getActivePanel()->getSortOrder();
return ~order & LLInventoryFilter::SO_DATE;
}
if (command_name == "sort_by_recent")
{
U32 order = getActivePanel()->getSortOrder();
return order & LLInventoryFilter::SO_DATE;
}
if (command_name == "sort_system_folders_to_top")
{
U32 order = getActivePanel()->getSortOrder();
return order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
}
return FALSE;
}
bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
{
*accept = ACCEPT_NO;

View File

@ -136,6 +136,7 @@ protected:
void onTrashButtonClick();
void onClipboardAction(const LLSD& userdata);
BOOL isActionEnabled(const LLSD& command_name);
BOOL isActionChecked(const LLSD& userdata);
void onCustomAction(const LLSD& command_name);
bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
/**

View File

@ -34,11 +34,13 @@
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "lldir.h"
#include "llexternaleditor.h"
#include "llfloaterreg.h"
#include "llinventorydefines.h"
#include "llinventorymodel.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
#include "lllivefile.h"
#include "llhelp.h"
#include "llnotificationsutil.h"
#include "llresmgr.h"
@ -115,6 +117,54 @@ static bool have_script_upload_cap(LLUUID& object_id)
return object && (! object->getRegion()->getCapability("UpdateScriptTask").empty());
}
/// ---------------------------------------------------------------------------
/// LLLiveLSLFile
/// ---------------------------------------------------------------------------
class LLLiveLSLFile : public LLLiveFile
{
public:
LLLiveLSLFile(std::string file_path, LLLiveLSLEditor* parent);
~LLLiveLSLFile();
void ignoreNextUpdate() { mIgnoreNextUpdate = true; }
protected:
/*virtual*/ bool loadFile();
LLLiveLSLEditor* mParent;
bool mIgnoreNextUpdate;
};
LLLiveLSLFile::LLLiveLSLFile(std::string file_path, LLLiveLSLEditor* parent)
: mParent(parent)
, mIgnoreNextUpdate(false)
, LLLiveFile(file_path, 1.0)
{
}
LLLiveLSLFile::~LLLiveLSLFile()
{
LLFile::remove(filename());
}
bool LLLiveLSLFile::loadFile()
{
if (mIgnoreNextUpdate)
{
mIgnoreNextUpdate = false;
return true;
}
if (!mParent->loadScriptText(filename()))
{
return false;
}
// Disable sync to avoid recursive load->save->load calls.
mParent->saveIfNeeded(false);
return true;
}
/// ---------------------------------------------------------------------------
/// LLFloaterScriptSearch
/// ---------------------------------------------------------------------------
@ -281,6 +331,7 @@ LLScriptEdCore::LLScriptEdCore(
const LLHandle<LLFloater>& floater_handle,
void (*load_callback)(void*),
void (*save_callback)(void*, BOOL),
void (*edit_callback)(void*),
void (*search_replace_callback) (void* userdata),
void* userdata,
S32 bottom_pad)
@ -290,6 +341,7 @@ LLScriptEdCore::LLScriptEdCore(
mEditor( NULL ),
mLoadCallback( load_callback ),
mSaveCallback( save_callback ),
mEditCallback( edit_callback ),
mSearchReplaceCallback( search_replace_callback ),
mUserdata( userdata ),
mForceClose( FALSE ),
@ -329,6 +381,7 @@ BOOL LLScriptEdCore::postBuild()
childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this);
childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,FALSE));
childSetAction("Edit_btn", boost::bind(&LLScriptEdCore::onEditButtonClick, this));
initMenu();
@ -809,6 +862,13 @@ void LLScriptEdCore::doSave( BOOL close_after_save )
}
}
void LLScriptEdCore::onEditButtonClick()
{
if (mEditCallback)
{
mEditCallback(mUserdata);
}
}
void LLScriptEdCore::onBtnUndoChanges()
{
@ -949,6 +1009,7 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata)
self->getHandle(),
LLPreviewLSL::onLoad,
LLPreviewLSL::onSave,
NULL, // no edit callback
LLPreviewLSL::onSearchReplace,
self,
0);
@ -1417,6 +1478,7 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata)
self->getHandle(),
&LLLiveLSLEditor::onLoad,
&LLLiveLSLEditor::onSave,
&LLLiveLSLEditor::onEdit,
&LLLiveLSLEditor::onSearchReplace,
self,
0);
@ -1433,6 +1495,7 @@ LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) :
mCloseAfterSave(FALSE),
mPendingUploads(0),
mIsModifiable(FALSE),
mLiveFile(NULL),
mIsNew(false)
{
mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this);
@ -1458,6 +1521,7 @@ BOOL LLLiveLSLEditor::postBuild()
LLLiveLSLEditor::~LLLiveLSLEditor()
{
delete mLiveFile;
}
// virtual
@ -1639,38 +1703,39 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
delete xored_id;
}
// unused
// void LLLiveLSLEditor::loadScriptText(const std::string& filename)
// {
// if(!filename)
// {
// llerrs << "Filename is Empty!" << llendl;
// return;
// }
// LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
// if(file)
// {
// // read in the whole file
// fseek(file, 0L, SEEK_END);
// long file_length = ftell(file);
// fseek(file, 0L, SEEK_SET);
// char* buffer = new char[file_length+1];
// size_t nread = fread(buffer, 1, file_length, file);
// if (nread < (size_t) file_length)
// {
// llwarns << "Short read" << llendl;
// }
// buffer[nread] = '\0';
// fclose(file);
// mScriptEd->mEditor->setText(LLStringExplicit(buffer));
// mScriptEd->mEditor->makePristine();
// delete[] buffer;
// }
// else
// {
// llwarns << "Error opening " << filename << llendl;
// }
// }
bool LLLiveLSLEditor::loadScriptText(const std::string& filename)
{
if (filename.empty())
{
llwarns << "Empty file name" << llendl;
return false;
}
LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
if (!file)
{
llwarns << "Error opening " << filename << llendl;
return false;
}
// read in the whole file
fseek(file, 0L, SEEK_END);
size_t file_length = (size_t) ftell(file);
fseek(file, 0L, SEEK_SET);
char* buffer = new char[file_length+1];
size_t nread = fread(buffer, 1, file_length, file);
if (nread < file_length)
{
llwarns << "Short read" << llendl;
}
buffer[nread] = '\0';
fclose(file);
mScriptEd->mEditor->setText(LLStringExplicit(buffer));
//mScriptEd->mEditor->makePristine();
delete[] buffer;
return true;
}
void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
{
@ -1825,9 +1890,8 @@ LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
mItem = new LLViewerInventoryItem(item);
}
void LLLiveLSLEditor::saveIfNeeded()
void LLLiveLSLEditor::saveIfNeeded(bool sync)
{
llinfos << "LLLiveLSLEditor::saveIfNeeded()" << llendl;
LLViewerObject* object = gObjectList.findObject(mObjectUUID);
if(!object)
{
@ -1877,29 +1941,19 @@ void LLLiveLSLEditor::saveIfNeeded()
mItem->setAssetUUID(asset_id);
mItem->setTransactionID(tid);
// write out the data, and store it in the asset database
LLFILE* fp = LLFile::fopen(filename, "wb");
if(!fp)
writeToFile(filename);
if (sync)
{
llwarns << "Unable to write to " << filename << llendl;
LLSD row;
row["columns"][0]["value"] = "Error writing to local file. Is your hard drive full?";
row["columns"][0]["font"] = "SANSSERIF_SMALL";
mScriptEd->mErrorList->addElement(row);
return;
// Sync with external ed2itor.
std::string tmp_file = getTmpFileName();
llstat s;
if (LLFile::stat(tmp_file, &s) == 0) // file exists
{
if (mLiveFile) mLiveFile->ignoreNextUpdate();
writeToFile(tmp_file);
}
}
std::string utf8text = mScriptEd->mEditor->getText();
// Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889
if ( utf8text.size() == 0 )
{
utf8text = " ";
}
fputs(utf8text.c_str(), fp);
fclose(fp);
fp = NULL;
// save it out to asset server
std::string url = object->getRegion()->getCapability("UpdateScriptTask");
@ -1916,6 +1970,73 @@ void LLLiveLSLEditor::saveIfNeeded()
}
}
void LLLiveLSLEditor::openExternalEditor()
{
LLViewerObject* object = gObjectList.findObject(mObjectUUID);
if(!object)
{
LLNotificationsUtil::add("SaveScriptFailObjectNotFound");
return;
}
delete mLiveFile; // deletes file
// Save the script to a temporary file.
std::string filename = getTmpFileName();
writeToFile(filename);
// Start watching file changes.
mLiveFile = new LLLiveLSLFile(filename, this);
mLiveFile->addToEventTimer();
// Open it in external editor.
{
LLExternalEditor ed;
if (!ed.setCommand("LL_SCRIPT_EDITOR"))
{
std::string msg = "Select an editor by setting the environment variable LL_SCRIPT_EDITOR "
"or the ExternalEditor setting"; // *TODO: localize
LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", msg));
return;
}
ed.run(filename);
}
}
bool LLLiveLSLEditor::writeToFile(const std::string& filename)
{
LLFILE* fp = LLFile::fopen(filename, "wb");
if (!fp)
{
llwarns << "Unable to write to " << filename << llendl;
LLSD row;
row["columns"][0]["value"] = "Error writing to local file. Is your hard drive full?";
row["columns"][0]["font"] = "SANSSERIF_SMALL";
mScriptEd->mErrorList->addElement(row);
return false;
}
std::string utf8text = mScriptEd->mEditor->getText();
// Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889
if (utf8text.size() == 0)
{
utf8text = " ";
}
fputs(utf8text.c_str(), fp);
fclose(fp);
return true;
}
std::string LLLiveLSLEditor::getTmpFileName()
{
return std::string(LLFile::tmpdir()) + "sl_script_" + mObjectUUID.asString() + ".lsl";
}
void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url,
const std::string& filename,
const LLUUID& task_id,
@ -2138,6 +2259,14 @@ void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)
self->saveIfNeeded();
}
// static
void LLLiveLSLEditor::onEdit(void* userdata)
{
LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
self->openExternalEditor();
}
// static
void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)
{

View File

@ -35,6 +35,7 @@
#include "lliconctrl.h"
#include "llframetimer.h"
class LLLiveLSLFile;
class LLMessageSystem;
class LLTextEditor;
class LLButton;
@ -62,6 +63,7 @@ public:
const LLHandle<LLFloater>& floater_handle,
void (*load_callback)(void* userdata),
void (*save_callback)(void* userdata, BOOL close_after_save),
void (*edit_callback)(void*),
void (*search_replace_callback)(void* userdata),
void* userdata,
S32 bottom_pad = 0); // pad below bottom row of buttons
@ -80,6 +82,8 @@ public:
bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response);
bool handleReloadFromServerDialog(const LLSD& notification, const LLSD& response);
void onEditButtonClick();
static void onCheckLock(LLUICtrl*, void*);
static void onHelpComboCommit(LLUICtrl* ctrl, void* userdata);
static void onClickBack(void* userdata);
@ -114,6 +118,7 @@ private:
LLTextEditor* mEditor;
void (*mLoadCallback)(void* userdata);
void (*mSaveCallback)(void* userdata, BOOL close_after_save);
void (*mEditCallback)(void* userdata);
void (*mSearchReplaceCallback) (void* userdata);
void* mUserdata;
LLComboBox *mFunctions;
@ -179,6 +184,7 @@ protected:
// Used to view and edit an LSL that is attached to an object.
class LLLiveLSLEditor : public LLPreview
{
friend class LLLiveLSLFile;
public:
LLLiveLSLEditor(const LLSD& key);
~LLLiveLSLEditor();
@ -202,7 +208,10 @@ private:
virtual void loadAsset();
void loadAsset(BOOL is_new);
void saveIfNeeded();
void saveIfNeeded(bool sync = true);
void openExternalEditor();
std::string getTmpFileName();
bool writeToFile(const std::string& filename);
void uploadAssetViaCaps(const std::string& url,
const std::string& filename,
const LLUUID& task_id,
@ -218,6 +227,7 @@ private:
static void onSearchReplace(void* userdata);
static void onLoad(void* userdata);
static void onSave(void* userdata, BOOL close_after_save);
static void onEdit(void* userdata);
static void onLoadComplete(LLVFS *vfs, const LLUUID& asset_uuid,
LLAssetType::EType type,
@ -227,7 +237,7 @@ private:
static void onRunningCheckboxClicked(LLUICtrl*, void* userdata);
static void onReset(void* userdata);
// void loadScriptText(const std::string& filename); // unused
bool loadScriptText(const std::string& filename);
void loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type);
static void onErrorList(LLUICtrl*, void* user_data);
@ -253,6 +263,7 @@ private:
LLCheckBoxCtrl* mMonoCheckbox;
BOOL mIsModifiable;
LLLiveLSLFile* mLiveFile;
};
#endif // LL_LLPREVIEWSCRIPT_H

View File

@ -117,10 +117,23 @@ static bool handleSetShaderChanged(const LLSD& newvalue)
gBumpImageList.destroyGL();
gBumpImageList.restoreGL();
// Changing shader also changes the terrain detail to high, reflect that change here
if (newvalue.asBoolean())
{
// shaders enabled, set terrain detail to high
gSavedSettings.setS32("RenderTerrainDetail", 1);
}
// else, leave terrain detail as is
LLViewerShaderMgr::instance()->setShaders();
return true;
}
bool handleRenderTransparentWaterChanged(const LLSD& newvalue)
{
LLWorld::getInstance()->updateWaterObjects();
return true;
}
static bool handleReleaseGLBufferChanged(const LLSD& newvalue)
{
if (gPipeline.isInit())
@ -637,6 +650,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("ShowMiniLocationPanel")->getSignal()->connect(boost::bind(&toggle_show_mini_location_panel, _2));
gSavedSettings.getControl("ShowObjectRenderingCost")->getSignal()->connect(boost::bind(&toggle_show_object_render_cost, _2));
gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2));
gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2));
}
#if TEST_CACHED_CONTROL

View File

@ -81,6 +81,7 @@
#include "llfloaterpostprocess.h"
#include "llfloaterpreference.h"
#include "llfloaterproperties.h"
#include "llfloaterregiondebugconsole.h"
#include "llfloaterregioninfo.h"
#include "llfloaterreporter.h"
#include "llfloaterscriptdebug.h"
@ -227,6 +228,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("reporter", "floater_report_abuse.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterReporter>);
LLFloaterReg::add("reset_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterResetQueue>);
LLFloaterReg::add("region_debug_console", "floater_region_debug_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionDebugConsole>);
LLFloaterReg::add("region_info", "floater_region_info.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionInfo>);
LLFloaterReg::add("script_debug", "floater_script_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebug>);

View File

@ -1083,7 +1083,7 @@ 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, false))
while(gDirUtilp->getNextFileInDir(base_dir, "*_*", filename))
{
target = base_dir;
target += filename;

View File

@ -6500,16 +6500,6 @@ class LLToggleControl : public view_listener_t
std::string control_name = userdata.asString();
BOOL checked = gSavedSettings.getBOOL( control_name );
gSavedSettings.setBOOL( control_name, !checked );
// Doubleclick actions - there can be only one
if ((control_name == "DoubleClickAutoPilot") && !checked)
{
gSavedSettings.setBOOL( "DoubleClickTeleport", FALSE );
}
else if ((control_name == "DoubleClickTeleport") && !checked)
{
gSavedSettings.setBOOL( "DoubleClickAutoPilot", FALSE );
}
return true;
}
};

View File

@ -3031,6 +3031,7 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
}
else
{
args["NAME"] = source_name;
LLNotificationsUtil::add("OfferCallingCard", args, payload);
}
}

View File

@ -1400,6 +1400,8 @@ 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");
capabilityNames.append("UntrustedSimulatorMessage");

View File

@ -60,8 +60,10 @@ const U32 WIDTH = (N_RES * WAVE_STEP); //128.f //64 // width of wave tile, in
const F32 WAVE_STEP_INV = (1. / WAVE_STEP);
LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
: LLStaticViewerObject(id, pcode, regionp),
LLVOWater::LLVOWater(const LLUUID &id,
const LLPCode pcode,
LLViewerRegion *regionp) :
LLStaticViewerObject(id, pcode, regionp),
mRenderType(LLPipeline::RENDER_TYPE_WATER)
{
// Terrain must draw during selection passes so it can block objects behind it.
@ -153,11 +155,17 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
LLStrider<U16> indicesp;
U16 index_offset;
S32 size = 16;
S32 num_quads = size*size;
face->setSize(4*num_quads, 6*num_quads);
// A quad is 4 vertices and 6 indices (making 2 triangles)
static const unsigned int vertices_per_quad = 4;
static const unsigned int indices_per_quad = 6;
const S32 size = gSavedSettings.getBOOL("RenderTransparentWater") ? 16 : 1;
const S32 num_quads = size * size;
face->setSize(vertices_per_quad * num_quads,
indices_per_quad * num_quads);
if (face->mVertexBuffer.isNull())
{
face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);

View File

@ -89,7 +89,7 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)
while(found)
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false);
found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name);
if(found)
{
@ -115,7 +115,7 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)
while(found)
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name, false);
found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name);
if(found)
{
name=name.erase(name.length()-4);

View File

@ -104,7 +104,7 @@ void LLWLParamManager::loadPresets(const std::string& file_name)
while(found)
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false);
found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name);
if(found)
{
@ -130,7 +130,7 @@ void LLWLParamManager::loadPresets(const std::string& file_name)
while(found)
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name, false);
found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name);
if(found)
{
name=name.erase(name.length()-4);

View File

@ -399,9 +399,6 @@
<color
name="HighlightParentColor"
value="0.67 0.83 0.96 1" />
<color
name="IMChatColor"
reference="LtGray" />
<color
name="IMHistoryBgColor"
reference="Unused?" />
@ -766,9 +763,6 @@
<color
name="SysWellItemSelected"
value="0.3 0.3 0.3 1.0" />
<color
name="ChatToastAgentNameColor"
reference="EmphasisColor" />
<color
name="ColorSwatchBorderColor"
value="0.45098 0.517647 0.607843 1"/>

View File

@ -4,19 +4,19 @@
Ingen registreret
</floater.string>
<floater.string name="bump">
[TIME] [FIRST] [LAST] ramte dig
[TIME] [NAME] ramte dig
</floater.string>
<floater.string name="llpushobject">
[TIME] [FIRST] [LAST] skubbede dig med et script
[TIME] [NAME] skubbede dig med et script
</floater.string>
<floater.string name="selected_object_collide">
[TIME] [FIRST] [LAST] ramte dig med et objekt
[TIME] [NAME] ramte dig med et objekt
</floater.string>
<floater.string name="scripted_object_collide">
[TIME] [FIRST] [LAST] ramte dig med et scriptet objekt
[TIME] [NAME] ramte dig med et scriptet objekt
</floater.string>
<floater.string name="physical_object_collide">
[TIME] [FIRST] [LAST] ramte dig med et fysisk objekt
[TIME] [NAME] ramte dig med et fysisk objekt
</floater.string>
<floater.string name="timeStr">
[[hour,datetime,slt]:[min,datetime,slt]]

View File

@ -11,7 +11,7 @@
</text>
<icon name="icon_person" tool_tip="Person"/>
<text name="payee_name">
[FIRST] [LAST]
Test Name That Is Extremely Long To Check Clipping
</text>
<button label="L$1" label_selected="L$1" name="fastpay 1"/>
<button label="L$5" label_selected="L$5" name="fastpay 5"/>

View File

@ -8,7 +8,7 @@
</string>
<icon name="icon_person" tool_tip="Person"/>
<text name="payee_name">
[FIRST] [LAST]
Ericacita Moostopolison
</text>
<text name="object_name_label">
Via objekt:

View File

@ -931,10 +931,10 @@ Henvis til dette fra en hjemmeside for at give andre nem adgang til denne lokati
Erstattet manglende tøj/kropsdele med standard.
</notification>
<notification name="FriendOnline">
[FIRST] [LAST] er Online
[NAME] er Online
</notification>
<notification name="FriendOffline">
[FIRST] [LAST] er Offline
[NAME] er Offline
</notification>
<notification name="AddSelfFriend">
Selvom du nok er meget sød, kan du ikke tilføje dig selv som ven.
@ -1002,9 +1002,6 @@ Prøv venligst igen.
<notification name="CannotRemoveProtectedCategories">
Du kan ikke fjerne beskyttede kategorier.
</notification>
<notification name="OfferedCard">
Du har tilbudt et visitkort til [FIRST] [LAST]
</notification>
<notification name="UnableToBuyWhileDownloading">
Ikke muligt at købe, imens genstandens data hentes.
Prøv venligst igen.
@ -1120,7 +1117,7 @@ Prøv venligst at geninstallere plugin eller kontakt leverandøren hvis probleme
De genstande du ejer på det valgte stykke land er blevet returneret til din beholdning.
</notification>
<notification name="OtherObjectsReturned">
Genstandene på det valgte stykke land der er ejet af [FIRST] [LAST] er blevet returneret til hans eller hendes beholdning.
Genstandene på det valgte stykke land der er ejet af [NAME] er blevet returneret til hans eller hendes beholdning.
</notification>
<notification name="OtherObjectsReturned2">
Objekterne i den valgte parcel, ejet af beboeren &apos;[NAME]&apos;, er blevet returneret til deres ejer.
@ -1321,7 +1318,7 @@ Prøv igen om lidt.
Tilbud om venskab afvist.
</notification>
<notification name="OfferCallingCard">
[FIRST] [LAST] tilbyder dig et visitkort.
[NAME] tilbyder dig et visitkort.
Dette vil lave et bogmørke i din beholding, så du hurtigt kan sende en IM til denne beboer.
<form name="form">
<button name="Accept" text="Acceptér"/>
@ -1380,7 +1377,7 @@ Tillad denne anmodning?
</form>
</notification>
<notification name="ScriptDialog">
[FIRST] [LAST]&apos;s &apos;[TITLE]&apos;
[NAME]&apos;s &apos;&lt;nolink&gt;[TITLE]&lt;/nolink&gt;&apos;
[MESSAGE]
<form name="form">
<button name="Ignore" text="Ignorér"/>
@ -1424,13 +1421,13 @@ Klik på Acceptér for at deltage eller Afvis for at afvise invitationen. Klik p
</form>
</notification>
<notification name="AutoUnmuteByIM">
[FIRST] [LAST] fik tilsendt en personlig besked og er dermed automatisk ikke mere blokeret.
[NAME] fik tilsendt en personlig besked og er dermed automatisk ikke mere blokeret.
</notification>
<notification name="AutoUnmuteByMoney">
[FIRST] [LAST] blev givet penge og er dermed automatisk ikke mere blokeret.
[NAME] blev givet penge og er dermed automatisk ikke mere blokeret.
</notification>
<notification name="AutoUnmuteByInventory">
[FIRST] [LAST] blev tilbudt en genstand og er dermed automatisk ikke mere blokeret.
[NAME] blev tilbudt en genstand og er dermed automatisk ikke mere blokeret.
</notification>
<notification name="VoiceInviteGroup">
[NAME] har has sluttet sig til stemme-chaten i gruppen [GROUP].

View File

@ -3469,7 +3469,7 @@ Hvis du bliver ved med at modtage denne besked, kontakt venligst [SUPPORT_SITE].
Du er den eneste deltager i denne samtale
</string>
<string name="offline_message">
[FIRST] [LAST] er ikke logget på.
[NAME] er ikke logget på.
</string>
<string name="invite_message">
Tryk på [BUTTON NAME] knappen for at acceptére/tilslutte til denne stemme chat.

View File

@ -2481,7 +2481,7 @@ Versuchen Sie es in einigen Minuten erneut.
Ihr Freundschaftsangebot wurde abgelehnt.
</notification>
<notification name="OfferCallingCard">
[FIRST] [LAST] bietet Ihnen ihre/seine Visitenkarte an.
[NAME] bietet Ihnen ihre/seine Visitenkarte an.
Ihrem Inventar wird ein Lesezeichen erstellt, damit Sie diesem Einwohner einfach eine IM schicken können.
<form name="form">
<button name="Accept" text="Akzeptieren"/>

View File

@ -54,7 +54,7 @@
<text name="my_account_link" value="[[URL] Meine Startseite aufrufen]"/>
<text name="title_partner_text" value="Mein Partner:"/>
<panel name="partner_data_panel">
<text initial_value="(wird in Datenbank gesucht)" name="partner_text" value="[FIRST] [LAST]"/>
<text initial_value="(wird in Datenbank gesucht)" name="partner_text"/>
</panel>
<text name="partner_edit_link" value="[[URL] bearbeiten]"/>
</panel>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
name="region_debug_console"
title="Region Debug"
layout="topleft"
min_height="300"
min_width="300"
height="400"
width="600"
default_tab_group="1">
<text_editor
left="10"
type="string"
length="1"
follows="left|top|right|bottom"
font="Monospace"
height="366"
width="576"
ignore_tab="false"
layout="topleft"
max_length="65536"
name="region_debug_console_output"
show_line_numbers="false"
word_wrap="true"
track_end="true"
read_only="true">
</text_editor>
<line_editor
border_style="line"
border_thickness="1"
tab_group="1"
follows="left|top|right"
font="SansSerif"
height="19"
layout="topleft"
bottom_delta="20"
max_length="127"
name="region_debug_console_input"
top_delta="0"
width="576" />
</floater>

View File

@ -16,22 +16,39 @@
</menu_item_call>
<menu_item_separator
layout="topleft" />
<menu_item_call
<menu_item_check
label="Sort by Name"
layout="topleft"
name="sort_by_name">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="sort_by_name" />
</menu_item_call>
<menu_item_call
<on_check
function="Inventory.GearDefault.Check"
parameter="sort_by_name" />
</menu_item_check>
<menu_item_check
label="Sort by Most Recent"
layout="topleft"
name="sort_by_recent">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="sort_by_recent" />
</menu_item_call>
<on_check
function="Inventory.GearDefault.Check"
parameter="sort_by_recent" />
</menu_item_check>
<menu_item_check
label="Sort System Folders to Top"
layout="topleft"
name="sort_system_folders_to_top">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="sort_system_folders_to_top" />
<on_check
function="Inventory.GearDefault.Check"
parameter="sort_system_folders_to_top" />
</menu_item_check>
<menu_item_separator
layout="topleft" />
<menu_item_call

View File

@ -359,6 +359,18 @@
<menu_item_check.on_check
control="NavBarShowParcelProperties" />
</menu_item_check>
<menu_item_separator />
<menu_item_check
label="Advanced Menu"
name="Show Advanced Menu"
shortcut="control|alt|shift|D">
<on_check
function="CheckControl"
parameter="UseDebugMenus" />
<on_click
function="ToggleControl"
parameter="UseDebugMenus" />
</menu_item_check>
</menu>
<menu_item_separator/>
@ -1526,6 +1538,18 @@
<menu_item_call.on_click
function="View.DefaultUISize" />
</menu_item_call>
<!-- This second, alternative shortcut for Show Advanced Menu is for backward compatibility. The main shortcut has been changed so it's Linux-friendly, where the old shortcut is typically eaten by the window manager. -->
<menu_item_check
label="Show Advanced Menu - legacy shortcut"
name="Show Advanced Menu - legacy shortcut"
shortcut="control|alt|D">
<on_check
function="CheckControl"
parameter="UseDebugMenus" />
<on_click
function="ToggleControl"
parameter="UseDebugMenus" />
</menu_item_check>
<menu_item_separator/>
@ -1693,23 +1717,6 @@
<menu_item_call.on_click
function="View.ZoomOut" />
</menu_item_call>
<menu_item_separator
visible="false"/>
<!-- Made invisible to avoid a dissonance: menu item toggles the menu where it is located. EXT-8069.
Can't be removed, to keep shortcut workable.
-->
<menu_item_check
label="Show Advanced Menu"
name="Show Advanced Menu"
shortcut="control|alt|D"
visible="false">
<on_check
function="CheckControl"
parameter="UseDebugMenus" />
<on_click
function="ToggleControl"
parameter="UseDebugMenus" />
</menu_item_check>
</menu> <!--Shortcuts-->
<menu_item_separator/>
@ -1732,7 +1739,6 @@
function="ToggleControl"
parameter="QAMode" />
</menu_item_check>
</menu>
<menu
create_jump_keys="true"
@ -2655,24 +2661,16 @@
function="Advanced.PrintTextureMemoryStats" />
</menu_item_call>
<menu_item_check
label="Double-ClickAuto-Pilot"
name="Double-ClickAuto-Pilot">
label="Region Debug Console"
name="Region Debug Console"
shortcut="control|shift|`"
use_mac_ctrl="true">
<menu_item_check.on_check
function="CheckControl"
parameter="DoubleClickAutoPilot" />
function="Floater.Visible"
parameter="region_debug_console" />
<menu_item_check.on_click
function="ToggleControl"
parameter="DoubleClickAutoPilot" />
</menu_item_check>
<menu_item_check
label="Double-Click Teleport"
name="DoubleClick Teleport">
<menu_item_check.on_check
function="CheckControl"
parameter="DoubleClickTeleport" />
<menu_item_check.on_click
function="ToggleControl"
parameter="DoubleClickTeleport" />
function="Floater.Toggle"
parameter="region_debug_console" />
</menu_item_check>
<menu_item_separator />

View File

@ -5539,7 +5539,7 @@ Friendship offer declined.
name="OfferCallingCard"
persist="true"
type="notify">
[FIRST] [LAST] is offering their calling card.
[NAME] is offering their calling card.
This will add a bookmark in your inventory so you can quickly IM this Resident.
<form name="form">
<button

View File

@ -79,6 +79,7 @@
</radio_group>
<check_box
control_name="AllowMultipleViewers"
follows="top|left"
height="15"
label="Allow Multiple Viewer"
@ -88,6 +89,7 @@
top_pad="20"
width="237"/>
<check_box
control_name="ForceShowGrid"
follows="top|left"
height="15"
label="Show Grid Selection at login"
@ -97,6 +99,7 @@
top_pad="5"
width="237"/>
<check_box
control_name="UseDebugMenus"
follows="top|left"
height="15"
label="Show Advanced Menu"
@ -106,6 +109,7 @@
top_pad="5"
width="237"/>
<check_box
control_name="QAMode"
follows="top|left"
height="15"
label="Show Developer Menu"

View File

@ -113,22 +113,22 @@
</text>
<color_swatch
can_apply_immediately="true"
color="LtGray"
color="EmphasisColor_35"
follows="left|top"
height="24"
label_height="0"
label_width="60"
layout="topleft"
left="360"
name="im"
name="objects"
top_pad="-15"
width="44">
<color_swatch.init_callback
function="Pref.getUIColor"
parameter="IMChatColor" />
parameter="ObjectChatColor" />
<color_swatch.commit_callback
function="Pref.applyUIColor"
parameter="IMChatColor" />
parameter="ObjectChatColor" />
</color_swatch>
<text
type="string"
@ -141,7 +141,7 @@
name="text_box3"
top_delta="5"
width="95">
IM
Objects
</text>
<color_swatch
can_apply_immediately="true"
@ -206,37 +206,6 @@
width="95">
Errors
</text>
<color_swatch
can_apply_immediately="true"
color="EmphasisColor_35"
follows="left|top"
height="24"
label_height="0"
layout="topleft"
left="360"
name="objects"
top_pad="-15"
width="44" >
<color_swatch.init_callback
function="Pref.getUIColor"
parameter="ObjectChatColor" />
<color_swatch.commit_callback
function="Pref.applyUIColor"
parameter="ObjectChatColor" />
</color_swatch>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_pad="5"
mouse_opaque="false"
name="text_box6"
top_delta="5"
width="95">
Objects
</text>
<color_swatch
can_apply_immediately="true"
color="LtYellow"
@ -305,7 +274,7 @@
left="30"
height="12"
name="bubble_chat"
top_pad="28"
top_pad="20"
width="120"
>
Bubble chat:
@ -336,11 +305,58 @@
height="16"
increment="0.05"
initial_value="1"
label="Opacity"
label="Opacity:"
layout="topleft"
left_pad="15"
label_width="56"
left_pad="10"
label_width="70"
name="bubble_chat_opacity"
top_delta = "6"
width="347" />
width="378" />
<text
follows="left|top"
layout="topleft"
left="30"
height="12"
name="bubble_chat"
top_pad="15"
width="120"
>
Floater Opacity:
</text>
<slider
can_edit_text="false"
control_name="ActiveFloaterTransparency"
decimal_digits="2"
follows="left|top"
height="16"
increment="0.01"
initial_value="0.8"
layout="topleft"
label_width="115"
label="Active :"
left="50"
max_val="1.00"
min_val="0.00"
name="active"
show_text="true"
top_pad="5"
width="415" />
<slider
can_edit_text="false"
control_name="InactiveFloaterTransparency"
decimal_digits="2"
follows="left|top"
height="16"
increment="0.01"
initial_value="0.5"
layout="topleft"
label_width="115"
label="Inctive :"
left="50"
max_val="1.00"
min_val="0.00"
name="active"
show_text="true"
top_pad="5"
width="415" />
</panel>

View File

@ -177,7 +177,10 @@
left_delta="0"
name="double_click_chkbox"
width="237"
top_pad="0"/>
top_pad="0">
<check_box.commit_callback
function="Pref.CommitDoubleClickChekbox"/>
</check_box>
<radio_group
height="20"
layout="topleft"
@ -191,7 +194,6 @@
left="0"
name="radio_teleport"
top_delta="20"
value="0"
width="100" />
<radio_item
height="16"
@ -200,7 +202,19 @@
layout="topleft"
name="radio_autopilot"
top_delta="0"
value="1"
width="75" />
<radio_group.commit_callback
function="Pref.CommitRadioDoubleClick"/>
</radio_group>
</panel>
<button
height="23"
label="Other Devices"
left="30"
name="joystick_setup_button"
top="30"
width="155">
<button.commit_callback
function="Floater.Show"
parameter="pref_joystick" />
</button>
</panel>

View File

@ -114,16 +114,17 @@
name="show_timestamps_check_im"
top_pad="10"
width="237" />
<check_box
enabled="false"
<check_box
control_name="LogFileNamewithDate"
enabled="false"
height="16"
label="Add datestamp to log file name"
label="Add datestamp to log file name."
layout="topleft"
left_delta="0"
name="show_datestamps_check_im"
left_detla="5"
name="logfile_name_datestamp"
top_pad="10"
width="237" />
<text
width="350"/>
<text
type="string"
length="1"
follows="left|top"

View File

@ -179,4 +179,13 @@
right="487"
name="Save_btn"
width="81" />
<button
follows="right|bottom"
height="23"
label="Edit..."
layout="topleft"
top_pad="-23"
right="400"
name="Edit_btn"
width="81" />
</panel>

View File

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<multi_floater name="im_floater" title="Mensaje Instantáneo">
<string name="only_user_message">
Eres el único Residente en esta sesión.
</string>
<string name="offline_message">
[FIRST] [LAST] no está conectado.
</string>
<string name="invite_message">
Pulse el botón [BUTTON NAME] para aceptar/conectar este chat de voz.
</string>
<string name="muted_message">
Has ignorado a este Residente. Enviándole un mensaje, automáticamente dejarás de ignorarle.
</string>
<string name="generic_request_error">
Error al hacer lo solicitado; por favor, inténtelo más tarde.
</string>
<string name="insufficient_perms_error">
Usted no tiene permisos suficientes.
</string>
<string name="session_does_not_exist_error">
La sesión ya acabó
</string>
<string name="no_ability_error">
Usted no tiene esa capacidad.
</string>
<string name="not_a_mod_error">
Usted no es un moderador de la sesión.
</string>
<string name="muted_error">
Un moderador del grupo le ha desactivado el chat de texto.
</string>
<string name="add_session_event">
No es posible añadir Residentes a la sesión de chat con [RECIPIENT].
</string>
<string name="message_session_event">
No se ha podido enviar su mensaje a la sesión de chat con [RECIPIENT].
</string>
<string name="removed_from_group">
Ha sido eliminado del grupo.
</string>
<string name="close_on_no_ability">
Usted ya no tendrá más la capacidad de estar en la sesión de chat.
</string>
</multi_floater>

View File

@ -2469,7 +2469,7 @@ Por favor, vuelve a intentarlo en unos momentos.
Rehusado el ofrecimiento de amistad.
</notification>
<notification name="OfferCallingCard">
[FIRST] [LAST] te está ofreciendo su tarjeta de visita.
[NAME] te está ofreciendo su tarjeta de visita.
Esto añadirá un marcador en tu inventario para que puedas enviarle rápidamente un MI.
<form name="form">
<button name="Accept" text="Aceptar"/>

View File

@ -3,7 +3,7 @@
<menu_item_call label="Voir le profil" name="view_profile"/>
<menu_item_call label="Devenir amis" name="add_friend"/>
<menu_item_call label="IM" name="im"/>
<menu_item_call label="Appeler" name="call"/>
<menu_item_call label="Appel" name="call"/>
<menu_item_call label="Téléporter" name="teleport"/>
<menu_item_call label="Inviter dans le groupe" name="invite_to_group"/>
<menu_item_call label="Ignorer" name="block"/>

View File

@ -2464,7 +2464,7 @@ Veuillez réessayer dans quelques minutes.
Amitié refusée.
</notification>
<notification name="OfferCallingCard">
[FIRST] [LAST] vous offre sa carte de visite.
[NAME] vous offre sa carte de visite.
Cela ajoute un marque-page dans votre inventaire, ce qui vous permet d&apos;envoyer rapidement un IM à ce résident.
<form name="form">
<button name="Accept" text="Accepter"/>

View File

@ -54,7 +54,7 @@
<text name="my_account_link" value="[[URL] Accéder à ma Page d&apos;accueil]"/>
<text name="title_partner_text" value="Mon partenaire :"/>
<panel name="partner_data_panel">
<text initial_value="(récupération en cours)" name="partner_text" value="[FIRST] [LAST]"/>
<text initial_value="(récupération en cours)" name="partner_text"/>
</panel>
<text name="partner_edit_link" value="[[URL] Modifier]"/>
</panel>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Choses" name="main inventory panel">
<panel.string name="ItemcountFetching">
Récupération de [ITEM_COUNT] articles... [FILTER]
Récupération : [ITEM_COUNT] articles... [FILTER]
</panel.string>
<panel.string name="ItemcountCompleted">
[ITEM_COUNT] articles [FILTER]

View File

@ -1089,7 +1089,7 @@
<string name="Textures" value=" Textures,"/>
<string name="Snapshots" value=" Photos,"/>
<string name="No Filters" value="Non "/>
<string name="Since Logoff" value=" - Depuis la déconnexion"/>
<string name="Since Logoff" value=" depuis la déconnexion"/>
<string name="InvFolder My Inventory">
Mon inventaire
</string>

View File

@ -4,19 +4,19 @@
Nessuno rilevato
</floater.string>
<floater.string name="bump">
[TIME] [FIRST] [LAST] ti ha urtato
[TIME] [NAME] ti ha urtato
</floater.string>
<floater.string name="llpushobject">
[TIME] [FIRST] [LAST] ti ha spinto per mezzo di uno script
[TIME] [NAME] ti ha spinto per mezzo di uno script
</floater.string>
<floater.string name="selected_object_collide">
[TIME] [FIRST] [LAST] ti ha colpito con un oggetto
[TIME] [NAME] ti ha colpito con un oggetto
</floater.string>
<floater.string name="scripted_object_collide">
[TIME] [FIRST] [LAST] ti ha colpito con un oggetto scriptato
[TIME] [NAME] ti ha colpito con un oggetto scriptato
</floater.string>
<floater.string name="physical_object_collide">
[TIME] [FIRST] [LAST] ti ha colpito con un oggetto fisico
[TIME] [NAME] ti ha colpito con un oggetto fisico
</floater.string>
<floater.string name="timeStr">
[[hour,datetime,slt]:[min,datetime,slt]]

View File

@ -11,7 +11,7 @@
</text>
<icon name="icon_person" tool_tip="Persona"/>
<text left="115" name="payee_name">
[FIRST] [LAST]
Test Name That Is Extremely Long To Check Clipping
</text>
<button label="1 L$" label_selected="1 L$" left="118" name="fastpay 1" width="80"/>
<button label="5 L$" label_selected="5 L$" left="210" name="fastpay 5"/>

View File

@ -8,7 +8,7 @@
</string>
<icon name="icon_person" tool_tip="Persona"/>
<text left="120" name="payee_name">
[FIRST] [LAST]
Ericacita Moostopolison
</text>
<text halign="left" left="5" name="object_name_label" width="110">
Mediante l&apos;oggetto:

View File

@ -2035,10 +2035,10 @@ Inseriscilo in una pagina web per dare ad altri un accesso facile a questa ubica
Oggetto: [SUBJECT], Messaggio: [MESSAGE]
</notification>
<notification name="FriendOnline">
[FIRST] [LAST] è Online
[NAME] è Online
</notification>
<notification name="FriendOffline">
[FIRST] [LAST] è Offline
[NAME] è Offline
</notification>
<notification name="AddSelfFriend">
Anche se sei molto simpatico, non puoi aggiungere te stesso all&apos;elenco degli amici.
@ -2105,9 +2105,6 @@ Questo potrebbe incidere sulla tua password.
<notification name="CannotRemoveProtectedCategories">
Non è possibile rimuovere le categorie protette.
</notification>
<notification name="OfferedCard">
Hai offerto un biglietto da visita a [FIRST] [LAST]
</notification>
<notification name="UnableToBuyWhileDownloading">
Impossibile acquistare l&apos;oggetto durante il download dei dati.
Riprova.
@ -2223,7 +2220,7 @@ Reinstalla il plugin o contatta il venditore se continui ad avere questi problem
Gli oggetti che possiedi sul terreno selezionato ti sono stati restituiti nell&apos;inventario.
</notification>
<notification name="OtherObjectsReturned">
Gli oggetti selezionati sul terreno che è di proprietà di [FIRST] [LAST] sono stati restituiti nel suo inventario.
Gli oggetti selezionati sul terreno che è di proprietà di [NAME] sono stati restituiti nel suo inventario.
</notification>
<notification name="OtherObjectsReturned2">
Sono stati restituiti al proprietario gli oggetti selezionati sul lotto nella terra di proprietà del residente &apos;[NAME]&apos;.
@ -2433,7 +2430,7 @@ Riprova tra qualche istante.
Offerta di amicizia rifiutata.
</notification>
<notification name="OfferCallingCard">
[FIRST] [LAST] ti offre il suo biglietto da visita.
[NAME] ti offre il suo biglietto da visita.
Questo sarà aggiunto nel tuo inventario come segnalibro per consentirti di inviare rapidamente messaggi IM a questo residente.
<form name="form">
<button name="Accept" text="Accetta"/>
@ -2493,7 +2490,7 @@ Concedi questa richiesta?
</form>
</notification>
<notification name="ScriptDialog">
[FIRST] [LAST] &apos;[TITLE]&apos;
[NAME] &apos;&lt;nolink&gt;[TITLE]&lt;/nolink&gt;&apos;
[MESSAGE]
<form name="form">
<button name="Ignore" text="Ignora"/>
@ -2537,13 +2534,13 @@ Clicca su Accetta per unirti alla chiamata oppure su Declina to declinare l&apos
</form>
</notification>
<notification name="AutoUnmuteByIM">
[FIRST] [LAST] ha ricevuto un IM ed è stato automaticamente sbloccato.
[NAME] ha ricevuto un IM ed è stato automaticamente sbloccato.
</notification>
<notification name="AutoUnmuteByMoney">
[FIRST] [LAST] ha ricevuto del denaro e pertanto è stato automaticamente sbloccato.
[NAME] ha ricevuto del denaro e pertanto è stato automaticamente sbloccato.
</notification>
<notification name="AutoUnmuteByInventory">
A [FIRST] [LAST] è stato offerto un elemento dell&apos;Inventario e pertanto è stato automaticamente sbloccato.
A [NAME] è stato offerto un elemento dell&apos;Inventario e pertanto è stato automaticamente sbloccato.
</notification>
<notification name="VoiceInviteGroup">
[NAME] si è aggiunto alla chiamata in chat vocale con il gruppo [GROUP].

View File

@ -3478,7 +3478,7 @@ Se il messaggio persiste, contatta [SUPPORT_SITE].
Sei l&apos;unico utente di questa sessione.
</string>
<string name="offline_message">
[FIRST] [LAST] è offline.
[NAME] è offline.
</string>
<string name="invite_message">
Clicca il tasto [BUTTON NAME] per accettare/connetterti a questa voice chat.

View File

@ -4,19 +4,19 @@
検出なし
</floater.string>
<floater.string name="bump">
[TIME] [FIRST] [LAST]が、あなたにぶつかりました。
[TIME] [NAME]が、あなたにぶつかりました。
</floater.string>
<floater.string name="llpushobject">
[TIME] [FIRST] [LAST]が、スクリプトであなたをプッシュしました。
[TIME] [NAME]が、スクリプトであなたをプッシュしました。
</floater.string>
<floater.string name="selected_object_collide">
[TIME] [FIRST] [LAST]が、オブジェクトをあなたに当てました。
[TIME] [NAME]が、オブジェクトをあなたに当てました。
</floater.string>
<floater.string name="scripted_object_collide">
[TIME] [FIRST] [LAST]が、スクリプト・オブジェクトをあなたに当てました。
[TIME] [NAME]が、スクリプト・オブジェクトをあなたに当てました。
</floater.string>
<floater.string name="physical_object_collide">
[TIME] [FIRST] [LAST]が、物理オブジェクトをあなたに当てました。
[TIME] [NAME]が、物理オブジェクトをあなたに当てました。
</floater.string>
<floater.string name="timeStr">
[[hour,datetime,slt]:[min,datetime,slt]]

View File

@ -11,7 +11,7 @@
</text>
<icon name="icon_person" tool_tip="住人"/>
<text name="payee_name">
[FIRST] [LAST]
Test Name That Is Extremely Long To Check Clipping
</text>
<button label="L$1" label_selected="L$1" name="fastpay 1"/>
<button label="L$5" label_selected="L$5" name="fastpay 5"/>

View File

@ -8,7 +8,7 @@
</string>
<icon name="icon_person" tool_tip="住人"/>
<text name="payee_name">
[FIRST] [LAST]
Ericacita Moostopolison
</text>
<text name="object_name_label">
オブジェクトを介して:

View File

@ -2082,10 +2082,10 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
件名: [SUBJECT]、メッセージ: [MESSAGE]
</notification>
<notification name="FriendOnline">
[FIRST] [LAST] はオンラインです
[NAME] はオンラインです
</notification>
<notification name="FriendOffline">
[FIRST] [LAST] はオフラインです
[NAME] はオフラインです
</notification>
<notification name="AddSelfFriend">
残念ながら自分自身をフレンド登録することはできません。
@ -2153,9 +2153,6 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
<notification name="CannotRemoveProtectedCategories">
保護されたカテゴリは削除できません。
</notification>
<notification name="OfferedCard">
[FIRST] [LAST] にコーリングカードを送りました。
</notification>
<notification name="UnableToBuyWhileDownloading">
オブジェクトデータのダウンロード中は購入できません。
もう一度お試しください。
@ -2273,7 +2270,7 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
</notification>
<notification name="OtherObjectsReturned">
選択した土地の区画上にあった
[FIRST] [LAST]
[NAME]
が所有するオブジェクトは、すべて所有者の「持ち物」に返却されました。
</notification>
<notification name="OtherObjectsReturned2">
@ -2488,7 +2485,7 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
フレンドの登録依頼が拒否されました。
</notification>
<notification name="OfferCallingCard">
[FIRST] [LAST] がコーリングカードを渡そうとしています。
[NAME] がコーリングカードを渡そうとしています。
あなたの「持ち物」にブックマークが追加され、この住人に素早く IM を送ることができます。
<form name="form">
<button name="Accept" text="受け入れる"/>
@ -2548,7 +2545,7 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
</form>
</notification>
<notification name="ScriptDialog">
[FIRST] [LAST] の「 [TITLE]
[NAME] の「 &lt;nolink&gt;[TITLE]&lt;/nolink&gt;
[MESSAGE]
<form name="form">
<button name="Ignore" text="無視する"/>
@ -2592,13 +2589,13 @@ M キーを押して変更します。
</form>
</notification>
<notification name="AutoUnmuteByIM">
[FIRST] [LAST] はインスタントメッセージを受け取り、自動的にブロックが解除されました。
[NAME] はインスタントメッセージを受け取り、自動的にブロックが解除されました。
</notification>
<notification name="AutoUnmuteByMoney">
[FIRST] [LAST] はお金を受け取り、自動的にブロックが解除されました。
[NAME] はお金を受け取り、自動的にブロックが解除されました。
</notification>
<notification name="AutoUnmuteByInventory">
[FIRST] [LAST] はアイテムを受け取り、自動的にブロックが解除されました。
[NAME] はアイテムを受け取り、自動的にブロックが解除されました。
</notification>
<notification name="VoiceInviteGroup">
[NAME] は [GROUP] のボイスチャットコールに参加しました。

View File

@ -46,7 +46,7 @@
<text name="my_account_link" value="[[URL] マイアカウントに移動]"/>
<text name="title_partner_text" value="マイパートナー:"/>
<panel name="partner_data_panel">
<name_box initial_value="(取得中)" name="partner_text" value="[FIRST] [LAST]"/>
<name_box initial_value="(取得中)" name="partner_text"/>
</panel>
<text name="partner_edit_link" value="[[URL] 編集]" width="100"/>
</panel>

View File

@ -3574,7 +3574,7 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
このセッションにいるユーザーはあなただけです。
</string>
<string name="offline_message">
[FIRST] [LAST] はオフラインです。
[NAME] はオフラインです。
</string>
<string name="invite_message">
このボイスチャットに応答・接続する場合は、[BUTTON NAME] をクリックしてください。

View File

@ -4,18 +4,18 @@
Geen gedetecteerd
</string>
<string name="bump">
[TIME] [FIRST] [LAST] botste tegen u aan
[TIME] [NAME] botste tegen u aan
</string>
<string name="llpushobject">
[TIME] [FIRST] [LAST] duwde u met een script
[TIME] [NAME] duwde u met een script
</string>
<string name="selected_object_collide">
[TIME] [FIRST] [LAST] raakte u met een object
[TIME] [NAME] raakte u met een object
</string>
<string name="scripted_object_collide">
[TIME] [FIRST] [LAST] raakte u met een gescript object
[TIME] [NAME] raakte u met een gescript object
</string>
<string name="physical_object_collide">
[TIME] [FIRST] [LAST] raakte u met een fysiek object
[TIME] [NAME] raakte u met een fysiek object
</string>
</floater>

View File

@ -10,7 +10,7 @@
Betaal inwoner:
</text>
<text name="payee_name" left="110">
[FIRST] [LAST]
Test Name That Is Extremely Long To Check Clipping
</text>
<text name="fastpay text">
Snel betalen:

View File

@ -7,7 +7,7 @@
Betaal inwoner:
</text>
<text name="payee_name" left="100" width="200">
[FIRST] [LAST]
Ericacita Moostopolison
</text>
<text name="object_name_label" left="5" width="90" halign="left">
Via object:

Some files were not shown because too many files have changed in this diff Show More