diff options
Diffstat (limited to 'indra/newview/llpreviewscript.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/newview/llpreviewscript.cpp | 817 |
1 files changed, 552 insertions, 265 deletions
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index ac7abf1448..7feb20332b 100644..100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -2,31 +2,25 @@ * @file llpreviewscript.cpp * @brief LLPreviewScript class implementation * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * 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 + * Copyright (C) 2010, Linden Research, Inc. * - * 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 + * 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. * - * 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. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -40,27 +34,30 @@ #include "llcheckboxctrl.h" #include "llcombobox.h" #include "lldir.h" +#include "llenvmanager.h" +#include "llexternaleditor.h" +#include "llfilepicker.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" #include "llscrollbar.h" #include "llscrollcontainer.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" #include "llscrolllistcell.h" +#include "llsdserialize.h" #include "llslider.h" #include "lscript_rt_interface.h" -#include "lscript_export.h" -#include "lltextbox.h" #include "lltooldraganddrop.h" #include "llvfile.h" #include "llagent.h" -#include "llnotify.h" #include "llmenugl.h" #include "roles_constants.h" #include "llselectmgr.h" @@ -72,6 +69,7 @@ #include "llkeyboard.h" #include "llscrollcontainer.h" #include "llcheckboxctrl.h" +#include "llscripteditor.h" #include "llselectmgr.h" #include "lltooldraganddrop.h" #include "llscrolllistctrl.h" @@ -79,9 +77,7 @@ #include "llslider.h" #include "lldir.h" #include "llcombobox.h" -//#include "llfloaterchat.h" #include "llviewerstats.h" -#include "llviewertexteditor.h" #include "llviewerwindow.h" #include "lluictrlfactory.h" #include "llmediactrl.h" @@ -89,7 +85,7 @@ #include "lltrans.h" #include "llviewercontrol.h" #include "llappviewer.h" -#include "llpanelinventory.h" +#include "llfloatergotoline.h" const std::string HELLO_LSL = "default\n" @@ -110,9 +106,6 @@ const std::string DEFAULT_SCRIPT_NAME = "New Script"; // *TODO:Translate? const std::string DEFAULT_SCRIPT_DESC = "(No Description)"; // *TODO:Translate? // Description and header information - -const S32 MAX_EXPORT_SIZE = 1000; - const S32 MAX_HISTORY_COUNT = 10; const F32 LIVE_HELP_REFRESH_TIME = 1.f; @@ -123,6 +116,50 @@ static bool have_script_upload_cap(LLUUID& object_id) } /// --------------------------------------------------------------------------- +/// LLLiveLSLFile +/// --------------------------------------------------------------------------- +class LLLiveLSLFile : public LLLiveFile +{ +public: + typedef boost::function<bool (const std::string& filename)> change_callback_t; + + LLLiveLSLFile(std::string file_path, change_callback_t change_cb); + ~LLLiveLSLFile(); + + void ignoreNextUpdate() { mIgnoreNextUpdate = true; } + +protected: + /*virtual*/ bool loadFile(); + + change_callback_t mOnChangeCallback; + bool mIgnoreNextUpdate; +}; + +LLLiveLSLFile::LLLiveLSLFile(std::string file_path, change_callback_t change_cb) +: mOnChangeCallback(change_cb) +, mIgnoreNextUpdate(false) +, LLLiveFile(file_path, 1.0) +{ + llassert(mOnChangeCallback); +} + +LLLiveLSLFile::~LLLiveLSLFile() +{ + LLFile::remove(filename()); +} + +bool LLLiveLSLFile::loadFile() +{ + if (mIgnoreNextUpdate) + { + mIgnoreNextUpdate = false; + return true; + } + + return mOnChangeCallback(filename()); +} + +/// --------------------------------------------------------------------------- /// LLFloaterScriptSearch /// --------------------------------------------------------------------------- class LLFloaterScriptSearch : public LLFloater @@ -145,20 +182,29 @@ public: LLScriptEdCore* getEditorCore() { return mEditorCore; } static LLFloaterScriptSearch* getInstance() { return sInstance; } + virtual bool hasAccelerators() const; + virtual BOOL handleKeyHere(KEY key, MASK mask); + private: LLScriptEdCore* mEditorCore; - static LLFloaterScriptSearch* sInstance; + +protected: + LLLineEditor* mSearchBox; + LLLineEditor* mReplaceBox; + void onSearchBoxCommit(); }; LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL; LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core) : LLFloater(LLSD()), + mSearchBox(NULL), + mReplaceBox(NULL), mEditorCore(editor_core) { - LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_search.xml", NULL); + buildFromFile("floater_script_search.xml"); sInstance = this; @@ -178,6 +224,10 @@ LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core) BOOL LLFloaterScriptSearch::postBuild() { + mReplaceBox = getChild<LLLineEditor>("replace_text"); + mSearchBox = getChild<LLLineEditor>("search_text"); + mSearchBox->setCommitCallback(boost::bind(&LLFloaterScriptSearch::onSearchBoxCommit, this)); + mSearchBox->setCommitOnFocusLost(FALSE); childSetAction("search_btn", onBtnSearch,this); childSetAction("replace_btn", onBtnReplace,this); childSetAction("replace_all_btn", onBtnReplaceAll,this); @@ -190,8 +240,12 @@ BOOL LLFloaterScriptSearch::postBuild() //static void LLFloaterScriptSearch::show(LLScriptEdCore* editor_core) { + LLSD::String search_text; + LLSD::String replace_text; if (sInstance && sInstance->mEditorCore && sInstance->mEditorCore != editor_core) { + search_text=sInstance->mSearchBox->getValue().asString(); + replace_text=sInstance->mReplaceBox->getValue().asString(); sInstance->closeFloater(); delete sInstance; } @@ -200,6 +254,8 @@ void LLFloaterScriptSearch::show(LLScriptEdCore* editor_core) { // sInstance will be assigned in the constructor. new LLFloaterScriptSearch(editor_core); + sInstance->mSearchBox->setValue(search_text); + sInstance->mReplaceBox->setValue(replace_text); } sInstance->openFloater(); @@ -220,7 +276,7 @@ void LLFloaterScriptSearch::onBtnSearch(void *userdata) void LLFloaterScriptSearch::handleBtnSearch() { LLCheckBoxCtrl* caseChk = getChild<LLCheckBoxCtrl>("case_text"); - mEditorCore->mEditor->selectNext(childGetText("search_text"), caseChk->get()); + mEditorCore->mEditor->selectNext(mSearchBox->getValue().asString(), caseChk->get()); } // static @@ -233,7 +289,7 @@ void LLFloaterScriptSearch::onBtnReplace(void *userdata) void LLFloaterScriptSearch::handleBtnReplace() { LLCheckBoxCtrl* caseChk = getChild<LLCheckBoxCtrl>("case_text"); - mEditorCore->mEditor->replaceText(childGetText("search_text"), childGetText("replace_text"), caseChk->get()); + mEditorCore->mEditor->replaceText(mSearchBox->getValue().asString(), mReplaceBox->getValue().asString(), caseChk->get()); } // static @@ -246,10 +302,40 @@ void LLFloaterScriptSearch::onBtnReplaceAll(void *userdata) void LLFloaterScriptSearch::handleBtnReplaceAll() { LLCheckBoxCtrl* caseChk = getChild<LLCheckBoxCtrl>("case_text"); - mEditorCore->mEditor->replaceTextAll(childGetText("search_text"), childGetText("replace_text"), caseChk->get()); + mEditorCore->mEditor->replaceTextAll(mSearchBox->getValue().asString(), mReplaceBox->getValue().asString(), caseChk->get()); +} + +bool LLFloaterScriptSearch::hasAccelerators() const +{ + if (mEditorCore) + { + return mEditorCore->hasAccelerators(); + } + return FALSE; } +BOOL LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask) +{ + if (mEditorCore) + { + BOOL handled = mEditorCore->handleKeyHere(key, mask); + if (!handled) + { + LLFloater::handleKeyHere(key, mask); + } + } + + return FALSE; +} +void LLFloaterScriptSearch::onSearchBoxCommit() +{ + if (mEditorCore && mEditorCore->mEditor) + { + LLCheckBoxCtrl* caseChk = getChild<LLCheckBoxCtrl>("case_text"); + mEditorCore->mEditor->selectNext(mSearchBox->getValue().asString(), caseChk->get()); + } +} /// --------------------------------------------------------------------------- /// LLScriptEdCore @@ -264,12 +350,14 @@ struct LLSECKeywordCompare }; LLScriptEdCore::LLScriptEdCore( + LLScriptEdContainer* container, const std::string& sample, const LLHandle<LLFloater>& floater_handle, void (*load_callback)(void*), void (*save_callback)(void*, BOOL), void (*search_replace_callback) (void* userdata), void* userdata, + bool live, S32 bottom_pad) : LLPanel(), @@ -283,12 +371,16 @@ LLScriptEdCore::LLScriptEdCore( mLastHelpToken(NULL), mLiveHelpHistorySize(0), mEnableSave(FALSE), + mLiveFile(NULL), + mLive(live), + mContainer(container), mHasScriptData(FALSE) { setFollowsAll(); setBorderVisible(FALSE); setXMLFilename("panel_script_ed.xml"); + llassert_always(mContainer != NULL); } LLScriptEdCore::~LLScriptEdCore() @@ -302,68 +394,54 @@ LLScriptEdCore::~LLScriptEdCore() script_search->closeFloater(); delete script_search; } + + delete mLiveFile; + if (mSyntaxIDConnection.connected()) + { + mSyntaxIDConnection.disconnect(); + } } BOOL LLScriptEdCore::postBuild() { mErrorList = getChild<LLScrollListCtrl>("lsl errors"); - mFunctions = getChild<LLComboBox>( "Insert..."); + mFunctions = getChild<LLComboBox>("Insert..."); childSetCommitCallback("Insert...", &LLScriptEdCore::onBtnInsertFunction, this); - mEditor = getChild<LLViewerTextEditor>("Script Editor"); + mEditor = getChild<LLScriptEditor>("Script Editor"); childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this); childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,FALSE)); + childSetAction("Edit_btn", boost::bind(&LLScriptEdCore::openInExternalEditor, this)); initMenu(); + mSyntaxIDConnection = LLSyntaxIdLSL::getInstance()->addSyntaxIDCallback(boost::bind(&LLScriptEdCore::processKeywords, this)); - std::vector<std::string> funcs; - std::vector<std::string> tooltips; - for (std::vector<LLScriptLibraryFunction>::const_iterator i = gScriptLibrary.mFunctions.begin(); - i != gScriptLibrary.mFunctions.end(); ++i) - { - // Make sure this isn't a god only function, or the agent is a god. - if (!i->mGodOnly || gAgent.isGodlike()) - { - std::string name = i->mName; - funcs.push_back(name); - - std::string desc_name = "LSLTipText_"; - desc_name += name; - std::string desc = LLTrans::getString(desc_name); - - F32 sleep_time = i->mSleepTime; - if( sleep_time ) - { - desc += "\n"; - - LLStringUtil::format_map_t args; - args["[SLEEP_TIME]"] = llformat("%.1f", sleep_time ); - desc += LLTrans::getString("LSLTipSleepTime", args); - } - - // A \n linefeed is not part of xml. Let's add one to keep all - // the tips one-per-line in strings.xml - LLStringUtil::replaceString( desc, "\\n", "\n" ); - - tooltips.push_back(desc); - } - } - - LLColor3 color(0.5f, 0.0f, 0.15f); - mEditor->loadKeywords(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keywords.ini"), funcs, tooltips, color); + // Intialise keyword highlighting for the current simulator's version of LSL + LLSyntaxIdLSL::getInstance()->initialize(); + processKeywords(); + + return TRUE; +} - std::vector<std::string> primary_keywords; - std::vector<std::string> secondary_keywords; +void LLScriptEdCore::processKeywords() +{ + LL_DEBUGS("SyntaxLSL") << "Processing keywords" << LL_ENDL; + mEditor->clearSegments(); + mEditor->initKeywords(); + mEditor->loadKeywords(); + + string_vec_t primary_keywords; + string_vec_t secondary_keywords; LLKeywordToken *token; LLKeywords::keyword_iterator_t token_it; for (token_it = mEditor->keywordsBegin(); token_it != mEditor->keywordsEnd(); ++token_it) { token = token_it->second; - if (token->getColor() == color) // Wow, what a disgusting hack. + if (token->getType() == LLKeywordToken::TT_FUNCTION) { primary_keywords.push_back( wstring_to_utf8str(token->getToken()) ); } @@ -372,24 +450,16 @@ BOOL LLScriptEdCore::postBuild() secondary_keywords.push_back( wstring_to_utf8str(token->getToken()) ); } } - - // Case-insensitive dictionary sort for primary keywords. We don't sort the secondary - // keywords. They're intelligently grouped in keywords.ini. - std::stable_sort( primary_keywords.begin(), primary_keywords.end(), LLSECKeywordCompare() ); - - for (std::vector<std::string>::const_iterator iter= primary_keywords.begin(); - iter!= primary_keywords.end(); ++iter) + for (string_vec_t::const_iterator iter = primary_keywords.begin(); + iter!= primary_keywords.end(); ++iter) { mFunctions->add(*iter); } - - for (std::vector<std::string>::const_iterator iter= secondary_keywords.begin(); - iter!= secondary_keywords.end(); ++iter) + for (string_vec_t::const_iterator iter = secondary_keywords.begin(); + iter!= secondary_keywords.end(); ++iter) { mFunctions->add(*iter); } - - return TRUE; } void LLScriptEdCore::initMenu() @@ -429,14 +499,29 @@ void LLScriptEdCore::initMenu() menuItem->setClickCallback(boost::bind(&LLTextEditor::selectAll, mEditor)); menuItem->setEnableCallback(boost::bind(&LLTextEditor::canSelectAll, mEditor)); + menuItem = getChild<LLMenuItemCallGL>("Deselect"); + menuItem->setClickCallback(boost::bind(&LLTextEditor::deselect, mEditor)); + menuItem->setEnableCallback(boost::bind(&LLTextEditor::canDeselect, mEditor)); + menuItem = getChild<LLMenuItemCallGL>("Search / Replace..."); menuItem->setClickCallback(boost::bind(&LLFloaterScriptSearch::show, this)); + menuItem = getChild<LLMenuItemCallGL>("Go to line..."); + menuItem->setClickCallback(boost::bind(&LLFloaterGotoLine::show, this)); + menuItem = getChild<LLMenuItemCallGL>("Help..."); menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnHelp, this)); menuItem = getChild<LLMenuItemCallGL>("Keyword Help..."); menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnDynamicHelp, this)); + + menuItem = getChild<LLMenuItemCallGL>("LoadFromFile"); + menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnLoadFromFile, this)); + menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::enableLoadFromFileMenu, this)); + + menuItem = getChild<LLMenuItemCallGL>("SaveToFile"); + menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnSaveToFile, this)); + menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::enableSaveToFileMenu, this)); } void LLScriptEdCore::setScriptText(const std::string& text, BOOL is_valid) @@ -448,17 +533,90 @@ void LLScriptEdCore::setScriptText(const std::string& text, BOOL is_valid) } } +bool LLScriptEdCore::loadScriptText(const std::string& filename) +{ + if (filename.empty()) + { + LL_WARNS() << "Empty file name" << LL_ENDL; + return false; + } + + LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ + if (!file) + { + LL_WARNS() << "Error opening " << filename << LL_ENDL; + 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) + { + LL_WARNS() << "Short read" << LL_ENDL; + } + buffer[nread] = '\0'; + fclose(file); + + mEditor->setText(LLStringExplicit(buffer)); + delete[] buffer; + + return true; +} + +bool LLScriptEdCore::writeToFile(const std::string& filename) +{ + LLFILE* fp = LLFile::fopen(filename, "wb"); + if (!fp) + { + LL_WARNS() << "Unable to write to " << filename << LL_ENDL; + + LLSD row; + row["columns"][0]["value"] = "Error writing to local file. Is your hard drive full?"; + row["columns"][0]["font"] = "SANSSERIF_SMALL"; + mErrorList->addElement(row); + return false; + } + + std::string utf8text = 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; +} + +void LLScriptEdCore::sync() +{ + // Sync with external editor. + std::string tmp_file = mContainer->getTmpFileName(); + llstat s; + if (LLFile::stat(tmp_file, &s) == 0) // file exists + { + if (mLiveFile) mLiveFile->ignoreNextUpdate(); + writeToFile(tmp_file); + } +} + bool LLScriptEdCore::hasChanged() { if (!mEditor) return false; - return !mEditor->isPristine(); + return ((!mEditor->isPristine() || mEnableSave) && mHasScriptData); } void LLScriptEdCore::draw() { BOOL script_changed = hasChanged(); - childSetEnabled("Save_btn", script_changed); + getChildView("Save_btn")->setEnabled(script_changed); if( mEditor->hasFocus() ) { @@ -470,11 +628,11 @@ void LLScriptEdCore::draw() args["[LINE]"] = llformat ("%d", line); args["[COLUMN]"] = llformat ("%d", column); cursor_pos = LLTrans::getString("CursorPos", args); - childSetText("line_col", cursor_pos); + getChild<LLUICtrl>("line_col")->setValue(cursor_pos); } else { - childSetText("line_col", LLStringUtil::null); + getChild<LLUICtrl>("line_col")->setValue(LLStringUtil::null); } updateDynamicHelp(); @@ -502,12 +660,13 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) LLTextSegmentPtr segment = NULL; std::vector<LLTextSegmentPtr> selected_segments; mEditor->getSelectedSegments(selected_segments); - + LLKeywordToken* token; // try segments in selection range first std::vector<LLTextSegmentPtr>::iterator segment_iter; for (segment_iter = selected_segments.begin(); segment_iter != selected_segments.end(); ++segment_iter) { - if((*segment_iter)->getToken() && (*segment_iter)->getToken()->getType() == LLKeywordToken::WORD) + token = (*segment_iter)->getToken(); + if(token && isKeyword(token)) { segment = *segment_iter; break; @@ -518,7 +677,8 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) if (!segment) { const LLTextSegmentPtr test_segment = mEditor->getPreviousSegment(); - if(test_segment->getToken() && test_segment->getToken()->getType() == LLKeywordToken::WORD) + token = test_segment->getToken(); + if(token && isKeyword(token)) { segment = test_segment; } @@ -547,6 +707,24 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) } } +bool LLScriptEdCore::isKeyword(LLKeywordToken* token) +{ + switch(token->getType()) + { + case LLKeywordToken::TT_CONSTANT: + case LLKeywordToken::TT_CONTROL: + case LLKeywordToken::TT_EVENT: + case LLKeywordToken::TT_FUNCTION: + case LLKeywordToken::TT_SECTION: + case LLKeywordToken::TT_TYPE: + case LLKeywordToken::TT_WORD: + return true; + + default: + return false; + } +} + void LLScriptEdCore::setHelpPage(const std::string& help_string) { LLFloater* help_floater = mLiveHelpHandle.get(); @@ -619,14 +797,20 @@ BOOL LLScriptEdCore::canClose() else { // Bring up view-modal dialog: Save changes? Yes, No, Cancel - LLNotifications::instance().add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleSaveChangesDialog, this, _1, _2)); + LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleSaveChangesDialog, this, _1, _2)); return FALSE; } } +void LLScriptEdCore::setEnableEditing(bool enable) +{ + mEditor->setEnabled(enable); + getChildView("Edit_btn")->setEnabled(enable); +} + bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLSD& response ) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); switch( option ) { case 0: // "Yes" @@ -661,11 +845,13 @@ void LLScriptEdCore::onBtnDynamicHelp() if (!live_help_floater) { live_help_floater = new LLFloater(LLSD()); - LLUICtrlFactory::getInstance()->buildFloater(live_help_floater, "floater_lsl_guide.xml", NULL); + live_help_floater->buildFromFile("floater_lsl_guide.xml"); LLFloater* parent = dynamic_cast<LLFloater*>(getParent()); - parent->addDependentFloater(live_help_floater, TRUE); + llassert(parent); + if (parent) + parent->addDependentFloater(live_help_floater, TRUE); live_help_floater->childSetCommitCallback("lock_check", onCheckLock, this); - live_help_floater->childSetValue("lock_check", gSavedSettings.getBOOL("ScriptHelpFollowsCursor")); + live_help_floater->getChild<LLUICtrl>("lock_check")->setValue(gSavedSettings.getBOOL("ScriptHelpFollowsCursor")); live_help_floater->childSetCommitCallback("history_combo", onHelpComboCommit, this); live_help_floater->childSetAction("back_btn", onClickBack, this); live_help_floater->childSetAction("fwd_btn", onClickForward, this); @@ -786,7 +972,7 @@ void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata) void LLScriptEdCore::doSave( BOOL close_after_save ) { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_LSL_SAVE_COUNT ); + add(LLStatViewer::LSL_SAVES, 1); if( mSaveCallback ) { @@ -794,12 +980,54 @@ void LLScriptEdCore::doSave( BOOL close_after_save ) } } +void LLScriptEdCore::openInExternalEditor() +{ + delete mLiveFile; // deletes file + + // Save the script to a temporary file. + std::string filename = mContainer->getTmpFileName(); + writeToFile(filename); + + // Start watching file changes. + mLiveFile = new LLLiveLSLFile(filename, boost::bind(&LLScriptEdContainer::onExternalChange, mContainer, _1)); + mLiveFile->addToEventTimer(); + + // Open it in external editor. + { + LLExternalEditor ed; + LLExternalEditor::EErrorCode status; + std::string msg; + + status = ed.setCommand("LL_SCRIPT_EDITOR"); + if (status != LLExternalEditor::EC_SUCCESS) + { + if (status == LLExternalEditor::EC_NOT_SPECIFIED) // Use custom message for this error. + { + msg = getString("external_editor_not_set"); + } + else + { + msg = LLExternalEditor::getErrorMessage(status); + } + + LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", msg)); + return; + } + + status = ed.run(filename); + if (status != LLExternalEditor::EC_SUCCESS) + { + msg = LLExternalEditor::getErrorMessage(status); + LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", msg)); + } + } +} void LLScriptEdCore::onBtnUndoChanges() { if( !mEditor->tryToRevertToPristineState() ) { - LLNotifications::instance().add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, this, _1, _2)); + LLNotificationsUtil::add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, this, _1, _2)); } } @@ -819,8 +1047,8 @@ void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data) LLStringUtil::replaceChar(line, ',',' '); LLStringUtil::replaceChar(line, ')',' '); sscanf(line.c_str(), "%d %d", &row, &column); - //llinfos << "LLScriptEdCore::onErrorList() - " << row << ", " - //<< column << llendl; + //LL_INFOS() << "LLScriptEdCore::onErrorList() - " << row << ", " + //<< column << LL_ENDL; self->mEditor->setCursor(row, column); self->mEditor->setFocus(TRUE); } @@ -828,7 +1056,7 @@ void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data) bool LLScriptEdCore::handleReloadFromServerDialog(const LLSD& notification, const LLSD& response ) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); switch( option ) { case 0: // "Yes" @@ -867,15 +1095,15 @@ struct LLEntryAndEdCore void LLScriptEdCore::deleteBridges() { - S32 count = mBridges.count(); + S32 count = mBridges.size(); LLEntryAndEdCore* eandc; for(S32 i = 0; i < count; i++) { - eandc = mBridges.get(i); + eandc = mBridges.at(i); delete eandc; mBridges[i] = NULL; } - mBridges.reset(); + mBridges.clear(); } // virtual @@ -907,6 +1135,124 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask) return FALSE; } +void LLScriptEdCore::onBtnLoadFromFile( void* data ) +{ + LLScriptEdCore* self = (LLScriptEdCore*) data; + + // TODO Maybe add a dialogue warning here if the current file has unsaved changes. + LLFilePicker& file_picker = LLFilePicker::instance(); + if( !file_picker.getOpenFile( LLFilePicker::FFLOAD_SCRIPT ) ) + { + //File picking cancelled by user, so nothing to do. + return; + } + + std::string filename = file_picker.getFirstFile(); + + std::ifstream fin(filename.c_str()); + + std::string line; + std::string text; + std::string linetotal; + while (!fin.eof()) + { + getline(fin,line); + text += line; + if (!fin.eof()) + { + text += "\n"; + } + } + fin.close(); + + // Only replace the script if there is something to replace with. + if (text.length() > 0) + { + self->mEditor->selectAll(); + LLWString script(utf8str_to_wstring(text)); + self->mEditor->insertText(script); + } +} + +void LLScriptEdCore::onBtnSaveToFile( void* userdata ) +{ + add(LLStatViewer::LSL_SAVES, 1); + + LLScriptEdCore* self = (LLScriptEdCore*) userdata; + + if( self->mSaveCallback ) + { + LLFilePicker& file_picker = LLFilePicker::instance(); + if( file_picker.getSaveFile( LLFilePicker::FFSAVE_SCRIPT, self->mScriptName ) ) + { + std::string filename = file_picker.getFirstFile(); + std::string scriptText=self->mEditor->getText(); + std::ofstream fout(filename.c_str()); + fout<<(scriptText); + fout.close(); + self->mSaveCallback( self->mUserdata, FALSE ); + } + } +} + +bool LLScriptEdCore::canLoadOrSaveToFile( void* userdata ) +{ + LLScriptEdCore* self = (LLScriptEdCore*) userdata; + return self->mEditor->canLoadOrSaveToFile(); +} + +// static +bool LLScriptEdCore::enableSaveToFileMenu(void* userdata) +{ + LLScriptEdCore* self = (LLScriptEdCore*)userdata; + if (!self || !self->mEditor) return FALSE; + return self->mEditor->canLoadOrSaveToFile(); +} + +// static +bool LLScriptEdCore::enableLoadFromFileMenu(void* userdata) +{ + LLScriptEdCore* self = (LLScriptEdCore*)userdata; + return (self && self->mEditor) ? self->mEditor->canLoadOrSaveToFile() : FALSE; +} + +/// --------------------------------------------------------------------------- +/// LLScriptEdContainer +/// --------------------------------------------------------------------------- + +LLScriptEdContainer::LLScriptEdContainer(const LLSD& key) : + LLPreview(key) +, mScriptEd(NULL) +{ +} + +std::string LLScriptEdContainer::getTmpFileName() +{ + // Take script inventory item id (within the object inventory) + // to consideration so that it's possible to edit multiple scripts + // in the same object inventory simultaneously (STORM-781). + std::string script_id = mObjectUUID.asString() + "_" + mItemUUID.asString(); + + // Use MD5 sum to make the file name shorter and not exceed maximum path length. + char script_id_hash_str[33]; /* Flawfinder: ignore */ + LLMD5 script_id_hash((const U8 *)script_id.c_str()); + script_id_hash.hex_digest(script_id_hash_str); + + return std::string(LLFile::tmpdir()) + "sl_script_" + script_id_hash_str + ".lsl"; +} + +bool LLScriptEdContainer::onExternalChange(const std::string& filename) +{ + if (!mScriptEd->loadScriptText(filename)) + { + return false; + } + + // Disable sync to avoid recursive load->save->load calls. + saveIfNeeded(false); + return true; +} + /// --------------------------------------------------------------------------- /// LLPreviewLSL /// --------------------------------------------------------------------------- @@ -930,34 +1276,38 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata) LLPreviewLSL *self = (LLPreviewLSL*)userdata; self->mScriptEd = new LLScriptEdCore( + self, HELLO_LSL, self->getHandle(), LLPreviewLSL::onLoad, LLPreviewLSL::onSave, LLPreviewLSL::onSearchReplace, self, + false, 0); - return self->mScriptEd; } LLPreviewLSL::LLPreviewLSL(const LLSD& key ) - : LLPreview( key ), +: LLScriptEdContainer(key), mPendingUploads(0) { mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this); - //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_preview.xml", FALSE); } // virtual BOOL LLPreviewLSL::postBuild() { - const LLInventoryItem* item = getItem(); + const LLInventoryItem* item = getItem(); + llassert(item); + if (item) + { + getChild<LLUICtrl>("desc")->setValue(item->getDescription()); + } childSetCommitCallback("desc", LLPreview::onText, this); - childSetText("desc", item->getDescription()); - childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe); + getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); return LLPreview::postBuild(); } @@ -965,7 +1315,7 @@ BOOL LLPreviewLSL::postBuild() // virtual void LLPreviewLSL::callbackLSLCompileSucceeded() { - llinfos << "LSL Bytecode saved" << llendl; + LL_INFOS() << "LSL Bytecode saved" << LL_ENDL; mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); closeIfNeeded(); @@ -974,7 +1324,7 @@ void LLPreviewLSL::callbackLSLCompileSucceeded() // virtual void LLPreviewLSL::callbackLSLCompileFailed(const LLSD& compile_errors) { - llinfos << "Compile failed!" << llendl; + LL_INFOS() << "Compile failed!" << LL_ENDL; for(LLSD::array_const_iterator line = compile_errors.beginArray(); line < compile_errors.endArray(); @@ -1031,16 +1381,16 @@ void LLPreviewLSL::loadAsset() { mScriptEd->setScriptText(mScriptEd->getString("can_not_view"), FALSE); mScriptEd->mEditor->makePristine(); - mScriptEd->mEditor->setEnabled(FALSE); mScriptEd->mFunctions->setEnabled(FALSE); mAssetStatus = PREVIEW_ASSET_LOADED; } - childSetVisible("lock", !is_modifiable); - mScriptEd->childSetEnabled("Insert...", is_modifiable); + getChildView("lock")->setVisible( !is_modifiable); + mScriptEd->getChildView("Insert...")->setEnabled(is_modifiable); } else { mScriptEd->setScriptText(std::string(HELLO_LSL), TRUE); + mScriptEd->setEnableEditing(TRUE); mAssetStatus = PREVIEW_ASSET_LOADED; } } @@ -1086,11 +1436,10 @@ void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save) // Save needs to compile the text in the buffer. If the compile // succeeds, then save both assets out to the database. If the compile -// fails, go ahead and save the text anyway so that the user doesn't -// get too fucked. -void LLPreviewLSL::saveIfNeeded() +// fails, go ahead and save the text anyway. +void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/) { - // llinfos << "LLPreviewLSL::saveIfNeeded()" << llendl; + // LL_INFOS() << "LLPreviewLSL::saveIfNeeded()" << LL_ENDL; if(!mScriptEd->hasChanged()) { return; @@ -1107,23 +1456,13 @@ void LLPreviewLSL::saveIfNeeded() std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); std::string filename = filepath + ".lsl"; - LLFILE* fp = LLFile::fopen(filename, "wb"); - if(!fp) - { - llwarns << "Unable to write to " << filename << llendl; + mScriptEd->writeToFile(filename); - 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; + if (sync) + { + mScriptEd->sync(); } - std::string utf8text = mScriptEd->mEditor->getText(); - fputs(utf8text.c_str(), fp); - fclose(fp); - fp = NULL; - const LLInventoryItem *inv_item = getItem(); // save it out to asset server std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent"); @@ -1146,7 +1485,7 @@ void LLPreviewLSL::uploadAssetViaCaps(const std::string& url, const std::string& filename, const LLUUID& item_id) { - llinfos << "Update Agent Inventory via capability" << llendl; + LL_INFOS() << "Update Agent Inventory via capability" << LL_ENDL; LLSD body; body["item_id"] = item_id; body["target"] = "lsl2"; @@ -1179,7 +1518,7 @@ void LLPreviewLSL::uploadAssetLegacy(const std::string& filename, asset_id.asString().c_str(), gAgent.isGodlike())) { - llinfos << "Compile failed!" << llendl; + LL_INFOS() << "Compile failed!" << LL_ENDL; //char command[256]; //sprintf(command, "type %s\n", err_filename.c_str()); //system(command); @@ -1217,7 +1556,7 @@ void LLPreviewLSL::uploadAssetLegacy(const std::string& filename, } else { - llinfos << "Compile worked!" << llendl; + LL_INFOS() << "Compile worked!" << LL_ENDL; if(gAssetStorage) { getWindow()->incBusyCount(); @@ -1259,8 +1598,8 @@ void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 } else { - llwarns << "Inventory item for script " << info->mItemUUID - << " is no longer in agent inventory." << llendl; + LL_WARNS() << "Inventory item for script " << info->mItemUUID + << " is no longer in agent inventory." << LL_ENDL; } // Find our window and close it if requested. @@ -1279,10 +1618,10 @@ void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 } else { - llwarns << "Problem saving script: " << status << llendl; + LL_WARNS() << "Problem saving script: " << status << LL_ENDL; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("SaveScriptFailReason", args); + LLNotificationsUtil::add("SaveScriptFailReason", args); } delete info; } @@ -1317,10 +1656,10 @@ void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_d } else { - llwarns << "Problem saving LSL Bytecode (Preview)" << llendl; + LL_WARNS() << "Problem saving LSL Bytecode (Preview)" << LL_ENDL; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("SaveBytecodeFailReason", args); + LLNotificationsUtil::add("SaveBytecodeFailReason", args); } delete instance_uuid; } @@ -1329,8 +1668,8 @@ void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_d void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status) { - lldebugs << "LLPreviewLSL::onLoadComplete: got uuid " << asset_uuid - << llendl; + LL_DEBUGS() << "LLPreviewLSL::onLoadComplete: got uuid " << asset_uuid + << LL_ENDL; LLUUID* item_uuid = (LLUUID*)user_data; LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", *item_uuid); if( preview ) @@ -1355,29 +1694,27 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset { is_modifiable = TRUE; } - preview->mScriptEd->mEditor->setEnabled(is_modifiable); + preview->mScriptEd->setEnableEditing(is_modifiable); preview->mAssetStatus = PREVIEW_ASSET_LOADED; } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { - LLNotifications::instance().add("ScriptMissing"); + LLNotificationsUtil::add("ScriptMissing"); } else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) { - LLNotifications::instance().add("ScriptNoPermissions"); + LLNotificationsUtil::add("ScriptNoPermissions"); } else { - LLNotifications::instance().add("UnableToLoadScript"); + LLNotificationsUtil::add("UnableToLoadScript"); } preview->mAssetStatus = PREVIEW_ASSET_ERROR; - llwarns << "Problem loading script: " << status << llendl; + LL_WARNS() << "Problem loading script: " << status << LL_ENDL; } } delete item_uuid; @@ -1392,25 +1729,24 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset //static void* LLLiveLSLEditor::createScriptEdPanel(void* userdata) { - LLLiveLSLEditor *self = (LLLiveLSLEditor*)userdata; self->mScriptEd = new LLScriptEdCore( + self, HELLO_LSL, self->getHandle(), &LLLiveLSLEditor::onLoad, &LLLiveLSLEditor::onSave, &LLLiveLSLEditor::onSearchReplace, self, + true, 0); - return self->mScriptEd; } LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) : - LLPreview(key), - mScriptEd(NULL), + LLScriptEdContainer(key), mAskedForRunningInfo(FALSE), mHaveRunningInfo(FALSE), mCloseAfterSave(FALSE), @@ -1419,20 +1755,19 @@ LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) : mIsNew(false) { mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); - //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_live_lsleditor.xml", FALSE); } BOOL LLLiveLSLEditor::postBuild() { childSetCommitCallback("running", LLLiveLSLEditor::onRunningCheckboxClicked, this); - childSetEnabled("running", FALSE); + getChildView("running")->setEnabled(FALSE); childSetAction("Reset",&LLLiveLSLEditor::onReset,this); - childSetEnabled("Reset", TRUE); + getChildView("Reset")->setEnabled(TRUE); mMonoCheckbox = getChild<LLCheckBoxCtrl>("mono"); childSetCommitCallback("mono", &LLLiveLSLEditor::onMonoCheckboxClicked, this); - childSetEnabled("mono", FALSE); + getChildView("mono")->setEnabled(FALSE); mScriptEd->mEditor->makePristine(); mScriptEd->mEditor->setFocus(TRUE); @@ -1440,16 +1775,12 @@ BOOL LLLiveLSLEditor::postBuild() return LLPreview::postBuild(); } -LLLiveLSLEditor::~LLLiveLSLEditor() -{ -} - // virtual void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id, const LLUUID& item_id, bool is_script_running) { - lldebugs << "LSL Bytecode saved" << llendl; + LL_DEBUGS() << "LSL Bytecode saved" << LL_ENDL; mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); closeIfNeeded(); @@ -1458,7 +1789,7 @@ void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id, // virtual void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors) { - lldebugs << "Compile failed!" << llendl; + LL_DEBUGS() << "Compile failed!" << LL_ENDL; for(LLSD::array_const_iterator line = compile_errors.beginArray(); line < compile_errors.endArray(); line++) @@ -1477,7 +1808,7 @@ void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors) void LLLiveLSLEditor::loadAsset() { - //llinfos << "LLLiveLSLEditor::loadAsset()" << llendl; + //LL_INFOS() << "LLLiveLSLEditor::loadAsset()" << LL_ENDL; if(!mIsNew) { LLViewerObject* object = gObjectList.findObject(mObjectUUID); @@ -1489,7 +1820,7 @@ void LLLiveLSLEditor::loadAsset() || gAgent.isGodlike())) { mItem = new LLViewerInventoryItem(item); - //llinfos << "asset id " << mItem->getAssetUUID() << llendl; + //LL_INFOS() << "asset id " << mItem->getAssetUUID() << LL_ENDL; } if(!gAgent.isGodlike() @@ -1500,14 +1831,14 @@ void LLLiveLSLEditor::loadAsset() mItem = new LLViewerInventoryItem(item); mScriptEd->setScriptText(getString("not_allowed"), FALSE); mScriptEd->mEditor->makePristine(); - mScriptEd->mEditor->setEnabled(FALSE); mScriptEd->enableSave(FALSE); mAssetStatus = PREVIEW_ASSET_LOADED; } else if(item && mItem.notNull()) { // request the text from the object - LLUUID* user_data = new LLUUID(mItemUUID); // ^ mObjectUUID + LLSD* user_data = new LLSD(); + user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID); gAssetStorage->getInvItemAsset(object->getRegion()->getHost(), gAgent.getID(), gAgent.getSessionID(), @@ -1538,11 +1869,7 @@ void LLLiveLSLEditor::loadAsset() mIsModifiable = item && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); - if(!mIsModifiable) - { - mScriptEd->mEditor->setEnabled(FALSE); - } - + // This is commented out, because we don't completely // handle script exports yet. /* @@ -1575,7 +1902,7 @@ void LLLiveLSLEditor::loadAsset() DEFAULT_SCRIPT_NAME, DEFAULT_SCRIPT_DESC, LLSaleInfo::DEFAULT, - LLInventoryItem::II_FLAGS_NONE, + LLInventoryItemFlags::II_FLAGS_NONE, time_corrected()); mAssetStatus = PREVIEW_ASSET_LOADED; } @@ -1586,75 +1913,41 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status) { - lldebugs << "LLLiveLSLEditor::onLoadComplete: got uuid " << asset_id - << llendl; - LLUUID* xored_id = (LLUUID*)user_data; + LL_DEBUGS() << "LLLiveLSLEditor::onLoadComplete: got uuid " << asset_id + << LL_ENDL; + LLSD* floater_key = (LLSD*)user_data; - LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", *xored_id); + LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", *floater_key); if(instance ) { if( LL_ERR_NOERR == status ) { instance->loadScriptText(vfs, asset_id, type); + instance->mScriptEd->setEnableEditing(TRUE); instance->mAssetStatus = PREVIEW_ASSET_LOADED; } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { - LLNotifications::instance().add("ScriptMissing"); + LLNotificationsUtil::add("ScriptMissing"); } else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) { - LLNotifications::instance().add("ScriptNoPermissions"); + LLNotificationsUtil::add("ScriptNoPermissions"); } else { - LLNotifications::instance().add("UnableToLoadScript"); + LLNotificationsUtil::add("UnableToLoadScript"); } instance->mAssetStatus = PREVIEW_ASSET_ERROR; } } - 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; -// } -// } + delete floater_key; +} void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type) { @@ -1666,13 +1959,14 @@ void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType if (file.getLastBytesRead() != file_length || file_length <= 0) { - llwarns << "Error reading " << uuid << ":" << type << llendl; + LL_WARNS() << "Error reading " << uuid << ":" << type << LL_ENDL; } buffer[file_length] = '\0'; mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), TRUE); mScriptEd->mEditor->makePristine(); + mScriptEd->setScriptName(getItem()->getName()); } @@ -1699,7 +1993,7 @@ void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata ) else { runningCheckbox->set(!running); - LLNotifications::instance().add("CouldNotStartStopScript"); + LLNotificationsUtil::add("CouldNotStartStopScript"); } } @@ -1722,7 +2016,7 @@ void LLLiveLSLEditor::onReset(void *userdata) } else { - LLNotifications::instance().add("CouldNotStartStopScript"); + LLNotificationsUtil::add("CouldNotStartStopScript"); } } @@ -1809,21 +2103,21 @@ LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id, mItem = new LLViewerInventoryItem(item); } -void LLLiveLSLEditor::saveIfNeeded() +// virtual +void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) { - llinfos << "LLLiveLSLEditor::saveIfNeeded()" << llendl; LLViewerObject* object = gObjectList.findObject(mObjectUUID); if(!object) { - LLNotifications::instance().add("SaveScriptFailObjectNotFound"); + LLNotificationsUtil::add("SaveScriptFailObjectNotFound"); return; } - if(mItem.isNull() || !mItem->isComplete()) + if(mItem.isNull() || !mItem->isFinished()) { // $NOTE: While the error message may not be exactly correct, // it's pretty close. - LLNotifications::instance().add("SaveScriptFailObjectNotFound"); + LLNotificationsUtil::add("SaveScriptFailObjectNotFound"); return; } @@ -1861,29 +2155,12 @@ 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) - { - llwarns << "Unable to write to " << filename << llendl; + mScriptEd->writeToFile(filename); - 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; - } - 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 ) + if (sync) { - utf8text = " "; + mScriptEd->sync(); } - - fputs(utf8text.c_str(), fp); - fclose(fp); - fp = NULL; // save it out to asset server std::string url = object->getRegion()->getCapability("UpdateScriptTask"); @@ -1906,7 +2183,7 @@ void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url, const LLUUID& item_id, BOOL is_running) { - llinfos << "Update Task Inventory via capability" << llendl; + LL_INFOS() << "Update Task Inventory via capability " << url << LL_ENDL; LLSD body; body["task_id"] = task_id; body["item_id"] = item_id; @@ -1945,7 +2222,7 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, gAgent.isGodlike())) { // load the error file into the error scrolllist - llinfos << "Compile failed!" << llendl; + LL_INFOS() << "Compile failed!" << LL_ENDL; if(NULL != (fp = LLFile::fopen(err_filename, "r"))) { char buffer[MAX_STRING]; /*Flawfinder: ignore*/ @@ -1983,12 +2260,12 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, } else { - llinfos << "Compile worked!" << llendl; + LL_INFOS() << "Compile worked!" << LL_ENDL; mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessfulSaving")); if(gAssetStorage) { - llinfos << "LLLiveLSLEditor::saveAsset " - << mItem->getAssetUUID() << llendl; + LL_INFOS() << "LLLiveLSLEditor::saveAsset " + << mItem->getAssetUUID() << LL_ENDL; getWindow()->incBusyCount(); mPendingUploads++; LLLiveLSLSaveData* data = NULL; @@ -2021,14 +2298,17 @@ void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_da if (status) { - llwarns << "Unable to save text for a script." << llendl; + LL_WARNS() << "Unable to save text for a script." << LL_ENDL; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("CompileQueueSaveText", args); + LLNotificationsUtil::add("CompileQueueSaveText", args); } else { - LLLiveLSLEditor* self = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", data->mItem->getUUID()); // ^ data->mSaveObjectID + LLSD floater_key; + floater_key["taskid"] = data->mSaveObjectID; + floater_key["itemid"] = data->mItem->getUUID(); + LLLiveLSLEditor* self = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", floater_key); if (self) { self->getWindow()->decBusyCount(); @@ -2052,8 +2332,11 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use return; if(0 ==status) { - llinfos << "LSL Bytecode saved" << llendl; - LLLiveLSLEditor* self = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", data->mItem->getUUID()); // ^ data->mSaveObjectID + LL_INFOS() << "LSL Bytecode saved" << LL_ENDL; + LLSD floater_key; + floater_key["taskid"] = data->mSaveObjectID; + floater_key["itemid"] = data->mItem->getUUID(); + LLLiveLSLEditor* self = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", floater_key); if (self) { // Tell the user that the compile worked. @@ -2078,12 +2361,12 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use } else { - llinfos << "Problem saving LSL Bytecode (Live Editor)" << llendl; - llwarns << "Unable to save a compiled script." << llendl; + LL_INFOS() << "Problem saving LSL Bytecode (Live Editor)" << LL_ENDL; + LL_WARNS() << "Unable to save a compiled script." << LL_ENDL; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("CompileQueueSaveBytecode", args); + LLNotificationsUtil::add("CompileQueueSaveBytecode", args); } std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_uuid.asString()); @@ -2122,6 +2405,7 @@ void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save) self->saveIfNeeded(); } + // static void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) { @@ -2130,7 +2414,10 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) msg->getUUIDFast(_PREHASH_Script, _PREHASH_ObjectID, object_id); msg->getUUIDFast(_PREHASH_Script, _PREHASH_ItemID, item_id); - LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", item_id); // ^ object_id + LLSD floater_key; + floater_key["taskid"] = object_id; + floater_key["itemid"] = item_id; + LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", floater_key); if(instance) { instance->mHaveRunningInfo = TRUE; |