From 9e854b697a06abed2a0917fb6120445f176764f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Fri, 16 Feb 2024 19:29:51 +0100 Subject: misc: BOOL to bool --- indra/newview/llpreviewscript.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llpreviewscript.cpp') diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index aceb8539d2..b0b9e00d1b 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -2367,11 +2367,11 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) if(instance) { instance->mHaveRunningInfo = TRUE; - BOOL running; + bool running; msg->getBOOLFast(_PREHASH_Script, _PREHASH_Running, running); LLCheckBoxCtrl* runningCheckbox = instance->getChild("running"); runningCheckbox->set(running); - BOOL mono; + bool mono; msg->getBOOLFast(_PREHASH_Script, "Mono", mono); LLCheckBoxCtrl* monoCheckbox = instance->getChild("mono"); monoCheckbox->setEnabled(instance->getIsModifiable() && have_script_upload_cap(object_id)); -- cgit v1.2.3 From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/newview/llpreviewscript.cpp | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'indra/newview/llpreviewscript.cpp') diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index b0b9e00d1b..11892933d8 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -153,7 +153,7 @@ public: LLFloaterScriptSearch(LLScriptEdCore* editor_core); ~LLFloaterScriptSearch(); - /*virtual*/ BOOL postBuild(); + /*virtual*/ bool postBuild(); static void show(LLScriptEdCore* editor_core); static void onBtnSearch(void* userdata); void handleBtnSearch(); @@ -168,7 +168,7 @@ public: static LLFloaterScriptSearch* getInstance() { return sInstance; } virtual bool hasAccelerators() const; - virtual BOOL handleKeyHere(KEY key, MASK mask); + virtual bool handleKeyHere(KEY key, MASK mask); private: @@ -207,19 +207,19 @@ LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core) } } -BOOL LLFloaterScriptSearch::postBuild() +bool LLFloaterScriptSearch::postBuild() { mReplaceBox = getChild("replace_text"); mSearchBox = getChild("search_text"); mSearchBox->setCommitCallback(boost::bind(&LLFloaterScriptSearch::onSearchBoxCommit, this)); - mSearchBox->setCommitOnFocusLost(FALSE); + mSearchBox->setCommitOnFocusLost(false); childSetAction("search_btn", onBtnSearch,this); childSetAction("replace_btn", onBtnReplace,this); childSetAction("replace_all_btn", onBtnReplaceAll,this); setDefaultBtn("search_btn"); - return TRUE; + return true; } //static @@ -296,21 +296,21 @@ bool LLFloaterScriptSearch::hasAccelerators() const { return mEditorCore->hasAccelerators(); } - return FALSE; + return false; } -BOOL LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask) +bool LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask) { if (mEditorCore) { - BOOL handled = mEditorCore->handleKeyHere(key, mask); + bool handled = mEditorCore->handleKeyHere(key, mask); if (!handled) { LLFloater::handleKeyHere(key, mask); } } - return FALSE; + return false; } void LLFloaterScriptSearch::onSearchBoxCommit() @@ -438,7 +438,7 @@ void LLLiveLSLEditor::onToggleExperience( LLUICtrl *ui, void* userdata ) self->updateExperiencePanel(); } -BOOL LLScriptEdCore::postBuild() +bool LLScriptEdCore::postBuild() { mErrorList = getChild("lsl errors"); @@ -460,7 +460,7 @@ BOOL LLScriptEdCore::postBuild() LLSyntaxIdLSL::getInstance()->initialize(); processKeywords(); - return TRUE; + return true; } void LLScriptEdCore::processKeywords() @@ -1173,7 +1173,7 @@ void LLScriptEdCore::deleteBridges() } // virtual -BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask) +bool LLScriptEdCore::handleKeyHere(KEY key, MASK mask) { bool just_control = MASK_CONTROL == (mask & MASK_MODIFIERS); @@ -1185,7 +1185,7 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask) mSaveCallback(mUserdata, FALSE); } - return TRUE; + return true; } if(('F' == key) && just_control) @@ -1195,10 +1195,10 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask) mSearchReplaceCallback(mUserdata); } - return TRUE; + return true; } - return FALSE; + return false; } void LLScriptEdCore::onBtnLoadFromFile( void* data ) @@ -1520,7 +1520,7 @@ LLPreviewLSL::LLPreviewLSL(const LLSD& key ) } // virtual -BOOL LLPreviewLSL::postBuild() +bool LLPreviewLSL::postBuild() { const LLInventoryItem* item = getItem(); @@ -1630,7 +1630,7 @@ void LLPreviewLSL::loadAsset() } -BOOL LLPreviewLSL::canClose() +bool LLPreviewLSL::canClose() { return mScriptEd->canClose(); } @@ -1861,20 +1861,20 @@ LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) : mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); } -BOOL LLLiveLSLEditor::postBuild() +bool LLLiveLSLEditor::postBuild() { childSetCommitCallback("running", LLLiveLSLEditor::onRunningCheckboxClicked, this); - getChildView("running")->setEnabled(FALSE); + getChildView("running")->setEnabled(false); childSetAction("Reset",&LLLiveLSLEditor::onReset,this); - getChildView("Reset")->setEnabled(TRUE); + getChildView("Reset")->setEnabled(true); mMonoCheckbox = getChild("mono"); childSetCommitCallback("mono", &LLLiveLSLEditor::onMonoCheckboxClicked, this); - getChildView("mono")->setEnabled(FALSE); + getChildView("mono")->setEnabled(true); mScriptEd->mEditor->makePristine(); - mScriptEd->mEditor->setFocus(TRUE); + mScriptEd->mEditor->setFocus(true); mExperiences = getChild("Experiences..."); @@ -2317,7 +2317,7 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) } } -BOOL LLLiveLSLEditor::canClose() +bool LLLiveLSLEditor::canClose() { return (mScriptEd->canClose()); } -- cgit v1.2.3 From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llpreviewscript.cpp | 184 +++++++++++++++++++------------------- 1 file changed, 92 insertions(+), 92 deletions(-) (limited to 'indra/newview/llpreviewscript.cpp') diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 11892933d8..80996bee2f 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -339,7 +339,7 @@ LLScriptEdCore::LLScriptEdCore( const std::string& sample, const LLHandle& floater_handle, void (*load_callback)(void*), - void (*save_callback)(void*, BOOL), + void (*save_callback)(void*, bool), void (*search_replace_callback) (void* userdata), void* userdata, bool live, @@ -352,19 +352,19 @@ LLScriptEdCore::LLScriptEdCore( mSaveCallback( save_callback ), mSearchReplaceCallback( search_replace_callback ), mUserdata( userdata ), - mForceClose( FALSE ), + mForceClose( false ), mLastHelpToken(NULL), mLiveHelpHistorySize(0), - mEnableSave(FALSE), + mEnableSave(false), mLiveFile(NULL), mLive(live), mContainer(container), - mHasScriptData(FALSE), - mScriptRemoved(FALSE), - mSaveDialogShown(FALSE) + mHasScriptData(false), + mScriptRemoved(false), + mSaveDialogShown(false) { setFollowsAll(); - setBorderVisible(FALSE); + setBorderVisible(false); setXMLFilename("panel_script_ed.xml"); llassert_always(mContainer != NULL); @@ -394,7 +394,7 @@ void LLLiveLSLEditor::experienceChanged() if(mScriptEd->getAssociatedExperience() != mExperiences->getSelectedValue().asUUID()) { mScriptEd->enableSave(getIsModifiable()); - //getChildView("Save_btn")->setEnabled(TRUE); + //getChildView("Save_btn")->setEnabled(true); mScriptEd->setAssociatedExperience(mExperiences->getSelectedValue().asUUID()); updateExperiencePanel(); } @@ -449,7 +449,7 @@ bool LLScriptEdCore::postBuild() mEditor = getChild("Script Editor"); childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this); - childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,FALSE)); + childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,false)); childSetAction("Edit_btn", boost::bind(&LLScriptEdCore::openInExternalEditor, this)); initMenu(); @@ -504,7 +504,7 @@ void LLScriptEdCore::initMenu() LLMenuItemCallGL* menuItem; menuItem = getChild("Save"); - menuItem->setClickCallback(boost::bind(&LLScriptEdCore::doSave, this, FALSE)); + menuItem->setClickCallback(boost::bind(&LLScriptEdCore::doSave, this, false)); menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::hasChanged, this)); menuItem = getChild("Revert All Changes"); @@ -557,7 +557,7 @@ void LLScriptEdCore::initMenu() menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::enableSaveToFileMenu, this)); } -void LLScriptEdCore::setScriptText(const std::string& text, BOOL is_valid) +void LLScriptEdCore::setScriptText(const std::string& text, bool is_valid) { if (mEditor) { @@ -662,14 +662,14 @@ bool LLScriptEdCore::hasChanged() void LLScriptEdCore::draw() { - BOOL script_changed = hasChanged(); + bool script_changed = hasChanged(); getChildView("Save_btn")->setEnabled(script_changed && !mScriptRemoved); if( mEditor->hasFocus() ) { S32 line = 0; S32 column = 0; - mEditor->getCurrentLineAndColumn( &line, &column, FALSE ); // don't include wordwrap + mEditor->getCurrentLineAndColumn( &line, &column, false ); // don't include wordwrap LLStringUtil::format_map_t args; std::string cursor_pos; args["[LINE]"] = llformat ("%d", line); @@ -687,7 +687,7 @@ void LLScriptEdCore::draw() LLPanel::draw(); } -void LLScriptEdCore::updateDynamicHelp(BOOL immediate) +void LLScriptEdCore::updateDynamicHelp(bool immediate) { LLFloater* help_floater = mLiveHelpHandle.get(); if (!help_floater) return; @@ -838,21 +838,21 @@ void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string) mLiveHelpHistorySize++; } -BOOL LLScriptEdCore::canClose() +bool LLScriptEdCore::canClose() { if(mForceClose || !hasChanged() || mScriptRemoved) { - return TRUE; + return true; } else { if(!mSaveDialogShown) { - mSaveDialogShown = TRUE; + mSaveDialogShown = true; // Bring up view-modal dialog: Save changes? Yes, No, Cancel LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleSaveChangesDialog, this, _1, _2)); } - return FALSE; + return false; } } @@ -864,17 +864,17 @@ void LLScriptEdCore::setEnableEditing(bool enable) bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLSD& response ) { - mSaveDialogShown = FALSE; + mSaveDialogShown = false; S32 option = LLNotificationsUtil::getSelectedOption(notification, response); switch( option ) { case 0: // "Yes" // close after saving - doSave( TRUE ); + doSave( true ); break; case 1: // "No" - mForceClose = TRUE; + mForceClose = true; // This will close immediately because mForceClose is true, so we won't // infinite loop with these dialogs. JC ((LLFloater*) getParent())->closeFloater(); @@ -899,7 +899,7 @@ void LLScriptEdCore::onBtnDynamicHelp() LLFloater* parent = dynamic_cast(getParent()); llassert(parent); if (parent) - parent->addDependentFloater(live_help_floater, TRUE); + parent->addDependentFloater(live_help_floater, true); live_help_floater->childSetCommitCallback("lock_check", onCheckLock, this); live_help_floater->getChild("lock_check")->setValue(gSavedSettings.getBOOL("ScriptHelpFollowsCursor")); live_help_floater->childSetCommitCallback("history_combo", onHelpComboCommit, this); @@ -907,7 +907,7 @@ void LLScriptEdCore::onBtnDynamicHelp() live_help_floater->childSetAction("fwd_btn", onClickForward, this); LLMediaCtrl* browser = live_help_floater->getChild("lsl_guide_html"); - browser->setAlwaysRefresh(TRUE); + browser->setAlwaysRefresh(true); LLComboBox* help_combo = live_help_floater->getChild("history_combo"); LLKeywordToken *token; @@ -927,12 +927,12 @@ void LLScriptEdCore::onBtnDynamicHelp() mLiveHelpHistorySize = 0; } - BOOL visible = TRUE; - BOOL take_focus = TRUE; + bool visible = true; + bool take_focus = true; live_help_floater->setVisible(visible); live_help_floater->setFrontmost(take_focus); - updateDynamicHelp(TRUE); + updateDynamicHelp(true); } //static @@ -1016,11 +1016,11 @@ void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata) { self->mEditor->insertText(self->mFunctions->getSimple()); } - self->mEditor->setFocus(TRUE); + self->mEditor->setFocus(true); self->setHelpPage(self->mFunctions->getSimple()); } -void LLScriptEdCore::doSave( BOOL close_after_save ) +void LLScriptEdCore::doSave( bool close_after_save ) { add(LLStatViewer::LSL_SAVES, 1); @@ -1116,7 +1116,7 @@ void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data) //LL_INFOS() << "LLScriptEdCore::onErrorList() - " << row << ", " //<< column << LL_ENDL; self->mEditor->setCursor(row, column); - self->mEditor->setFocus(TRUE); + self->mEditor->setFocus(true); } } @@ -1128,7 +1128,7 @@ bool LLScriptEdCore::handleReloadFromServerDialog(const LLSD& notification, cons case 0: // "Yes" if( mLoadCallback ) { - setScriptText(getString("loading"), FALSE); + setScriptText(getString("loading"), false); mLoadCallback(mUserdata); } break; @@ -1182,7 +1182,7 @@ bool LLScriptEdCore::handleKeyHere(KEY key, MASK mask) if(mSaveCallback) { // don't close after saving - mSaveCallback(mUserdata, FALSE); + mSaveCallback(mUserdata, false); } return true; @@ -1258,7 +1258,7 @@ void LLScriptEdCore::saveScriptToFile(const std::vector& filenames, llofstream fout(filename.c_str()); fout << (scriptText); fout.close(); - self->mSaveCallback(self->mUserdata, FALSE); + self->mSaveCallback(self->mUserdata, false); } } @@ -1272,7 +1272,7 @@ bool LLScriptEdCore::canLoadOrSaveToFile( void* userdata ) bool LLScriptEdCore::enableSaveToFileMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; - if (!self || !self->mEditor) return FALSE; + if (!self || !self->mEditor) return false; return self->mEditor->canLoadOrSaveToFile(); } @@ -1280,7 +1280,7 @@ bool LLScriptEdCore::enableSaveToFileMenu(void* userdata) bool LLScriptEdCore::enableLoadFromFileMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; - return (self && self->mEditor) ? self->mEditor->canLoadOrSaveToFile() : FALSE; + return (self && self->mEditor) ? self->mEditor->canLoadOrSaveToFile() : false; } LLUUID LLScriptEdCore::getAssociatedExperience()const @@ -1299,26 +1299,26 @@ void LLLiveLSLEditor::updateExperiencePanel() { if(mScriptEd->getAssociatedExperience().isNull()) { - mExperienceEnabled->set(FALSE); - mExperiences->setVisible(FALSE); + mExperienceEnabled->set(false); + mExperiences->setVisible(false); if(mExperienceIds.size()>0) { - mExperienceEnabled->setEnabled(TRUE); + mExperienceEnabled->setEnabled(true); mExperienceEnabled->setToolTip(getString("add_experiences")); } else { - mExperienceEnabled->setEnabled(FALSE); + mExperienceEnabled->setEnabled(false); mExperienceEnabled->setToolTip(getString("no_experiences")); } - getChild("view_profile")->setVisible(FALSE); + getChild("view_profile")->setVisible(false); } else { mExperienceEnabled->setToolTip(getString("experience_enabled")); mExperienceEnabled->setEnabled(getIsModifiable()); - mExperiences->setVisible(TRUE); - mExperienceEnabled->set(TRUE); + mExperiences->setVisible(true); + mExperienceEnabled->set(true); getChild("view_profile")->setToolTip(getString("show_experience_profile")); buildExperienceList(); } @@ -1375,20 +1375,20 @@ void LLLiveLSLEditor::buildExperienceList() item=mExperiences->add(getString("loading"), associated, ADD_TOP); last = associated; } - item->setEnabled(FALSE); + item->setEnabled(false); } if(last.notNull()) { - mExperiences->setEnabled(FALSE); + mExperiences->setEnabled(false); LLExperienceCache::instance().get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); } else { - mExperiences->setEnabled(TRUE); - mExperiences->sortByName(TRUE); + mExperiences->setEnabled(true); + mExperiences->sortByName(true); mExperiences->setCurrentByIndex(mExperiences->getCurrentIndex()); - getChild("view_profile")->setVisible(TRUE); + getChild("view_profile")->setVisible(true); } } @@ -1541,7 +1541,7 @@ void LLPreviewLSL::draw() if(!item) { setTitle(LLTrans::getString("ScriptWasDeleted")); - mScriptEd->setItemRemoved(TRUE); + mScriptEd->setItemRemoved(true); } LLPreview::draw(); @@ -1581,7 +1581,7 @@ void LLPreviewLSL::loadAsset() // then it might be part of the inventory library. If it's in the // library, then you can see the script, but not modify it. const LLInventoryItem* item = gInventory.getItem(mItemUUID); - BOOL is_library = item + bool is_library = item && !gInventory.isObjectDescendentOf(mItemUUID, gInventory.getRootFolderID()); if(!item) @@ -1591,9 +1591,9 @@ void LLPreviewLSL::loadAsset() } if(item) { - BOOL is_copyable = gAgent.allowOperation(PERM_COPY, + bool is_copyable = gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE); - BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, + bool is_modifiable = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); if (gAgent.isGodlike() || (is_copyable && (is_modifiable || is_library))) { @@ -1608,14 +1608,14 @@ void LLPreviewLSL::loadAsset() item->getType(), &LLPreviewLSL::onLoadComplete, (void*)new_uuid, - TRUE); + true); mAssetStatus = PREVIEW_ASSET_LOADING; } else { - mScriptEd->setScriptText(mScriptEd->getString("can_not_view"), FALSE); + mScriptEd->setScriptText(mScriptEd->getString("can_not_view"), false); mScriptEd->mEditor->makePristine(); - mScriptEd->mFunctions->setEnabled(FALSE); + mScriptEd->mFunctions->setEnabled(false); mAssetStatus = PREVIEW_ASSET_LOADED; } getChildView("lock")->setVisible( !is_modifiable); @@ -1623,8 +1623,8 @@ void LLPreviewLSL::loadAsset() } else { - mScriptEd->setScriptText(std::string(HELLO_LSL), TRUE); - mScriptEd->setEnableEditing(TRUE); + mScriptEd->setScriptText(std::string(HELLO_LSL), true); + mScriptEd->setEnableEditing(true); mAssetStatus = PREVIEW_ASSET_LOADED; } } @@ -1661,7 +1661,7 @@ void LLPreviewLSL::onLoad(void* userdata) } // static -void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save) +void LLPreviewLSL::onSave(void* userdata, bool close_after_save) { LLPreviewLSL* self = (LLPreviewLSL*)userdata; self->mCloseAfterSave = close_after_save; @@ -1778,12 +1778,12 @@ void LLPreviewLSL::onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType t // put a EOS at the end buffer[file_length] = 0; - preview->mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), TRUE); + preview->mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), true); preview->mScriptEd->mEditor->makePristine(); std::string script_name = DEFAULT_SCRIPT_NAME; LLInventoryItem* item = gInventory.getItem(*item_uuid); - BOOL is_modifiable = FALSE; + bool is_modifiable = false; if (item) { if (!item->getName().empty()) @@ -1792,7 +1792,7 @@ void LLPreviewLSL::onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType t } if (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) { - is_modifiable = TRUE; + is_modifiable = true; } } preview->mScriptEd->setScriptName(script_name); @@ -1850,13 +1850,13 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata) LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) : LLScriptEdContainer(key), - mAskedForRunningInfo(FALSE), - mHaveRunningInfo(FALSE), - mCloseAfterSave(FALSE), + mAskedForRunningInfo(false), + mHaveRunningInfo(false), + mCloseAfterSave(false), mPendingUploads(0), - mIsModifiable(FALSE), + mIsModifiable(false), mIsNew(false), - mIsSaving(FALSE) + mIsSaving(false) { mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); } @@ -1898,7 +1898,7 @@ void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id, mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); getChild("running")->set(is_script_running); - mIsSaving = FALSE; + mIsSaving = false; closeIfNeeded(); } @@ -1919,7 +1919,7 @@ void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors) mScriptEd->mErrorList->addElement(row); } mScriptEd->selectFirstError(); - mIsSaving = FALSE; + mIsSaving = false; closeIfNeeded(); } @@ -1951,9 +1951,9 @@ void LLLiveLSLEditor::loadAsset() if(!isGodlike && (!copyManipulate || !mIsModifiable)) { mItem = new LLViewerInventoryItem(item); - mScriptEd->setScriptText(getString("not_allowed"), FALSE); + mScriptEd->setScriptText(getString("not_allowed"), false); mScriptEd->mEditor->makePristine(); - mScriptEd->enableSave(FALSE); + mScriptEd->enableSave(false); mAssetStatus = PREVIEW_ASSET_LOADED; } else if(copyManipulate || isGodlike) @@ -1972,24 +1972,24 @@ void LLLiveLSLEditor::loadAsset() item->getType(), &LLLiveLSLEditor::onLoadComplete, (void*)user_data, - TRUE); + true); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_GetScriptRunning); msg->nextBlockFast(_PREHASH_Script); msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID); msg->addUUIDFast(_PREHASH_ItemID, mItemUUID); msg->sendReliable(object->getRegion()->getHost()); - mAskedForRunningInfo = TRUE; + mAskedForRunningInfo = true; mAssetStatus = PREVIEW_ASSET_LOADING; } } if(mItem.isNull()) { - mScriptEd->setScriptText(LLStringUtil::null, FALSE); + mScriptEd->setScriptText(LLStringUtil::null, false); mScriptEd->mEditor->makePristine(); mAssetStatus = PREVIEW_ASSET_LOADED; - mIsModifiable = FALSE; + mIsModifiable = false; } refreshFromItem(); @@ -2011,8 +2011,8 @@ void LLLiveLSLEditor::loadAsset() } else { - mScriptEd->setScriptText(std::string(HELLO_LSL), TRUE); - mScriptEd->enableSave(FALSE); + mScriptEd->setScriptText(std::string(HELLO_LSL), true); + mScriptEd->enableSave(false); LLPermissions perm; perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, gAgent.getGroupID()); perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, PERM_MOVE | PERM_TRANSFER); @@ -2049,7 +2049,7 @@ void LLLiveLSLEditor::onLoadComplete(const LLUUID& asset_id, if( LL_ERR_NOERR == status ) { instance->loadScriptText(asset_id, type); - instance->mScriptEd->setEnableEditing(TRUE); + instance->mScriptEd->setEnableEditing(true); instance->mAssetStatus = PREVIEW_ASSET_LOADED; instance->mScriptEd->setAssetID(asset_id); } @@ -2090,7 +2090,7 @@ void LLLiveLSLEditor::loadScriptText(const LLUUID &uuid, LLAssetType::EType type buffer[file_length] = '\0'; - mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), TRUE); + mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), true); mScriptEd->makeEditorPristine(); std::string script_name = DEFAULT_SCRIPT_NAME; @@ -2109,7 +2109,7 @@ void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata ) LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; LLViewerObject* object = gObjectList.findObject( self->mObjectUUID ); LLCheckBoxCtrl* runningCheckbox = self->getChild("running"); - BOOL running = runningCheckbox->get(); + bool running = runningCheckbox->get(); //self->mRunningCheckbox->get(); if( object ) { @@ -2168,14 +2168,14 @@ void LLLiveLSLEditor::draw() else { runningCheckbox->setLabel(getString("public_objects_can_not_run")); - runningCheckbox->setEnabled(FALSE); + runningCheckbox->setEnabled(false); // *FIX: Set it to false so that the ui is correct for // a box that is released to public. It could be // incorrect after a release/claim cycle, but will be // correct after clicking on it. - runningCheckbox->set(FALSE); - mMonoCheckbox->set(FALSE); + runningCheckbox->set(false); + mMonoCheckbox->set(false); } } else if(!object) @@ -2183,10 +2183,10 @@ void LLLiveLSLEditor::draw() // HACK: Display this information in the title bar. // Really ought to put in main window. setTitle(LLTrans::getString("ObjectOutOfRange")); - runningCheckbox->setEnabled(FALSE); - mMonoCheckbox->setEnabled(FALSE); + runningCheckbox->setEnabled(false); + mMonoCheckbox->setEnabled(false); // object may have fallen out of range. - mHaveRunningInfo = FALSE; + mHaveRunningInfo = false; } LLPreview::draw(); @@ -2203,15 +2203,15 @@ void LLLiveLSLEditor::onSearchReplace(void* userdata) struct LLLiveLSLSaveData { - LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, BOOL active); + LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, bool active); LLUUID mSaveObjectID; LLPointer mItem; - BOOL mActive; + bool mActive; }; LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, - BOOL active) : + bool active) : mSaveObjectID(id), mActive(active) { @@ -2284,7 +2284,7 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) mPendingUploads = 0; // save the script - mScriptEd->enableSave(FALSE); + mScriptEd->enableSave(false); mScriptEd->mEditor->makePristine(); mScriptEd->mErrorList->deleteAllItems(); mScriptEd->mEditor->makePristine(); @@ -2340,7 +2340,7 @@ void LLLiveLSLEditor::onLoad(void* userdata) } // static -void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save) +void LLLiveLSLEditor::onSave(void* userdata, bool close_after_save) { LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; if(self) @@ -2366,7 +2366,7 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance("preview_scriptedit", floater_key); if(instance) { - instance->mHaveRunningInfo = TRUE; + instance->mHaveRunningInfo = true; bool running; msg->getBOOLFast(_PREHASH_Script, _PREHASH_Running, running); LLCheckBoxCtrl* runningCheckbox = instance->getChild("running"); @@ -2387,13 +2387,13 @@ void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata) self->mScriptEd->enableSave(self->getIsModifiable()); } -BOOL LLLiveLSLEditor::monoChecked() const +bool LLLiveLSLEditor::monoChecked() const { if(NULL != mMonoCheckbox) { - return mMonoCheckbox->getValue()? TRUE : FALSE; + return mMonoCheckbox->getValue()? true : false; } - return FALSE; + return false; } void LLLiveLSLEditor::setAssociatedExperience( LLHandle editor, const LLSD& experience ) -- cgit v1.2.3 From f9473e8afcb624cc1b101195bf15943ec372b56f Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Mon, 6 May 2024 16:52:34 +0200 Subject: secondlife/viewer#1333 BOOL to bool conversion leftovers: ternaries --- indra/newview/llpreviewscript.cpp | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'indra/newview/llpreviewscript.cpp') diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 151252fb2d..4be3f6c742 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -2309,7 +2309,6 @@ LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id, mItem = new LLViewerInventoryItem(item); } - /*static*/ void LLLiveLSLEditor::finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, bool isRunning) { @@ -2333,15 +2332,13 @@ void LLLiveLSLEditor::finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAs preview->callbackLSLCompileFailed(response["errors"]); } } - } - // virtual void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) { LLViewerObject* object = gObjectList.findObject(mObjectUUID); - if(!object) + if (!object) { LLNotificationsUtil::add("SaveScriptFailObjectNotFound"); return; @@ -2366,7 +2363,7 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) } // Don't need to save if we're pristine - if(!mScriptEd->hasChanged()) + if (!mScriptEd->hasChanged()) { return; } @@ -2383,6 +2380,7 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) { mScriptEd->sync(); } + bool isRunning = getChild("running")->get(); getWindow()->incBusyCount(); mPendingUploads++; @@ -2409,14 +2407,14 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) bool LLLiveLSLEditor::canClose() { - return (mScriptEd->canClose()); + return mScriptEd->canClose(); } void LLLiveLSLEditor::closeIfNeeded() { getWindow()->decBusyCount(); mPendingUploads--; - if (mPendingUploads <= 0 && mCloseAfterSave) + if ((mPendingUploads <= 0) && mCloseAfterSave) { closeFloater(); } @@ -2432,8 +2430,7 @@ void LLLiveLSLEditor::onLoad(void* userdata) // static void LLLiveLSLEditor::onSave(void* userdata, bool close_after_save) { - LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; - if(self) + if (LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata) { self->mCloseAfterSave = close_after_save; self->mScriptEd->mErrorList->setCommentText(""); @@ -2441,7 +2438,6 @@ void LLLiveLSLEditor::onSave(void* userdata, bool close_after_save) } } - // static void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) { @@ -2453,8 +2449,7 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) LLSD floater_key; floater_key["taskid"] = object_id; floater_key["itemid"] = item_id; - LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance("preview_scriptedit", floater_key); - if(instance) + if (LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance("preview_scriptedit", floater_key)) { instance->mHaveRunningInfo = true; bool running; @@ -2469,7 +2464,6 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) } } - void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata) { LLLiveLSLEditor* self = static_cast(userdata); @@ -2479,20 +2473,15 @@ void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata) bool LLLiveLSLEditor::monoChecked() const { - if(NULL != mMonoCheckbox) - { - return mMonoCheckbox->getValue()? true : false; - } - return false; + return mMonoCheckbox && mMonoCheckbox->getValue(); } void LLLiveLSLEditor::setAssociatedExperience( LLHandle editor, const LLSD& experience ) { - LLLiveLSLEditor* scriptEd = editor.get(); - if(scriptEd) + if (LLLiveLSLEditor* scriptEd = editor.get()) { LLUUID id; - if(experience.has(LLExperienceCache::EXPERIENCE_ID)) + if (experience.has(LLExperienceCache::EXPERIENCE_ID)) { id=experience[LLExperienceCache::EXPERIENCE_ID].asUUID(); } -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llpreviewscript.cpp | 4982 ++++++++++++++++++------------------- 1 file changed, 2491 insertions(+), 2491 deletions(-) (limited to 'indra/newview/llpreviewscript.cpp') diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 202b34a59f..a6ab08601d 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1,2491 +1,2491 @@ -/** - * @file llpreviewscript.cpp - * @brief LLPreviewScript class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpreviewscript.h" - -#include "llassetstorage.h" -#include "llbutton.h" -#include "llcheckboxctrl.h" -#include "llcombobox.h" -#include "lldir.h" -#include "llexternaleditor.h" -#include "llfilepicker.h" -#include "llfloaterreg.h" -#include "llinventorydefines.h" -#include "llinventorymodel.h" -#include "llkeyboard.h" -#include "lllineeditor.h" -#include "llmd5.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 "lltooldraganddrop.h" -#include "llfilesystem.h" - -#include "llagent.h" -#include "llmenugl.h" -#include "roles_constants.h" -#include "llselectmgr.h" -#include "llviewerinventory.h" -#include "llviewermenu.h" -#include "llviewermenufile.h" // LLFilePickerReplyThread -#include "llviewerobject.h" -#include "llviewerobjectlist.h" -#include "llviewerregion.h" -#include "llkeyboard.h" -#include "llscrollcontainer.h" -#include "llcheckboxctrl.h" -#include "llscripteditor.h" -#include "llselectmgr.h" -#include "lltooldraganddrop.h" -#include "llscrolllistctrl.h" -#include "lltextbox.h" -#include "llslider.h" -#include "lldir.h" -#include "llcombobox.h" -#include "llviewerstats.h" -#include "llviewerwindow.h" -#include "lluictrlfactory.h" -#include "llmediactrl.h" -#include "lluictrlfactory.h" -#include "lltrans.h" -#include "llviewercontrol.h" -#include "llappviewer.h" -#include "llfloatergotoline.h" -#include "llexperiencecache.h" -#include "llfloaterexperienceprofile.h" -#include "llviewerassetupload.h" -#include "lltoggleablemenu.h" -#include "llmenubutton.h" -#include "llinventoryfunctions.h" - -const std::string HELLO_LSL = - "default\n" - "{\n" - " state_entry()\n" - " {\n" - " llSay(0, \"Hello, Avatar!\");\n" - " }\n" - "\n" - " touch_start(integer total_number)\n" - " {\n" - " llSay(0, \"Touched.\");\n" - " }\n" - "}\n"; -const std::string HELP_LSL_PORTAL_TOPIC = "LSL_Portal"; - -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_HISTORY_COUNT = 10; -const F32 LIVE_HELP_REFRESH_TIME = 1.f; - -static bool have_script_upload_cap(LLUUID& object_id) -{ - LLViewerObject* object = gObjectList.findObject(object_id); - return object && (! object->getRegion()->getCapability("UpdateScriptTask").empty()); -} - -/// --------------------------------------------------------------------------- -/// LLLiveLSLFile -/// --------------------------------------------------------------------------- - -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 -{ -public: - LLFloaterScriptSearch(LLScriptEdCore* editor_core); - ~LLFloaterScriptSearch(); - - /*virtual*/ bool postBuild(); - static void show(LLScriptEdCore* editor_core); - static void onBtnSearch(void* userdata); - void handleBtnSearch(); - - static void onBtnReplace(void* userdata); - void handleBtnReplace(); - - static void onBtnReplaceAll(void* userdata); - void handleBtnReplaceAll(); - - 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) -{ - buildFromFile("floater_script_search.xml"); - - sInstance = this; - - // find floater in which script panel is embedded - LLView* viewp = (LLView*)editor_core; - while(viewp) - { - LLFloater* floaterp = dynamic_cast(viewp); - if (floaterp) - { - floaterp->addDependentFloater(this); - break; - } - viewp = viewp->getParent(); - } -} - -bool LLFloaterScriptSearch::postBuild() -{ - mReplaceBox = getChild("replace_text"); - mSearchBox = getChild("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); - - setDefaultBtn("search_btn"); - - return true; -} - -//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; - } - - if (!sInstance) - { - // sInstance will be assigned in the constructor. - new LLFloaterScriptSearch(editor_core); - sInstance->mSearchBox->setValue(search_text); - sInstance->mReplaceBox->setValue(replace_text); - } - - sInstance->openFloater(); -} - -LLFloaterScriptSearch::~LLFloaterScriptSearch() -{ - sInstance = NULL; -} - -// static -void LLFloaterScriptSearch::onBtnSearch(void *userdata) -{ - LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata; - self->handleBtnSearch(); -} - -void LLFloaterScriptSearch::handleBtnSearch() -{ - LLCheckBoxCtrl* caseChk = getChild("case_text"); - mEditorCore->mEditor->selectNext(mSearchBox->getValue().asString(), caseChk->get()); -} - -// static -void LLFloaterScriptSearch::onBtnReplace(void *userdata) -{ - LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata; - self->handleBtnReplace(); -} - -void LLFloaterScriptSearch::handleBtnReplace() -{ - LLCheckBoxCtrl* caseChk = getChild("case_text"); - mEditorCore->mEditor->replaceText(mSearchBox->getValue().asString(), mReplaceBox->getValue().asString(), caseChk->get()); -} - -// static -void LLFloaterScriptSearch::onBtnReplaceAll(void *userdata) -{ - LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata; - self->handleBtnReplaceAll(); -} - -void LLFloaterScriptSearch::handleBtnReplaceAll() -{ - LLCheckBoxCtrl* caseChk = getChild("case_text"); - 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("case_text"); - mEditorCore->mEditor->selectNext(mSearchBox->getValue().asString(), caseChk->get()); - } -} - -/// --------------------------------------------------------------------------- - -class LLScriptMovedObserver : public LLInventoryObserver -{ - public: - LLScriptMovedObserver(LLPreviewLSL *floater) : mPreview(floater) { gInventory.addObserver(this); } - virtual ~LLScriptMovedObserver() { gInventory.removeObserver(this); } - virtual void changed(U32 mask); - - private: - LLPreviewLSL *mPreview; -}; - -void LLScriptMovedObserver::changed(U32 mask) -{ - const std::set &mChangedItemIDs = gInventory.getChangedIDs(); - std::set::const_iterator it; - - const LLUUID &item_id = mPreview->getScriptID(); - - for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++) - { - if (*it == item_id) - { - if ((mask & (LLInventoryObserver::STRUCTURE)) != 0) - { - mPreview->setDirty(); - } - } - } -} - -/// --------------------------------------------------------------------------- -/// LLScriptEdCore -/// --------------------------------------------------------------------------- - -struct LLSECKeywordCompare -{ - bool operator()(const std::string& lhs, const std::string& rhs) - { - return (LLStringUtil::compareDictInsensitive( lhs, rhs ) < 0 ); - } -}; - -LLScriptEdCore::LLScriptEdCore( - LLScriptEdContainer* container, - const std::string& sample, - const LLHandle& 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(), - mSampleText(sample), - mEditor( NULL ), - mLoadCallback( load_callback ), - mSaveCallback( save_callback ), - mSearchReplaceCallback( search_replace_callback ), - mUserdata( userdata ), - mForceClose( false ), - mLastHelpToken(NULL), - mLiveHelpHistorySize(0), - mEnableSave(false), - mLiveFile(NULL), - mLive(live), - mContainer(container), - mHasScriptData(false), - mScriptRemoved(false), - mSaveDialogShown(false) -{ - setFollowsAll(); - setBorderVisible(false); - - setXMLFilename("panel_script_ed.xml"); - llassert_always(mContainer != NULL); -} - -LLScriptEdCore::~LLScriptEdCore() -{ - deleteBridges(); - - // If the search window is up for this editor, close it. - LLFloaterScriptSearch* script_search = LLFloaterScriptSearch::getInstance(); - if (script_search && script_search->getEditorCore() == this) - { - script_search->closeFloater(); - delete script_search; - } - - delete mLiveFile; - if (mSyntaxIDConnection.connected()) - { - mSyntaxIDConnection.disconnect(); - } -} - -void LLLiveLSLEditor::experienceChanged() -{ - if(mScriptEd->getAssociatedExperience() != mExperiences->getSelectedValue().asUUID()) - { - mScriptEd->enableSave(getIsModifiable()); - //getChildView("Save_btn")->setEnabled(true); - mScriptEd->setAssociatedExperience(mExperiences->getSelectedValue().asUUID()); - updateExperiencePanel(); - } -} - -void LLLiveLSLEditor::onViewProfile( LLUICtrl *ui, void* userdata ) -{ - LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; - - LLUUID id; - if(self->mExperienceEnabled->get()) - { - id=self->mScriptEd->getAssociatedExperience(); - if(id.notNull()) - { - LLFloaterReg::showInstance("experience_profile", id, true); - } - } - -} - -void LLLiveLSLEditor::onToggleExperience( LLUICtrl *ui, void* userdata ) -{ - LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; - - LLUUID id; - if(self->mExperienceEnabled->get()) - { - if(self->mScriptEd->getAssociatedExperience().isNull()) - { - id=self->mExperienceIds.beginArray()->asUUID(); - } - } - - if(id != self->mScriptEd->getAssociatedExperience()) - { - self->mScriptEd->enableSave(self->getIsModifiable()); - } - self->mScriptEd->setAssociatedExperience(id); - - self->updateExperiencePanel(); -} - -bool LLScriptEdCore::postBuild() -{ - mErrorList = getChild("lsl errors"); - - mFunctions = getChild("Insert..."); - - childSetCommitCallback("Insert...", &LLScriptEdCore::onBtnInsertFunction, this); - - mEditor = getChild("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)); - - // Intialise keyword highlighting for the current simulator's version of LSL - LLSyntaxIdLSL::getInstance()->initialize(); - processKeywords(); - - mCommitCallbackRegistrar.add("FontSize.Set", boost::bind(&LLScriptEdCore::onChangeFontSize, this, _2)); - mEnableCallbackRegistrar.add("FontSize.Check", boost::bind(&LLScriptEdCore::isFontSizeChecked, this, _2)); - - LLToggleableMenu *context_menu = LLUICtrlFactory::getInstance()->createFromFile( - "menu_lsl_font_size.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - getChild("font_btn")->setMenu(context_menu, LLMenuButton::MP_BOTTOM_LEFT, true); - - return true; -} - -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->getType() == LLKeywordToken::TT_FUNCTION) - { - primary_keywords.push_back( wstring_to_utf8str(token->getToken()) ); - } - else - { - secondary_keywords.push_back( wstring_to_utf8str(token->getToken()) ); - } - } - for (string_vec_t::const_iterator iter = primary_keywords.begin(); - iter!= primary_keywords.end(); ++iter) - { - mFunctions->add(*iter); - } - for (string_vec_t::const_iterator iter = secondary_keywords.begin(); - iter!= secondary_keywords.end(); ++iter) - { - mFunctions->add(*iter); - } -} - -void LLScriptEdCore::initMenu() -{ - // *TODO: Skinning - make these callbacks data driven - LLMenuItemCallGL* menuItem; - - menuItem = getChild("Save"); - menuItem->setClickCallback(boost::bind(&LLScriptEdCore::doSave, this, false)); - menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::hasChanged, this)); - - menuItem = getChild("Revert All Changes"); - menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnUndoChanges, this)); - menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::hasChanged, this)); - - menuItem = getChild("Undo"); - menuItem->setClickCallback(boost::bind(&LLTextEditor::undo, mEditor)); - menuItem->setEnableCallback(boost::bind(&LLTextEditor::canUndo, mEditor)); - - menuItem = getChild("Redo"); - menuItem->setClickCallback(boost::bind(&LLTextEditor::redo, mEditor)); - menuItem->setEnableCallback(boost::bind(&LLTextEditor::canRedo, mEditor)); - - menuItem = getChild("Cut"); - menuItem->setClickCallback(boost::bind(&LLTextEditor::cut, mEditor)); - menuItem->setEnableCallback(boost::bind(&LLTextEditor::canCut, mEditor)); - - menuItem = getChild("Copy"); - menuItem->setClickCallback(boost::bind(&LLTextEditor::copy, mEditor)); - menuItem->setEnableCallback(boost::bind(&LLTextEditor::canCopy, mEditor)); - - menuItem = getChild("Paste"); - menuItem->setClickCallback(boost::bind(&LLTextEditor::paste, mEditor)); - menuItem->setEnableCallback(boost::bind(&LLTextEditor::canPaste, mEditor)); - - menuItem = getChild("Select All"); - menuItem->setClickCallback(boost::bind(&LLTextEditor::selectAll, mEditor)); - menuItem->setEnableCallback(boost::bind(&LLTextEditor::canSelectAll, mEditor)); - - menuItem = getChild("Deselect"); - menuItem->setClickCallback(boost::bind(&LLTextEditor::deselect, mEditor)); - menuItem->setEnableCallback(boost::bind(&LLTextEditor::canDeselect, mEditor)); - - menuItem = getChild("Search / Replace..."); - menuItem->setClickCallback(boost::bind(&LLFloaterScriptSearch::show, this)); - - menuItem = getChild("Go to line..."); - menuItem->setClickCallback(boost::bind(&LLFloaterGotoLine::show, this)); - - menuItem = getChild("Keyword Help..."); - menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnDynamicHelp, this)); - - menuItem = getChild("LoadFromFile"); - menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnLoadFromFile, this)); - menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::enableLoadFromFileMenu, this)); - - menuItem = getChild("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) -{ - if (mEditor) - { - mEditor->setText(text); - mHasScriptData = is_valid; - } -} - -void LLScriptEdCore::makeEditorPristine() -{ - if (mEditor) - { - mEditor->makePristine(); - } -} - -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); - - std::string text = std::string(buffer); - LLStringUtil::replaceTabsWithSpaces(text, LLTextEditor::spacesPerTab()); - - mEditor->setText(text); - 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. - if (mLiveFile) - { - std::string tmp_file = mLiveFile->filename(); - llstat s; - if (LLFile::stat(tmp_file, &s) == 0) // file exists - { - mLiveFile->ignoreNextUpdate(); - writeToFile(tmp_file); - } - } -} - -bool LLScriptEdCore::hasChanged() -{ - if (!mEditor) return false; - - return ((!mEditor->isPristine() || mEnableSave) && mHasScriptData); -} - -void LLScriptEdCore::draw() -{ - bool script_changed = hasChanged(); - getChildView("Save_btn")->setEnabled(script_changed && !mScriptRemoved); - - if( mEditor->hasFocus() ) - { - S32 line = 0; - S32 column = 0; - mEditor->getCurrentLineAndColumn( &line, &column, false ); // don't include wordwrap - LLStringUtil::format_map_t args; - std::string cursor_pos; - args["[LINE]"] = llformat ("%d", line); - args["[COLUMN]"] = llformat ("%d", column); - cursor_pos = LLTrans::getString("CursorPos", args); - getChild("line_col")->setValue(cursor_pos); - } - else - { - getChild("line_col")->setValue(LLStringUtil::null); - } - - updateDynamicHelp(); - - LLPanel::draw(); -} - -void LLScriptEdCore::updateDynamicHelp(bool immediate) -{ - LLFloater* help_floater = mLiveHelpHandle.get(); - if (!help_floater) return; - - // update back and forward buttons - LLButton* fwd_button = help_floater->getChild("fwd_btn"); - LLButton* back_button = help_floater->getChild("back_btn"); - LLMediaCtrl* browser = help_floater->getChild("lsl_guide_html"); - back_button->setEnabled(browser->canNavigateBack()); - fwd_button->setEnabled(browser->canNavigateForward()); - - if (!immediate && !gSavedSettings.getBOOL("ScriptHelpFollowsCursor")) - { - return; - } - - LLTextSegmentPtr segment = NULL; - std::vector selected_segments; - mEditor->getSelectedSegments(selected_segments); - LLKeywordToken* token; - // try segments in selection range first - std::vector::iterator segment_iter; - for (segment_iter = selected_segments.begin(); segment_iter != selected_segments.end(); ++segment_iter) - { - token = (*segment_iter)->getToken(); - if(token && isKeyword(token)) - { - segment = *segment_iter; - break; - } - } - - // then try previous segment in case we just typed it - if (!segment) - { - const LLTextSegmentPtr test_segment = mEditor->getPreviousSegment(); - token = test_segment->getToken(); - if(token && isKeyword(token)) - { - segment = test_segment; - } - } - - if (segment) - { - if (segment->getToken() != mLastHelpToken) - { - mLastHelpToken = segment->getToken(); - mLiveHelpTimer.start(); - } - if (immediate || (mLiveHelpTimer.getStarted() && mLiveHelpTimer.getElapsedTimeF32() > LIVE_HELP_REFRESH_TIME)) - { - // Use Wtext since segment's start/end are made for wstring and will - // result in a shift for case of multi-byte symbols inside std::string. - LLWString segment_text = mEditor->getWText().substr(segment->getStart(), segment->getEnd() - segment->getStart()); - std::string help_string = wstring_to_utf8str(segment_text); - setHelpPage(help_string); - mLiveHelpTimer.stop(); - } - } - else - { - if (immediate) - { - setHelpPage(LLStringUtil::null); - } - } -} - -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(); - if (!help_floater) return; - - LLMediaCtrl* web_browser = help_floater->getChild("lsl_guide_html"); - if (!web_browser) return; - - LLComboBox* history_combo = help_floater->getChild("history_combo"); - if (!history_combo) return; - - LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); - - url_string.setArg("[LSL_STRING]", help_string.empty() ? HELP_LSL_PORTAL_TOPIC : help_string); - - addHelpItemToHistory(help_string); - - web_browser->navigateTo(url_string); - -} - - -void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string) -{ - if (help_string.empty()) return; - - LLFloater* help_floater = mLiveHelpHandle.get(); - if (!help_floater) return; - - LLComboBox* history_combo = help_floater->getChild("history_combo"); - if (!history_combo) return; - - // separate history items from full item list - if (mLiveHelpHistorySize == 0) - { - history_combo->addSeparator(ADD_TOP); - } - // delete all history items over history limit - while(mLiveHelpHistorySize > MAX_HISTORY_COUNT - 1) - { - history_combo->remove(mLiveHelpHistorySize - 1); - mLiveHelpHistorySize--; - } - - history_combo->setSimple(help_string); - S32 index = history_combo->getCurrentIndex(); - - // if help string exists in the combo box - if (index >= 0) - { - S32 cur_index = history_combo->getCurrentIndex(); - if (cur_index < mLiveHelpHistorySize) - { - // item found in history, bubble up to top - history_combo->remove(history_combo->getCurrentIndex()); - mLiveHelpHistorySize--; - } - } - history_combo->add(help_string, LLSD(help_string), ADD_TOP); - history_combo->selectFirstItem(); - mLiveHelpHistorySize++; -} - -bool LLScriptEdCore::canClose() -{ - if(mForceClose || !hasChanged() || mScriptRemoved) - { - return true; - } - else - { - if(!mSaveDialogShown) - { - mSaveDialogShown = true; - // Bring up view-modal dialog: Save changes? Yes, No, Cancel - 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 ) -{ - mSaveDialogShown = false; - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - switch( option ) - { - case 0: // "Yes" - // close after saving - doSave( true ); - break; - - case 1: // "No" - mForceClose = true; - // This will close immediately because mForceClose is true, so we won't - // infinite loop with these dialogs. JC - ((LLFloater*) getParent())->closeFloater(); - break; - - case 2: // "Cancel" - default: - // If we were quitting, we didn't really mean it. - LLAppViewer::instance()->abortQuit(); - break; - } - return false; -} - -void LLScriptEdCore::onBtnDynamicHelp() -{ - LLFloater* live_help_floater = mLiveHelpHandle.get(); - if (!live_help_floater) - { - live_help_floater = new LLFloater(LLSD()); - live_help_floater->buildFromFile("floater_lsl_guide.xml"); - LLFloater* parent = dynamic_cast(getParent()); - llassert(parent); - if (parent) - parent->addDependentFloater(live_help_floater, true); - live_help_floater->childSetCommitCallback("lock_check", onCheckLock, this); - live_help_floater->getChild("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); - - LLMediaCtrl* browser = live_help_floater->getChild("lsl_guide_html"); - browser->setAlwaysRefresh(true); - - LLComboBox* help_combo = live_help_floater->getChild("history_combo"); - LLKeywordToken *token; - LLKeywords::keyword_iterator_t token_it; - for (token_it = mEditor->keywordsBegin(); - token_it != mEditor->keywordsEnd(); - ++token_it) - { - token = token_it->second; - help_combo->add(wstring_to_utf8str(token->getToken())); - } - help_combo->sortByName(); - - // re-initialize help variables - mLastHelpToken = NULL; - mLiveHelpHandle = live_help_floater->getHandle(); - mLiveHelpHistorySize = 0; - } - - bool visible = true; - bool take_focus = true; - live_help_floater->setVisible(visible); - live_help_floater->setFrontmost(take_focus); - - updateDynamicHelp(true); -} - -//static -void LLScriptEdCore::onClickBack(void* userdata) -{ - LLScriptEdCore* corep = (LLScriptEdCore*)userdata; - LLFloater* live_help_floater = corep->mLiveHelpHandle.get(); - if (live_help_floater) - { - LLMediaCtrl* browserp = live_help_floater->getChild("lsl_guide_html"); - if (browserp) - { - browserp->navigateBack(); - } - } -} - -//static -void LLScriptEdCore::onClickForward(void* userdata) -{ - LLScriptEdCore* corep = (LLScriptEdCore*)userdata; - LLFloater* live_help_floater = corep->mLiveHelpHandle.get(); - if (live_help_floater) - { - LLMediaCtrl* browserp = live_help_floater->getChild("lsl_guide_html"); - if (browserp) - { - browserp->navigateForward(); - } - } -} - -// static -void LLScriptEdCore::onCheckLock(LLUICtrl* ctrl, void* userdata) -{ - LLScriptEdCore* corep = (LLScriptEdCore*)userdata; - - // clear out token any time we lock the frame, so we will refresh web page immediately when unlocked - gSavedSettings.setBOOL("ScriptHelpFollowsCursor", ctrl->getValue().asBoolean()); - - corep->mLastHelpToken = NULL; -} - -// static -void LLScriptEdCore::onBtnInsertSample(void* userdata) -{ - LLScriptEdCore* self = (LLScriptEdCore*) userdata; - - // Insert sample code - self->mEditor->selectAll(); - self->mEditor->cut(); - self->mEditor->insertText(self->mSampleText); -} - -// static -void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata) -{ - LLScriptEdCore* corep = (LLScriptEdCore*)userdata; - - LLFloater* live_help_floater = corep->mLiveHelpHandle.get(); - if (live_help_floater) - { - std::string help_string = ctrl->getValue().asString(); - - corep->addHelpItemToHistory(help_string); - - LLMediaCtrl* web_browser = live_help_floater->getChild("lsl_guide_html"); - LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); - url_string.setArg("[LSL_STRING]", help_string); - web_browser->navigateTo(url_string); - } -} - -// static -void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata) -{ - LLScriptEdCore* self = (LLScriptEdCore*) userdata; - - // Insert sample code - if(self->mEditor->getEnabled()) - { - self->mEditor->insertText(self->mFunctions->getSimple()); - } - self->mEditor->setFocus(true); - self->setHelpPage(self->mFunctions->getSimple()); -} - -void LLScriptEdCore::doSave( bool close_after_save ) -{ - add(LLStatViewer::LSL_SAVES, 1); - - if( mSaveCallback ) - { - mSaveCallback( mUserdata, close_after_save ); - } -} - -void LLScriptEdCore::openInExternalEditor() -{ - delete mLiveFile; // deletes file - - // Generate a suitable filename - std::string script_name = mScriptName; - std::string forbidden_chars = "<>:\"\\/|?*"; - for (std::string::iterator c = forbidden_chars.begin(); c != forbidden_chars.end(); c++) - { - script_name.erase(std::remove(script_name.begin(), script_name.end(), *c), script_name.end()); - } - std::string filename = mContainer->getTmpFileName(script_name); - - // Save the script to a temporary file. - if (!writeToFile(filename)) - { - // In case some characters from script name are forbidden - // and not accounted for, name is too long or some other issue, - // try file that doesn't include script name - script_name.clear(); - filename = mContainer->getTmpFileName(script_name); - 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 = LLTrans::getString("ExternalEditorNotSet"); - } - 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() ) - { - LLNotificationsUtil::add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, this, _1, _2)); - } -} - -// static -void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data) -{ - LLScriptEdCore* self = (LLScriptEdCore*)user_data; - LLScrollListItem* item = self->mErrorList->getFirstSelected(); - if(item) - { - // *FIX: replace with boost grep - S32 row = 0; - S32 column = 0; - const LLScrollListCell* cell = item->getColumn(0); - std::string line(cell->getValue().asString()); - line.erase(0, 1); - LLStringUtil::replaceChar(line, ',',' '); - LLStringUtil::replaceChar(line, ')',' '); - sscanf(line.c_str(), "%d %d", &row, &column); - //LL_INFOS() << "LLScriptEdCore::onErrorList() - " << row << ", " - //<< column << LL_ENDL; - self->mEditor->setCursor(row, column); - self->mEditor->setFocus(true); - } -} - -bool LLScriptEdCore::handleReloadFromServerDialog(const LLSD& notification, const LLSD& response ) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - switch( option ) - { - case 0: // "Yes" - if( mLoadCallback ) - { - setScriptText(getString("loading"), false); - mLoadCallback(mUserdata); - } - break; - - case 1: // "No" - break; - - default: - llassert(0); - break; - } - return false; -} - -void LLScriptEdCore::selectFirstError() -{ - // Select the first item; - mErrorList->selectFirstItem(); - onErrorList(mErrorList, this); -} - - -struct LLEntryAndEdCore -{ - LLScriptEdCore* mCore; - LLEntryAndEdCore(LLScriptEdCore* core) : - mCore(core) - {} -}; - -void LLScriptEdCore::deleteBridges() -{ - S32 count = mBridges.size(); - LLEntryAndEdCore* eandc; - for(S32 i = 0; i < count; i++) - { - eandc = mBridges.at(i); - delete eandc; - mBridges[i] = NULL; - } - mBridges.clear(); -} - -// virtual -bool LLScriptEdCore::handleKeyHere(KEY key, MASK mask) -{ - bool just_control = MASK_CONTROL == (mask & MASK_MODIFIERS); - - if(('S' == key) && just_control) - { - if(mSaveCallback) - { - // don't close after saving - mSaveCallback(mUserdata, false); - } - - return true; - } - - if(('F' == key) && just_control) - { - if(mSearchReplaceCallback) - { - mSearchReplaceCallback(mUserdata); - } - - return true; - } - - return false; -} - -void LLScriptEdCore::onBtnLoadFromFile( void* data ) -{ - LLFilePickerReplyThread::startPicker(boost::bind(&LLScriptEdCore::loadScriptFromFile, _1, data), LLFilePicker::FFLOAD_SCRIPT, false); -} - -void LLScriptEdCore::loadScriptFromFile(const std::vector& filenames, void* data) -{ - std::string filename = filenames[0]; - - llifstream 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. - LLScriptEdCore* self = (LLScriptEdCore*)data; - if (self && (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 ) - { - LLFilePickerReplyThread::startPicker(boost::bind(&LLScriptEdCore::saveScriptToFile, _1, userdata), LLFilePicker::FFSAVE_SCRIPT, self->mScriptName); - } -} - -void LLScriptEdCore::saveScriptToFile(const std::vector& filenames, void* data) -{ - LLScriptEdCore* self = (LLScriptEdCore*)data; - if (self) - { - std::string filename = filenames[0]; - std::string scriptText = self->mEditor->getText(); - llofstream 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; -} - -LLUUID LLScriptEdCore::getAssociatedExperience()const -{ - return mAssociatedExperience; -} - -void LLScriptEdCore::onChangeFontSize(const LLSD &userdata) -{ - const std::string font_name = userdata.asString(); - gSavedSettings.setString("LSLFontSizeName", font_name); -} - -bool LLScriptEdCore::isFontSizeChecked(const LLSD &userdata) -{ - const std::string current_size_name = LLScriptEditor::getScriptFontSize(); - const std::string size_name = userdata.asString(); - - return (size_name == current_size_name); -} - - void LLLiveLSLEditor::setExperienceIds( const LLSD& experience_ids ) -{ - mExperienceIds=experience_ids; - updateExperiencePanel(); -} - - -void LLLiveLSLEditor::updateExperiencePanel() -{ - if(mScriptEd->getAssociatedExperience().isNull()) - { - mExperienceEnabled->set(false); - mExperiences->setVisible(false); - if(mExperienceIds.size()>0) - { - mExperienceEnabled->setEnabled(true); - mExperienceEnabled->setToolTip(getString("add_experiences")); - } - else - { - mExperienceEnabled->setEnabled(false); - mExperienceEnabled->setToolTip(getString("no_experiences")); - } - getChild("view_profile")->setVisible(false); - } - else - { - mExperienceEnabled->setToolTip(getString("experience_enabled")); - mExperienceEnabled->setEnabled(getIsModifiable()); - mExperiences->setVisible(true); - mExperienceEnabled->set(true); - getChild("view_profile")->setToolTip(getString("show_experience_profile")); - buildExperienceList(); - } -} - -void LLLiveLSLEditor::buildExperienceList() -{ - mExperiences->clearRows(); - bool foundAssociated=false; - const LLUUID& associated = mScriptEd->getAssociatedExperience(); - LLUUID last; - LLScrollListItem* item; - for(LLSD::array_const_iterator it = mExperienceIds.beginArray(); it != mExperienceIds.endArray(); ++it) - { - LLUUID id = it->asUUID(); - EAddPosition position = ADD_BOTTOM; - if(id == associated) - { - foundAssociated = true; - position = ADD_TOP; - } - - const LLSD& experience = LLExperienceCache::instance().get(id); - if(experience.isUndefined()) - { - mExperiences->add(getString("loading"), id, position); - last = id; - } - else - { - std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); - if (experience_name_string.empty()) - { - experience_name_string = LLTrans::getString("ExperienceNameUntitled"); - } - mExperiences->add(experience_name_string, id, position); - } - } - - if(!foundAssociated ) - { - const LLSD& experience = LLExperienceCache::instance().get(associated); - if(experience.isDefined()) - { - std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); - if (experience_name_string.empty()) - { - experience_name_string = LLTrans::getString("ExperienceNameUntitled"); - } - item=mExperiences->add(experience_name_string, associated, ADD_TOP); - } - else - { - item=mExperiences->add(getString("loading"), associated, ADD_TOP); - last = associated; - } - item->setEnabled(false); - } - - if(last.notNull()) - { - mExperiences->setEnabled(false); - LLExperienceCache::instance().get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); - } - else - { - mExperiences->setEnabled(true); - mExperiences->sortByName(true); - mExperiences->setCurrentByIndex(mExperiences->getCurrentIndex()); - getChild("view_profile")->setVisible(true); - } -} - - -void LLScriptEdCore::setAssociatedExperience( const LLUUID& experience_id ) -{ - mAssociatedExperience = experience_id; -} - - - -void LLLiveLSLEditor::requestExperiences() -{ - if (!getIsModifiable()) - { - return; - } - - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - std::string lookup_url=region->getCapability("GetCreatorExperiences"); - if(!lookup_url.empty()) - { - LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t success = - boost::bind(&LLLiveLSLEditor::receiveExperienceIds, _1, getDerivedHandle()); - - LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url, success); - } - } -} - -/*static*/ -void LLLiveLSLEditor::receiveExperienceIds(LLSD result, LLHandle hparent) -{ - LLLiveLSLEditor* parent = hparent.get(); - if (!parent) - return; - - parent->setExperienceIds(result["experience_ids"]); -} - - -/// --------------------------------------------------------------------------- -/// LLScriptEdContainer -/// --------------------------------------------------------------------------- - -LLScriptEdContainer::LLScriptEdContainer(const LLSD& key) : - LLPreview(key) -, mScriptEd(NULL) -{ -} - -std::string LLScriptEdContainer::getTmpFileName(const std::string& script_name) -{ - // 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); - - if (script_name.empty()) - { - return std::string(LLFile::tmpdir()) + "sl_script_" + script_id_hash_str + ".lsl"; - } - else - { - return std::string(LLFile::tmpdir()) + "sl_script_" + script_name + "_" + 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; -} - -bool LLScriptEdContainer::handleKeyHere(KEY key, MASK mask) -{ - if (('A' == key) && (MASK_CONTROL == (mask & MASK_MODIFIERS))) - { - mScriptEd->selectAll(); - return true; - } - - if (!LLPreview::handleKeyHere(key, mask)) - { - return mScriptEd->handleKeyHere(key, mask); - } - return true; -} - -/// --------------------------------------------------------------------------- -/// LLPreviewLSL -/// --------------------------------------------------------------------------- - -struct LLScriptSaveInfo -{ - LLUUID mItemUUID; - std::string mDescription; - LLTransactionID mTransactionID; - - LLScriptSaveInfo(const LLUUID& uuid, const std::string& desc, LLTransactionID tid) : - mItemUUID(uuid), mDescription(desc), mTransactionID(tid) {} -}; - - - -//static -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 ) -: LLScriptEdContainer(key), - mPendingUploads(0) -{ - mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this); - - mItemObserver = new LLScriptMovedObserver(this); -} - -LLPreviewLSL::~LLPreviewLSL() -{ - delete mItemObserver; - mItemObserver = NULL; -} - -// virtual -bool LLPreviewLSL::postBuild() -{ - const LLInventoryItem* item = getItem(); - - llassert(item); - if (item) - { - getChild("desc")->setValue(item->getDescription()); - - std::string item_path = get_category_path(item->getParentUUID()); - getChild("path_txt")->setValue(item_path); - getChild("path_txt")->setToolTip(item_path); - } - childSetCommitCallback("desc", LLPreview::onText, this); - getChild("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); - - return LLPreview::postBuild(); -} - -void LLPreviewLSL::draw() -{ - const LLInventoryItem* item = getItem(); - if(!item) - { - setTitle(LLTrans::getString("ScriptWasDeleted")); - mScriptEd->setItemRemoved(true); - } - else if (mDirty) - { - std::string item_path = get_category_path(item->getParentUUID()); - getChild("path_txt")->setValue(item_path); - getChild("path_txt")->setToolTip(item_path); - } - LLPreview::draw(); -} -// virtual -void LLPreviewLSL::callbackLSLCompileSucceeded() -{ - LL_INFOS() << "LSL Bytecode saved" << LL_ENDL; - mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); - mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); - closeIfNeeded(); -} - -// virtual -void LLPreviewLSL::callbackLSLCompileFailed(const LLSD& compile_errors) -{ - LL_INFOS() << "Compile failed!" << LL_ENDL; - - for(LLSD::array_const_iterator line = compile_errors.beginArray(); - line < compile_errors.endArray(); - line++) - { - LLSD row; - std::string error_message = line->asString(); - LLStringUtil::stripNonprintable(error_message); - row["columns"][0]["value"] = error_message; - row["columns"][0]["font"] = "OCRA"; - mScriptEd->mErrorList->addElement(row); - } - mScriptEd->selectFirstError(); - closeIfNeeded(); -} - -void LLPreviewLSL::loadAsset() -{ - // *HACK: we poke into inventory to see if it's there, and if so, - // then it might be part of the inventory library. If it's in the - // library, then you can see the script, but not modify it. - const LLInventoryItem* item = gInventory.getItem(mItemUUID); - bool is_library = item - && !gInventory.isObjectDescendentOf(mItemUUID, - gInventory.getRootFolderID()); - if(!item) - { - // do the more generic search. - getItem(); - } - if(item) - { - bool is_copyable = gAgent.allowOperation(PERM_COPY, - item->getPermissions(), GP_OBJECT_MANIPULATE); - bool is_modifiable = gAgent.allowOperation(PERM_MODIFY, - item->getPermissions(), GP_OBJECT_MANIPULATE); - if (gAgent.isGodlike() || (is_copyable && (is_modifiable || is_library))) - { - LLUUID* new_uuid = new LLUUID(mItemUUID); - gAssetStorage->getInvItemAsset(LLHost(), - gAgent.getID(), - gAgent.getSessionID(), - item->getPermissions().getOwner(), - LLUUID::null, - item->getUUID(), - item->getAssetUUID(), - item->getType(), - &LLPreviewLSL::onLoadComplete, - (void*)new_uuid, - true); - mAssetStatus = PREVIEW_ASSET_LOADING; - } - else - { - mScriptEd->setScriptText(mScriptEd->getString("can_not_view"), false); - mScriptEd->mEditor->makePristine(); - mScriptEd->mFunctions->setEnabled(false); - mAssetStatus = PREVIEW_ASSET_LOADED; - } - 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; - } -} - - -bool LLPreviewLSL::canClose() -{ - return mScriptEd->canClose(); -} - -void LLPreviewLSL::closeIfNeeded() -{ - // Find our window and close it if requested. - getWindow()->decBusyCount(); - mPendingUploads--; - if (mPendingUploads <= 0 && mCloseAfterSave) - { - closeFloater(); - } -} - -void LLPreviewLSL::onSearchReplace(void* userdata) -{ - LLPreviewLSL* self = (LLPreviewLSL*)userdata; - LLScriptEdCore* sec = self->mScriptEd; - LLFloaterScriptSearch::show(sec); -} - -// static -void LLPreviewLSL::onLoad(void* userdata) -{ - LLPreviewLSL* self = (LLPreviewLSL*)userdata; - self->loadAsset(); -} - -// static -void LLPreviewLSL::onSave(void* userdata, bool close_after_save) -{ - LLPreviewLSL* self = (LLPreviewLSL*)userdata; - self->mCloseAfterSave = close_after_save; - self->saveIfNeeded(); -} - -/*static*/ -void LLPreviewLSL::finishedLSLUpload(LLUUID itemId, LLSD response) -{ - // Find our window and close it if requested. - LLPreviewLSL* preview = LLFloaterReg::findTypedInstance("preview_script", LLSD(itemId)); - if (preview) - { - // Bytecode save completed - if (response["compiled"]) - { - preview->callbackLSLCompileSucceeded(); - } - else - { - preview->callbackLSLCompileFailed(response["errors"]); - } - } -} - -bool LLPreviewLSL::failedLSLUpload(LLUUID itemId, LLUUID taskId, LLSD response, std::string reason) -{ - LLSD floater_key; - if (taskId.notNull()) - { - floater_key["taskid"] = taskId; - floater_key["itemid"] = itemId; - } - else - { - floater_key = LLSD(itemId); - } - - LLPreviewLSL* preview = LLFloaterReg::findTypedInstance("preview_script", floater_key); - if (preview) - { - // unfreeze floater - LLSD errors; - errors.append(LLTrans::getString("UploadFailed") + reason); - preview->callbackLSLCompileFailed(errors); - return true; - } - - return false; -} - -// 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. -void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/) -{ - if (!mScriptEd->hasChanged()) - { - return; - } - - mPendingUploads = 0; - mScriptEd->mErrorList->deleteAllItems(); - mScriptEd->mEditor->makePristine(); - - if (sync) - { - mScriptEd->sync(); - } - - if (!gAgent.getRegion()) return; - const LLInventoryItem *inv_item = getItem(); - // save it out to asset server - std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent"); - if(inv_item) - { - getWindow()->incBusyCount(); - mPendingUploads++; - if (!url.empty()) - { - std::string buffer(mScriptEd->mEditor->getText()); - - LLUUID old_asset_id = inv_item->getAssetUUID().isNull() ? mScriptEd->getAssetID() : inv_item->getAssetUUID(); - - LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared(mItemUUID, buffer, - [old_asset_id](LLUUID itemId, LLUUID, LLUUID, LLSD response) { - LLFileSystem::removeFile(old_asset_id, LLAssetType::AT_LSL_TEXT); - LLPreviewLSL::finishedLSLUpload(itemId, response); - }, - LLPreviewLSL::failedLSLUpload)); - - LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); - } - } -} - -// static -void LLPreviewLSL::onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status) -{ - LL_DEBUGS() << "LLPreviewLSL::onLoadComplete: got uuid " << asset_uuid - << LL_ENDL; - LLUUID* item_uuid = (LLUUID*)user_data; - LLPreviewLSL* preview = LLFloaterReg::findTypedInstance("preview_script", *item_uuid); - if( preview ) - { - if(0 == status) - { - LLFileSystem file(asset_uuid, type); - S32 file_length = file.getSize(); - - std::vector buffer(file_length+1); - file.read((U8*)&buffer[0], file_length); - - // put a EOS at the end - buffer[file_length] = 0; - preview->mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), true); - preview->mScriptEd->mEditor->makePristine(); - - std::string script_name = DEFAULT_SCRIPT_NAME; - LLInventoryItem* item = gInventory.getItem(*item_uuid); - bool is_modifiable = false; - if (item) - { - if (!item->getName().empty()) - { - script_name = item->getName(); - } - if (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) - { - is_modifiable = true; - } - } - preview->mScriptEd->setScriptName(script_name); - preview->mScriptEd->setEnableEditing(is_modifiable); - preview->mScriptEd->setAssetID(asset_uuid); - preview->mAssetStatus = PREVIEW_ASSET_LOADED; - } - else - { - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || - LL_ERR_FILE_EMPTY == status) - { - LLNotificationsUtil::add("ScriptMissing"); - } - else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) - { - LLNotificationsUtil::add("ScriptNoPermissions"); - } - else - { - LLNotificationsUtil::add("UnableToLoadScript"); - } - - preview->mAssetStatus = PREVIEW_ASSET_ERROR; - LL_WARNS() << "Problem loading script: " << status << LL_ENDL; - } - } - delete item_uuid; -} - - -/// --------------------------------------------------------------------------- -/// LLLiveLSLEditor -/// --------------------------------------------------------------------------- - - -//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) : - LLScriptEdContainer(key), - mAskedForRunningInfo(false), - mHaveRunningInfo(false), - mCloseAfterSave(false), - mPendingUploads(0), - mIsModifiable(false), - mIsNew(false), - mIsSaving(false), - mObjectName("") -{ - mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); -} - -bool LLLiveLSLEditor::postBuild() -{ - childSetCommitCallback("running", LLLiveLSLEditor::onRunningCheckboxClicked, this); - getChildView("running")->setEnabled(false); - - childSetAction("Reset",&LLLiveLSLEditor::onReset,this); - getChildView("Reset")->setEnabled(true); - - mMonoCheckbox = getChild("mono"); - childSetCommitCallback("mono", &LLLiveLSLEditor::onMonoCheckboxClicked, this); - getChildView("mono")->setEnabled(true); - - mScriptEd->mEditor->makePristine(); - mScriptEd->mEditor->setFocus(true); - - - mExperiences = getChild("Experiences..."); - mExperiences->setCommitCallback(boost::bind(&LLLiveLSLEditor::experienceChanged, this)); - - mExperienceEnabled = getChild("enable_xp"); - - childSetCommitCallback("enable_xp", onToggleExperience, this); - childSetCommitCallback("view_profile", onViewProfile, this); - - - return LLPreview::postBuild(); -} - -// virtual -void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id, - const LLUUID& item_id, - bool is_script_running) -{ - LL_DEBUGS() << "LSL Bytecode saved" << LL_ENDL; - mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); - mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); - getChild("running")->set(is_script_running); - mIsSaving = false; - closeIfNeeded(); -} - -// virtual -void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors) -{ - LL_DEBUGS() << "Compile failed!" << LL_ENDL; - for(LLSD::array_const_iterator line = compile_errors.beginArray(); - line < compile_errors.endArray(); - line++) - { - LLSD row; - std::string error_message = line->asString(); - LLStringUtil::stripNonprintable(error_message); - row["columns"][0]["value"] = error_message; - // *TODO: change to "MONOSPACE" and change llfontgl.cpp? - row["columns"][0]["font"] = "OCRA"; - mScriptEd->mErrorList->addElement(row); - } - mScriptEd->selectFirstError(); - mIsSaving = false; - closeIfNeeded(); -} - -void LLLiveLSLEditor::loadAsset() -{ - //LL_INFOS() << "LLLiveLSLEditor::loadAsset()" << LL_ENDL; - if(!mIsNew) - { - LLViewerObject* object = gObjectList.findObject(mObjectUUID); - if(object) - { - LLViewerInventoryItem* item = dynamic_cast(object->getInventoryObject(mItemUUID)); - - if(item) - { - LLViewerRegion* region = object->getRegion(); - std::string url = std::string(); - if(region) - { - url = region->getCapability("GetMetadata"); - } - LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), url, - boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle(), _1)); - - bool isGodlike = gAgent.isGodlike(); - bool copyManipulate = gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE); - mIsModifiable = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); - - if(!isGodlike && (!copyManipulate || !mIsModifiable)) - { - mItem = new LLViewerInventoryItem(item); - mScriptEd->setScriptText(getString("not_allowed"), false); - mScriptEd->mEditor->makePristine(); - mScriptEd->enableSave(false); - mAssetStatus = PREVIEW_ASSET_LOADED; - } - else if(copyManipulate || isGodlike) - { - mItem = new LLViewerInventoryItem(item); - // request the text from the object - LLSD* user_data = new LLSD(); - user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID); - gAssetStorage->getInvItemAsset(object->getRegion()->getHost(), - gAgent.getID(), - gAgent.getSessionID(), - item->getPermissions().getOwner(), - object->getID(), - item->getUUID(), - item->getAssetUUID(), - item->getType(), - &LLLiveLSLEditor::onLoadComplete, - (void*)user_data, - true); - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_GetScriptRunning); - msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID); - msg->addUUIDFast(_PREHASH_ItemID, mItemUUID); - msg->sendReliable(object->getRegion()->getHost()); - mAskedForRunningInfo = true; - mAssetStatus = PREVIEW_ASSET_LOADING; - } - } - - if(mItem.isNull()) - { - mScriptEd->setScriptText(LLStringUtil::null, false); - mScriptEd->mEditor->makePristine(); - mAssetStatus = PREVIEW_ASSET_LOADED; - mIsModifiable = false; - } - - refreshFromItem(); - getChild("obj_name")->setValue(mObjectName); - // This is commented out, because we don't completely - // handle script exports yet. - /* - // request the exports from the object - gMessageSystem->newMessage("GetScriptExports"); - gMessageSystem->nextBlock("ScriptBlock"); - gMessageSystem->addUUID("AgentID", gAgent.getID()); - U32 local_id = object->getLocalID(); - gMessageSystem->addData("LocalID", &local_id); - gMessageSystem->addUUID("ItemID", mItemUUID); - LLHost host(object->getRegion()->getIP(), - object->getRegion()->getPort()); - gMessageSystem->sendReliable(host); - */ - } - } - else - { - mScriptEd->setScriptText(std::string(HELLO_LSL), true); - mScriptEd->enableSave(false); - LLPermissions perm; - perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, gAgent.getGroupID()); - perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, PERM_MOVE | PERM_TRANSFER); - mItem = new LLViewerInventoryItem(mItemUUID, - mObjectUUID, - perm, - LLUUID::null, - LLAssetType::AT_LSL_TEXT, - LLInventoryType::IT_LSL, - DEFAULT_SCRIPT_NAME, - DEFAULT_SCRIPT_DESC, - LLSaleInfo::DEFAULT, - LLInventoryItemFlags::II_FLAGS_NONE, - time_corrected()); - mAssetStatus = PREVIEW_ASSET_LOADED; - } - - requestExperiences(); -} - -// static -void LLLiveLSLEditor::onLoadComplete(const LLUUID& asset_id, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status) -{ - LL_DEBUGS() << "LLLiveLSLEditor::onLoadComplete: got uuid " << asset_id - << LL_ENDL; - LLSD* floater_key = (LLSD*)user_data; - - LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance("preview_scriptedit", *floater_key); - - if(instance ) - { - if( LL_ERR_NOERR == status ) - { - instance->loadScriptText(asset_id, type); - instance->mScriptEd->setEnableEditing(true); - instance->mAssetStatus = PREVIEW_ASSET_LOADED; - instance->mScriptEd->setAssetID(asset_id); - } - else - { - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || - LL_ERR_FILE_EMPTY == status) - { - LLNotificationsUtil::add("ScriptMissing"); - } - else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) - { - LLNotificationsUtil::add("ScriptNoPermissions"); - } - else - { - LLNotificationsUtil::add("UnableToLoadScript"); - } - instance->mAssetStatus = PREVIEW_ASSET_ERROR; - } - } - - delete floater_key; -} - -void LLLiveLSLEditor::loadScriptText(const LLUUID &uuid, LLAssetType::EType type) -{ - LLFileSystem file(uuid, type); - S32 file_length = file.getSize(); - std::vector buffer(file_length + 1); - file.read((U8*)&buffer[0], file_length); - - if (file.getLastBytesRead() != file_length || - file_length <= 0) - { - LL_WARNS() << "Error reading " << uuid << ":" << type << LL_ENDL; - } - - buffer[file_length] = '\0'; - - mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), true); - mScriptEd->makeEditorPristine(); - - std::string script_name = DEFAULT_SCRIPT_NAME; - const LLInventoryItem* inv_item = getItem(); - - if(inv_item) - { - script_name = inv_item->getName(); - } - mScriptEd->setScriptName(script_name); -} - - -void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata ) -{ - LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; - LLViewerObject* object = gObjectList.findObject( self->mObjectUUID ); - LLCheckBoxCtrl* runningCheckbox = self->getChild("running"); - bool running = runningCheckbox->get(); - //self->mRunningCheckbox->get(); - if( object ) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_SetScriptRunning); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectUUID); - msg->addUUIDFast(_PREHASH_ItemID, self->mItemUUID); - msg->addBOOLFast(_PREHASH_Running, running); - msg->sendReliable(object->getRegion()->getHost()); - } - else - { - runningCheckbox->set(!running); - LLNotificationsUtil::add("CouldNotStartStopScript"); - } -} - -void LLLiveLSLEditor::onReset(void *userdata) -{ - LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; - - LLViewerObject* object = gObjectList.findObject( self->mObjectUUID ); - if(object) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ScriptReset); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectUUID); - msg->addUUIDFast(_PREHASH_ItemID, self->mItemUUID); - msg->sendReliable(object->getRegion()->getHost()); - } - else - { - LLNotificationsUtil::add("CouldNotStartStopScript"); - } -} - -void LLLiveLSLEditor::draw() -{ - LLViewerObject* object = gObjectList.findObject(mObjectUUID); - LLCheckBoxCtrl* runningCheckbox = getChild( "running"); - if(object && mAskedForRunningInfo && mHaveRunningInfo) - { - if(object->permAnyOwner()) - { - runningCheckbox->setLabel(getString("script_running")); - runningCheckbox->setEnabled(!mIsSaving); - } - else - { - runningCheckbox->setLabel(getString("public_objects_can_not_run")); - runningCheckbox->setEnabled(false); - - // *FIX: Set it to false so that the ui is correct for - // a box that is released to public. It could be - // incorrect after a release/claim cycle, but will be - // correct after clicking on it. - runningCheckbox->set(false); - mMonoCheckbox->set(false); - } - } - else if(!object) - { - // HACK: Display this information in the title bar. - // Really ought to put in main window. - setTitle(LLTrans::getString("ObjectOutOfRange")); - runningCheckbox->setEnabled(false); - mMonoCheckbox->setEnabled(false); - // object may have fallen out of range. - mHaveRunningInfo = false; - } - - LLPreview::draw(); -} - - -void LLLiveLSLEditor::onSearchReplace(void* userdata) -{ - LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; - - LLScriptEdCore* sec = self->mScriptEd; - LLFloaterScriptSearch::show(sec); -} - -struct LLLiveLSLSaveData -{ - LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, bool active); - LLUUID mSaveObjectID; - LLPointer mItem; - bool mActive; -}; - -LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id, - const LLViewerInventoryItem* item, - bool active) : - mSaveObjectID(id), - mActive(active) -{ - llassert(item); - mItem = new LLViewerInventoryItem(item); -} - -/*static*/ -void LLLiveLSLEditor::finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, bool isRunning) -{ - LLSD floater_key; - floater_key["taskid"] = taskId; - floater_key["itemid"] = itemId; - - LLLiveLSLEditor* preview = LLFloaterReg::findTypedInstance("preview_scriptedit", floater_key); - if (preview) - { - preview->mItem->setAssetUUID(newAssetId); - preview->mScriptEd->setAssetID(newAssetId); - - // Bytecode save completed - if (response["compiled"]) - { - preview->callbackLSLCompileSucceeded(taskId, itemId, isRunning); - } - else - { - preview->callbackLSLCompileFailed(response["errors"]); - } - } -} - -// virtual -void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) -{ - LLViewerObject* object = gObjectList.findObject(mObjectUUID); - if (!object) - { - LLNotificationsUtil::add("SaveScriptFailObjectNotFound"); - return; - } - - if (mItem.isNull() || !mItem->isFinished()) - { - // $NOTE: While the error message may not be exactly correct, - // it's pretty close. - LLNotificationsUtil::add("SaveScriptFailObjectNotFound"); - return; - } - - // get the latest info about it. We used to be losing the script - // name on save, because the viewer object version of the item, - // and the editor version would get out of synch. Here's a good - // place to synch them back up. - LLInventoryItem* inv_item = dynamic_cast(object->getInventoryObject(mItemUUID)); - if (inv_item) - { - mItem->copyItem(inv_item); - } - - // Don't need to save if we're pristine - if (!mScriptEd->hasChanged()) - { - return; - } - - mPendingUploads = 0; - - // save the script - mScriptEd->enableSave(false); - mScriptEd->mEditor->makePristine(); - mScriptEd->mErrorList->deleteAllItems(); - mScriptEd->mEditor->makePristine(); - - if (sync) - { - mScriptEd->sync(); - } - - bool isRunning = getChild("running")->get(); - getWindow()->incBusyCount(); - mPendingUploads++; - - std::string url = object->getRegion()->getCapability("UpdateScriptTask"); - - if (!url.empty()) - { - std::string buffer(mScriptEd->mEditor->getText()); - LLUUID old_asset_id = mScriptEd->getAssetID(); - - LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared(mObjectUUID, mItemUUID, - monoChecked() ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2, - isRunning, mScriptEd->getAssociatedExperience(), buffer, - [isRunning, old_asset_id](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) { - LLFileSystem::removeFile(old_asset_id, LLAssetType::AT_LSL_TEXT); - LLLiveLSLEditor::finishLSLUpload(itemId, taskId, newAssetId, response, isRunning); - }, - nullptr)); // needs failure handling? - - LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); - } -} - -bool LLLiveLSLEditor::canClose() -{ - return mScriptEd->canClose(); -} - -void LLLiveLSLEditor::closeIfNeeded() -{ - getWindow()->decBusyCount(); - mPendingUploads--; - if ((mPendingUploads <= 0) && mCloseAfterSave) - { - closeFloater(); - } -} - -// static -void LLLiveLSLEditor::onLoad(void* userdata) -{ - LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; - self->loadAsset(); -} - -// static -void LLLiveLSLEditor::onSave(void* userdata, bool close_after_save) -{ - if (LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata) - { - self->mCloseAfterSave = close_after_save; - self->mScriptEd->mErrorList->setCommentText(""); - self->saveIfNeeded(); - } -} - -// static -void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) -{ - LLUUID item_id; - LLUUID object_id; - msg->getUUIDFast(_PREHASH_Script, _PREHASH_ObjectID, object_id); - msg->getUUIDFast(_PREHASH_Script, _PREHASH_ItemID, item_id); - - LLSD floater_key; - floater_key["taskid"] = object_id; - floater_key["itemid"] = item_id; - if (LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance("preview_scriptedit", floater_key)) - { - instance->mHaveRunningInfo = true; - bool running; - msg->getBOOLFast(_PREHASH_Script, _PREHASH_Running, running); - LLCheckBoxCtrl* runningCheckbox = instance->getChild("running"); - runningCheckbox->set(running); - bool mono; - msg->getBOOLFast(_PREHASH_Script, "Mono", mono); - LLCheckBoxCtrl* monoCheckbox = instance->getChild("mono"); - monoCheckbox->setEnabled(instance->getIsModifiable() && have_script_upload_cap(object_id)); - monoCheckbox->set(mono); - } -} - -void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata) -{ - LLLiveLSLEditor* self = static_cast(userdata); - self->mMonoCheckbox->setEnabled(have_script_upload_cap(self->mObjectUUID)); - self->mScriptEd->enableSave(self->getIsModifiable()); -} - -bool LLLiveLSLEditor::monoChecked() const -{ - return mMonoCheckbox && mMonoCheckbox->getValue(); -} - -void LLLiveLSLEditor::setAssociatedExperience( LLHandle editor, const LLSD& experience ) -{ - if (LLLiveLSLEditor* scriptEd = editor.get()) - { - LLUUID id; - if (experience.has(LLExperienceCache::EXPERIENCE_ID)) - { - id=experience[LLExperienceCache::EXPERIENCE_ID].asUUID(); - } - scriptEd->mScriptEd->setAssociatedExperience(id); - scriptEd->updateExperiencePanel(); - } -} +/** + * @file llpreviewscript.cpp + * @brief LLPreviewScript class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpreviewscript.h" + +#include "llassetstorage.h" +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "lldir.h" +#include "llexternaleditor.h" +#include "llfilepicker.h" +#include "llfloaterreg.h" +#include "llinventorydefines.h" +#include "llinventorymodel.h" +#include "llkeyboard.h" +#include "lllineeditor.h" +#include "llmd5.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 "lltooldraganddrop.h" +#include "llfilesystem.h" + +#include "llagent.h" +#include "llmenugl.h" +#include "roles_constants.h" +#include "llselectmgr.h" +#include "llviewerinventory.h" +#include "llviewermenu.h" +#include "llviewermenufile.h" // LLFilePickerReplyThread +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llkeyboard.h" +#include "llscrollcontainer.h" +#include "llcheckboxctrl.h" +#include "llscripteditor.h" +#include "llselectmgr.h" +#include "lltooldraganddrop.h" +#include "llscrolllistctrl.h" +#include "lltextbox.h" +#include "llslider.h" +#include "lldir.h" +#include "llcombobox.h" +#include "llviewerstats.h" +#include "llviewerwindow.h" +#include "lluictrlfactory.h" +#include "llmediactrl.h" +#include "lluictrlfactory.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llappviewer.h" +#include "llfloatergotoline.h" +#include "llexperiencecache.h" +#include "llfloaterexperienceprofile.h" +#include "llviewerassetupload.h" +#include "lltoggleablemenu.h" +#include "llmenubutton.h" +#include "llinventoryfunctions.h" + +const std::string HELLO_LSL = + "default\n" + "{\n" + " state_entry()\n" + " {\n" + " llSay(0, \"Hello, Avatar!\");\n" + " }\n" + "\n" + " touch_start(integer total_number)\n" + " {\n" + " llSay(0, \"Touched.\");\n" + " }\n" + "}\n"; +const std::string HELP_LSL_PORTAL_TOPIC = "LSL_Portal"; + +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_HISTORY_COUNT = 10; +const F32 LIVE_HELP_REFRESH_TIME = 1.f; + +static bool have_script_upload_cap(LLUUID& object_id) +{ + LLViewerObject* object = gObjectList.findObject(object_id); + return object && (! object->getRegion()->getCapability("UpdateScriptTask").empty()); +} + +/// --------------------------------------------------------------------------- +/// LLLiveLSLFile +/// --------------------------------------------------------------------------- + +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 +{ +public: + LLFloaterScriptSearch(LLScriptEdCore* editor_core); + ~LLFloaterScriptSearch(); + + /*virtual*/ bool postBuild(); + static void show(LLScriptEdCore* editor_core); + static void onBtnSearch(void* userdata); + void handleBtnSearch(); + + static void onBtnReplace(void* userdata); + void handleBtnReplace(); + + static void onBtnReplaceAll(void* userdata); + void handleBtnReplaceAll(); + + 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) +{ + buildFromFile("floater_script_search.xml"); + + sInstance = this; + + // find floater in which script panel is embedded + LLView* viewp = (LLView*)editor_core; + while(viewp) + { + LLFloater* floaterp = dynamic_cast(viewp); + if (floaterp) + { + floaterp->addDependentFloater(this); + break; + } + viewp = viewp->getParent(); + } +} + +bool LLFloaterScriptSearch::postBuild() +{ + mReplaceBox = getChild("replace_text"); + mSearchBox = getChild("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); + + setDefaultBtn("search_btn"); + + return true; +} + +//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; + } + + if (!sInstance) + { + // sInstance will be assigned in the constructor. + new LLFloaterScriptSearch(editor_core); + sInstance->mSearchBox->setValue(search_text); + sInstance->mReplaceBox->setValue(replace_text); + } + + sInstance->openFloater(); +} + +LLFloaterScriptSearch::~LLFloaterScriptSearch() +{ + sInstance = NULL; +} + +// static +void LLFloaterScriptSearch::onBtnSearch(void *userdata) +{ + LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata; + self->handleBtnSearch(); +} + +void LLFloaterScriptSearch::handleBtnSearch() +{ + LLCheckBoxCtrl* caseChk = getChild("case_text"); + mEditorCore->mEditor->selectNext(mSearchBox->getValue().asString(), caseChk->get()); +} + +// static +void LLFloaterScriptSearch::onBtnReplace(void *userdata) +{ + LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata; + self->handleBtnReplace(); +} + +void LLFloaterScriptSearch::handleBtnReplace() +{ + LLCheckBoxCtrl* caseChk = getChild("case_text"); + mEditorCore->mEditor->replaceText(mSearchBox->getValue().asString(), mReplaceBox->getValue().asString(), caseChk->get()); +} + +// static +void LLFloaterScriptSearch::onBtnReplaceAll(void *userdata) +{ + LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata; + self->handleBtnReplaceAll(); +} + +void LLFloaterScriptSearch::handleBtnReplaceAll() +{ + LLCheckBoxCtrl* caseChk = getChild("case_text"); + 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("case_text"); + mEditorCore->mEditor->selectNext(mSearchBox->getValue().asString(), caseChk->get()); + } +} + +/// --------------------------------------------------------------------------- + +class LLScriptMovedObserver : public LLInventoryObserver +{ + public: + LLScriptMovedObserver(LLPreviewLSL *floater) : mPreview(floater) { gInventory.addObserver(this); } + virtual ~LLScriptMovedObserver() { gInventory.removeObserver(this); } + virtual void changed(U32 mask); + + private: + LLPreviewLSL *mPreview; +}; + +void LLScriptMovedObserver::changed(U32 mask) +{ + const std::set &mChangedItemIDs = gInventory.getChangedIDs(); + std::set::const_iterator it; + + const LLUUID &item_id = mPreview->getScriptID(); + + for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++) + { + if (*it == item_id) + { + if ((mask & (LLInventoryObserver::STRUCTURE)) != 0) + { + mPreview->setDirty(); + } + } + } +} + +/// --------------------------------------------------------------------------- +/// LLScriptEdCore +/// --------------------------------------------------------------------------- + +struct LLSECKeywordCompare +{ + bool operator()(const std::string& lhs, const std::string& rhs) + { + return (LLStringUtil::compareDictInsensitive( lhs, rhs ) < 0 ); + } +}; + +LLScriptEdCore::LLScriptEdCore( + LLScriptEdContainer* container, + const std::string& sample, + const LLHandle& 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(), + mSampleText(sample), + mEditor( NULL ), + mLoadCallback( load_callback ), + mSaveCallback( save_callback ), + mSearchReplaceCallback( search_replace_callback ), + mUserdata( userdata ), + mForceClose( false ), + mLastHelpToken(NULL), + mLiveHelpHistorySize(0), + mEnableSave(false), + mLiveFile(NULL), + mLive(live), + mContainer(container), + mHasScriptData(false), + mScriptRemoved(false), + mSaveDialogShown(false) +{ + setFollowsAll(); + setBorderVisible(false); + + setXMLFilename("panel_script_ed.xml"); + llassert_always(mContainer != NULL); +} + +LLScriptEdCore::~LLScriptEdCore() +{ + deleteBridges(); + + // If the search window is up for this editor, close it. + LLFloaterScriptSearch* script_search = LLFloaterScriptSearch::getInstance(); + if (script_search && script_search->getEditorCore() == this) + { + script_search->closeFloater(); + delete script_search; + } + + delete mLiveFile; + if (mSyntaxIDConnection.connected()) + { + mSyntaxIDConnection.disconnect(); + } +} + +void LLLiveLSLEditor::experienceChanged() +{ + if(mScriptEd->getAssociatedExperience() != mExperiences->getSelectedValue().asUUID()) + { + mScriptEd->enableSave(getIsModifiable()); + //getChildView("Save_btn")->setEnabled(true); + mScriptEd->setAssociatedExperience(mExperiences->getSelectedValue().asUUID()); + updateExperiencePanel(); + } +} + +void LLLiveLSLEditor::onViewProfile( LLUICtrl *ui, void* userdata ) +{ + LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; + + LLUUID id; + if(self->mExperienceEnabled->get()) + { + id=self->mScriptEd->getAssociatedExperience(); + if(id.notNull()) + { + LLFloaterReg::showInstance("experience_profile", id, true); + } + } + +} + +void LLLiveLSLEditor::onToggleExperience( LLUICtrl *ui, void* userdata ) +{ + LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; + + LLUUID id; + if(self->mExperienceEnabled->get()) + { + if(self->mScriptEd->getAssociatedExperience().isNull()) + { + id=self->mExperienceIds.beginArray()->asUUID(); + } + } + + if(id != self->mScriptEd->getAssociatedExperience()) + { + self->mScriptEd->enableSave(self->getIsModifiable()); + } + self->mScriptEd->setAssociatedExperience(id); + + self->updateExperiencePanel(); +} + +bool LLScriptEdCore::postBuild() +{ + mErrorList = getChild("lsl errors"); + + mFunctions = getChild("Insert..."); + + childSetCommitCallback("Insert...", &LLScriptEdCore::onBtnInsertFunction, this); + + mEditor = getChild("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)); + + // Intialise keyword highlighting for the current simulator's version of LSL + LLSyntaxIdLSL::getInstance()->initialize(); + processKeywords(); + + mCommitCallbackRegistrar.add("FontSize.Set", boost::bind(&LLScriptEdCore::onChangeFontSize, this, _2)); + mEnableCallbackRegistrar.add("FontSize.Check", boost::bind(&LLScriptEdCore::isFontSizeChecked, this, _2)); + + LLToggleableMenu *context_menu = LLUICtrlFactory::getInstance()->createFromFile( + "menu_lsl_font_size.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + getChild("font_btn")->setMenu(context_menu, LLMenuButton::MP_BOTTOM_LEFT, true); + + return true; +} + +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->getType() == LLKeywordToken::TT_FUNCTION) + { + primary_keywords.push_back( wstring_to_utf8str(token->getToken()) ); + } + else + { + secondary_keywords.push_back( wstring_to_utf8str(token->getToken()) ); + } + } + for (string_vec_t::const_iterator iter = primary_keywords.begin(); + iter!= primary_keywords.end(); ++iter) + { + mFunctions->add(*iter); + } + for (string_vec_t::const_iterator iter = secondary_keywords.begin(); + iter!= secondary_keywords.end(); ++iter) + { + mFunctions->add(*iter); + } +} + +void LLScriptEdCore::initMenu() +{ + // *TODO: Skinning - make these callbacks data driven + LLMenuItemCallGL* menuItem; + + menuItem = getChild("Save"); + menuItem->setClickCallback(boost::bind(&LLScriptEdCore::doSave, this, false)); + menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::hasChanged, this)); + + menuItem = getChild("Revert All Changes"); + menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnUndoChanges, this)); + menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::hasChanged, this)); + + menuItem = getChild("Undo"); + menuItem->setClickCallback(boost::bind(&LLTextEditor::undo, mEditor)); + menuItem->setEnableCallback(boost::bind(&LLTextEditor::canUndo, mEditor)); + + menuItem = getChild("Redo"); + menuItem->setClickCallback(boost::bind(&LLTextEditor::redo, mEditor)); + menuItem->setEnableCallback(boost::bind(&LLTextEditor::canRedo, mEditor)); + + menuItem = getChild("Cut"); + menuItem->setClickCallback(boost::bind(&LLTextEditor::cut, mEditor)); + menuItem->setEnableCallback(boost::bind(&LLTextEditor::canCut, mEditor)); + + menuItem = getChild("Copy"); + menuItem->setClickCallback(boost::bind(&LLTextEditor::copy, mEditor)); + menuItem->setEnableCallback(boost::bind(&LLTextEditor::canCopy, mEditor)); + + menuItem = getChild("Paste"); + menuItem->setClickCallback(boost::bind(&LLTextEditor::paste, mEditor)); + menuItem->setEnableCallback(boost::bind(&LLTextEditor::canPaste, mEditor)); + + menuItem = getChild("Select All"); + menuItem->setClickCallback(boost::bind(&LLTextEditor::selectAll, mEditor)); + menuItem->setEnableCallback(boost::bind(&LLTextEditor::canSelectAll, mEditor)); + + menuItem = getChild("Deselect"); + menuItem->setClickCallback(boost::bind(&LLTextEditor::deselect, mEditor)); + menuItem->setEnableCallback(boost::bind(&LLTextEditor::canDeselect, mEditor)); + + menuItem = getChild("Search / Replace..."); + menuItem->setClickCallback(boost::bind(&LLFloaterScriptSearch::show, this)); + + menuItem = getChild("Go to line..."); + menuItem->setClickCallback(boost::bind(&LLFloaterGotoLine::show, this)); + + menuItem = getChild("Keyword Help..."); + menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnDynamicHelp, this)); + + menuItem = getChild("LoadFromFile"); + menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnLoadFromFile, this)); + menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::enableLoadFromFileMenu, this)); + + menuItem = getChild("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) +{ + if (mEditor) + { + mEditor->setText(text); + mHasScriptData = is_valid; + } +} + +void LLScriptEdCore::makeEditorPristine() +{ + if (mEditor) + { + mEditor->makePristine(); + } +} + +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); + + std::string text = std::string(buffer); + LLStringUtil::replaceTabsWithSpaces(text, LLTextEditor::spacesPerTab()); + + mEditor->setText(text); + 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. + if (mLiveFile) + { + std::string tmp_file = mLiveFile->filename(); + llstat s; + if (LLFile::stat(tmp_file, &s) == 0) // file exists + { + mLiveFile->ignoreNextUpdate(); + writeToFile(tmp_file); + } + } +} + +bool LLScriptEdCore::hasChanged() +{ + if (!mEditor) return false; + + return ((!mEditor->isPristine() || mEnableSave) && mHasScriptData); +} + +void LLScriptEdCore::draw() +{ + bool script_changed = hasChanged(); + getChildView("Save_btn")->setEnabled(script_changed && !mScriptRemoved); + + if( mEditor->hasFocus() ) + { + S32 line = 0; + S32 column = 0; + mEditor->getCurrentLineAndColumn( &line, &column, false ); // don't include wordwrap + LLStringUtil::format_map_t args; + std::string cursor_pos; + args["[LINE]"] = llformat ("%d", line); + args["[COLUMN]"] = llformat ("%d", column); + cursor_pos = LLTrans::getString("CursorPos", args); + getChild("line_col")->setValue(cursor_pos); + } + else + { + getChild("line_col")->setValue(LLStringUtil::null); + } + + updateDynamicHelp(); + + LLPanel::draw(); +} + +void LLScriptEdCore::updateDynamicHelp(bool immediate) +{ + LLFloater* help_floater = mLiveHelpHandle.get(); + if (!help_floater) return; + + // update back and forward buttons + LLButton* fwd_button = help_floater->getChild("fwd_btn"); + LLButton* back_button = help_floater->getChild("back_btn"); + LLMediaCtrl* browser = help_floater->getChild("lsl_guide_html"); + back_button->setEnabled(browser->canNavigateBack()); + fwd_button->setEnabled(browser->canNavigateForward()); + + if (!immediate && !gSavedSettings.getBOOL("ScriptHelpFollowsCursor")) + { + return; + } + + LLTextSegmentPtr segment = NULL; + std::vector selected_segments; + mEditor->getSelectedSegments(selected_segments); + LLKeywordToken* token; + // try segments in selection range first + std::vector::iterator segment_iter; + for (segment_iter = selected_segments.begin(); segment_iter != selected_segments.end(); ++segment_iter) + { + token = (*segment_iter)->getToken(); + if(token && isKeyword(token)) + { + segment = *segment_iter; + break; + } + } + + // then try previous segment in case we just typed it + if (!segment) + { + const LLTextSegmentPtr test_segment = mEditor->getPreviousSegment(); + token = test_segment->getToken(); + if(token && isKeyword(token)) + { + segment = test_segment; + } + } + + if (segment) + { + if (segment->getToken() != mLastHelpToken) + { + mLastHelpToken = segment->getToken(); + mLiveHelpTimer.start(); + } + if (immediate || (mLiveHelpTimer.getStarted() && mLiveHelpTimer.getElapsedTimeF32() > LIVE_HELP_REFRESH_TIME)) + { + // Use Wtext since segment's start/end are made for wstring and will + // result in a shift for case of multi-byte symbols inside std::string. + LLWString segment_text = mEditor->getWText().substr(segment->getStart(), segment->getEnd() - segment->getStart()); + std::string help_string = wstring_to_utf8str(segment_text); + setHelpPage(help_string); + mLiveHelpTimer.stop(); + } + } + else + { + if (immediate) + { + setHelpPage(LLStringUtil::null); + } + } +} + +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(); + if (!help_floater) return; + + LLMediaCtrl* web_browser = help_floater->getChild("lsl_guide_html"); + if (!web_browser) return; + + LLComboBox* history_combo = help_floater->getChild("history_combo"); + if (!history_combo) return; + + LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); + + url_string.setArg("[LSL_STRING]", help_string.empty() ? HELP_LSL_PORTAL_TOPIC : help_string); + + addHelpItemToHistory(help_string); + + web_browser->navigateTo(url_string); + +} + + +void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string) +{ + if (help_string.empty()) return; + + LLFloater* help_floater = mLiveHelpHandle.get(); + if (!help_floater) return; + + LLComboBox* history_combo = help_floater->getChild("history_combo"); + if (!history_combo) return; + + // separate history items from full item list + if (mLiveHelpHistorySize == 0) + { + history_combo->addSeparator(ADD_TOP); + } + // delete all history items over history limit + while(mLiveHelpHistorySize > MAX_HISTORY_COUNT - 1) + { + history_combo->remove(mLiveHelpHistorySize - 1); + mLiveHelpHistorySize--; + } + + history_combo->setSimple(help_string); + S32 index = history_combo->getCurrentIndex(); + + // if help string exists in the combo box + if (index >= 0) + { + S32 cur_index = history_combo->getCurrentIndex(); + if (cur_index < mLiveHelpHistorySize) + { + // item found in history, bubble up to top + history_combo->remove(history_combo->getCurrentIndex()); + mLiveHelpHistorySize--; + } + } + history_combo->add(help_string, LLSD(help_string), ADD_TOP); + history_combo->selectFirstItem(); + mLiveHelpHistorySize++; +} + +bool LLScriptEdCore::canClose() +{ + if(mForceClose || !hasChanged() || mScriptRemoved) + { + return true; + } + else + { + if(!mSaveDialogShown) + { + mSaveDialogShown = true; + // Bring up view-modal dialog: Save changes? Yes, No, Cancel + 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 ) +{ + mSaveDialogShown = false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch( option ) + { + case 0: // "Yes" + // close after saving + doSave( true ); + break; + + case 1: // "No" + mForceClose = true; + // This will close immediately because mForceClose is true, so we won't + // infinite loop with these dialogs. JC + ((LLFloater*) getParent())->closeFloater(); + break; + + case 2: // "Cancel" + default: + // If we were quitting, we didn't really mean it. + LLAppViewer::instance()->abortQuit(); + break; + } + return false; +} + +void LLScriptEdCore::onBtnDynamicHelp() +{ + LLFloater* live_help_floater = mLiveHelpHandle.get(); + if (!live_help_floater) + { + live_help_floater = new LLFloater(LLSD()); + live_help_floater->buildFromFile("floater_lsl_guide.xml"); + LLFloater* parent = dynamic_cast(getParent()); + llassert(parent); + if (parent) + parent->addDependentFloater(live_help_floater, true); + live_help_floater->childSetCommitCallback("lock_check", onCheckLock, this); + live_help_floater->getChild("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); + + LLMediaCtrl* browser = live_help_floater->getChild("lsl_guide_html"); + browser->setAlwaysRefresh(true); + + LLComboBox* help_combo = live_help_floater->getChild("history_combo"); + LLKeywordToken *token; + LLKeywords::keyword_iterator_t token_it; + for (token_it = mEditor->keywordsBegin(); + token_it != mEditor->keywordsEnd(); + ++token_it) + { + token = token_it->second; + help_combo->add(wstring_to_utf8str(token->getToken())); + } + help_combo->sortByName(); + + // re-initialize help variables + mLastHelpToken = NULL; + mLiveHelpHandle = live_help_floater->getHandle(); + mLiveHelpHistorySize = 0; + } + + bool visible = true; + bool take_focus = true; + live_help_floater->setVisible(visible); + live_help_floater->setFrontmost(take_focus); + + updateDynamicHelp(true); +} + +//static +void LLScriptEdCore::onClickBack(void* userdata) +{ + LLScriptEdCore* corep = (LLScriptEdCore*)userdata; + LLFloater* live_help_floater = corep->mLiveHelpHandle.get(); + if (live_help_floater) + { + LLMediaCtrl* browserp = live_help_floater->getChild("lsl_guide_html"); + if (browserp) + { + browserp->navigateBack(); + } + } +} + +//static +void LLScriptEdCore::onClickForward(void* userdata) +{ + LLScriptEdCore* corep = (LLScriptEdCore*)userdata; + LLFloater* live_help_floater = corep->mLiveHelpHandle.get(); + if (live_help_floater) + { + LLMediaCtrl* browserp = live_help_floater->getChild("lsl_guide_html"); + if (browserp) + { + browserp->navigateForward(); + } + } +} + +// static +void LLScriptEdCore::onCheckLock(LLUICtrl* ctrl, void* userdata) +{ + LLScriptEdCore* corep = (LLScriptEdCore*)userdata; + + // clear out token any time we lock the frame, so we will refresh web page immediately when unlocked + gSavedSettings.setBOOL("ScriptHelpFollowsCursor", ctrl->getValue().asBoolean()); + + corep->mLastHelpToken = NULL; +} + +// static +void LLScriptEdCore::onBtnInsertSample(void* userdata) +{ + LLScriptEdCore* self = (LLScriptEdCore*) userdata; + + // Insert sample code + self->mEditor->selectAll(); + self->mEditor->cut(); + self->mEditor->insertText(self->mSampleText); +} + +// static +void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata) +{ + LLScriptEdCore* corep = (LLScriptEdCore*)userdata; + + LLFloater* live_help_floater = corep->mLiveHelpHandle.get(); + if (live_help_floater) + { + std::string help_string = ctrl->getValue().asString(); + + corep->addHelpItemToHistory(help_string); + + LLMediaCtrl* web_browser = live_help_floater->getChild("lsl_guide_html"); + LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); + url_string.setArg("[LSL_STRING]", help_string); + web_browser->navigateTo(url_string); + } +} + +// static +void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata) +{ + LLScriptEdCore* self = (LLScriptEdCore*) userdata; + + // Insert sample code + if(self->mEditor->getEnabled()) + { + self->mEditor->insertText(self->mFunctions->getSimple()); + } + self->mEditor->setFocus(true); + self->setHelpPage(self->mFunctions->getSimple()); +} + +void LLScriptEdCore::doSave( bool close_after_save ) +{ + add(LLStatViewer::LSL_SAVES, 1); + + if( mSaveCallback ) + { + mSaveCallback( mUserdata, close_after_save ); + } +} + +void LLScriptEdCore::openInExternalEditor() +{ + delete mLiveFile; // deletes file + + // Generate a suitable filename + std::string script_name = mScriptName; + std::string forbidden_chars = "<>:\"\\/|?*"; + for (std::string::iterator c = forbidden_chars.begin(); c != forbidden_chars.end(); c++) + { + script_name.erase(std::remove(script_name.begin(), script_name.end(), *c), script_name.end()); + } + std::string filename = mContainer->getTmpFileName(script_name); + + // Save the script to a temporary file. + if (!writeToFile(filename)) + { + // In case some characters from script name are forbidden + // and not accounted for, name is too long or some other issue, + // try file that doesn't include script name + script_name.clear(); + filename = mContainer->getTmpFileName(script_name); + 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 = LLTrans::getString("ExternalEditorNotSet"); + } + 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() ) + { + LLNotificationsUtil::add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, this, _1, _2)); + } +} + +// static +void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data) +{ + LLScriptEdCore* self = (LLScriptEdCore*)user_data; + LLScrollListItem* item = self->mErrorList->getFirstSelected(); + if(item) + { + // *FIX: replace with boost grep + S32 row = 0; + S32 column = 0; + const LLScrollListCell* cell = item->getColumn(0); + std::string line(cell->getValue().asString()); + line.erase(0, 1); + LLStringUtil::replaceChar(line, ',',' '); + LLStringUtil::replaceChar(line, ')',' '); + sscanf(line.c_str(), "%d %d", &row, &column); + //LL_INFOS() << "LLScriptEdCore::onErrorList() - " << row << ", " + //<< column << LL_ENDL; + self->mEditor->setCursor(row, column); + self->mEditor->setFocus(true); + } +} + +bool LLScriptEdCore::handleReloadFromServerDialog(const LLSD& notification, const LLSD& response ) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch( option ) + { + case 0: // "Yes" + if( mLoadCallback ) + { + setScriptText(getString("loading"), false); + mLoadCallback(mUserdata); + } + break; + + case 1: // "No" + break; + + default: + llassert(0); + break; + } + return false; +} + +void LLScriptEdCore::selectFirstError() +{ + // Select the first item; + mErrorList->selectFirstItem(); + onErrorList(mErrorList, this); +} + + +struct LLEntryAndEdCore +{ + LLScriptEdCore* mCore; + LLEntryAndEdCore(LLScriptEdCore* core) : + mCore(core) + {} +}; + +void LLScriptEdCore::deleteBridges() +{ + S32 count = mBridges.size(); + LLEntryAndEdCore* eandc; + for(S32 i = 0; i < count; i++) + { + eandc = mBridges.at(i); + delete eandc; + mBridges[i] = NULL; + } + mBridges.clear(); +} + +// virtual +bool LLScriptEdCore::handleKeyHere(KEY key, MASK mask) +{ + bool just_control = MASK_CONTROL == (mask & MASK_MODIFIERS); + + if(('S' == key) && just_control) + { + if(mSaveCallback) + { + // don't close after saving + mSaveCallback(mUserdata, false); + } + + return true; + } + + if(('F' == key) && just_control) + { + if(mSearchReplaceCallback) + { + mSearchReplaceCallback(mUserdata); + } + + return true; + } + + return false; +} + +void LLScriptEdCore::onBtnLoadFromFile( void* data ) +{ + LLFilePickerReplyThread::startPicker(boost::bind(&LLScriptEdCore::loadScriptFromFile, _1, data), LLFilePicker::FFLOAD_SCRIPT, false); +} + +void LLScriptEdCore::loadScriptFromFile(const std::vector& filenames, void* data) +{ + std::string filename = filenames[0]; + + llifstream 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. + LLScriptEdCore* self = (LLScriptEdCore*)data; + if (self && (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 ) + { + LLFilePickerReplyThread::startPicker(boost::bind(&LLScriptEdCore::saveScriptToFile, _1, userdata), LLFilePicker::FFSAVE_SCRIPT, self->mScriptName); + } +} + +void LLScriptEdCore::saveScriptToFile(const std::vector& filenames, void* data) +{ + LLScriptEdCore* self = (LLScriptEdCore*)data; + if (self) + { + std::string filename = filenames[0]; + std::string scriptText = self->mEditor->getText(); + llofstream 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; +} + +LLUUID LLScriptEdCore::getAssociatedExperience()const +{ + return mAssociatedExperience; +} + +void LLScriptEdCore::onChangeFontSize(const LLSD &userdata) +{ + const std::string font_name = userdata.asString(); + gSavedSettings.setString("LSLFontSizeName", font_name); +} + +bool LLScriptEdCore::isFontSizeChecked(const LLSD &userdata) +{ + const std::string current_size_name = LLScriptEditor::getScriptFontSize(); + const std::string size_name = userdata.asString(); + + return (size_name == current_size_name); +} + + void LLLiveLSLEditor::setExperienceIds( const LLSD& experience_ids ) +{ + mExperienceIds=experience_ids; + updateExperiencePanel(); +} + + +void LLLiveLSLEditor::updateExperiencePanel() +{ + if(mScriptEd->getAssociatedExperience().isNull()) + { + mExperienceEnabled->set(false); + mExperiences->setVisible(false); + if(mExperienceIds.size()>0) + { + mExperienceEnabled->setEnabled(true); + mExperienceEnabled->setToolTip(getString("add_experiences")); + } + else + { + mExperienceEnabled->setEnabled(false); + mExperienceEnabled->setToolTip(getString("no_experiences")); + } + getChild("view_profile")->setVisible(false); + } + else + { + mExperienceEnabled->setToolTip(getString("experience_enabled")); + mExperienceEnabled->setEnabled(getIsModifiable()); + mExperiences->setVisible(true); + mExperienceEnabled->set(true); + getChild("view_profile")->setToolTip(getString("show_experience_profile")); + buildExperienceList(); + } +} + +void LLLiveLSLEditor::buildExperienceList() +{ + mExperiences->clearRows(); + bool foundAssociated=false; + const LLUUID& associated = mScriptEd->getAssociatedExperience(); + LLUUID last; + LLScrollListItem* item; + for(LLSD::array_const_iterator it = mExperienceIds.beginArray(); it != mExperienceIds.endArray(); ++it) + { + LLUUID id = it->asUUID(); + EAddPosition position = ADD_BOTTOM; + if(id == associated) + { + foundAssociated = true; + position = ADD_TOP; + } + + const LLSD& experience = LLExperienceCache::instance().get(id); + if(experience.isUndefined()) + { + mExperiences->add(getString("loading"), id, position); + last = id; + } + else + { + std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); + if (experience_name_string.empty()) + { + experience_name_string = LLTrans::getString("ExperienceNameUntitled"); + } + mExperiences->add(experience_name_string, id, position); + } + } + + if(!foundAssociated ) + { + const LLSD& experience = LLExperienceCache::instance().get(associated); + if(experience.isDefined()) + { + std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); + if (experience_name_string.empty()) + { + experience_name_string = LLTrans::getString("ExperienceNameUntitled"); + } + item=mExperiences->add(experience_name_string, associated, ADD_TOP); + } + else + { + item=mExperiences->add(getString("loading"), associated, ADD_TOP); + last = associated; + } + item->setEnabled(false); + } + + if(last.notNull()) + { + mExperiences->setEnabled(false); + LLExperienceCache::instance().get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); + } + else + { + mExperiences->setEnabled(true); + mExperiences->sortByName(true); + mExperiences->setCurrentByIndex(mExperiences->getCurrentIndex()); + getChild("view_profile")->setVisible(true); + } +} + + +void LLScriptEdCore::setAssociatedExperience( const LLUUID& experience_id ) +{ + mAssociatedExperience = experience_id; +} + + + +void LLLiveLSLEditor::requestExperiences() +{ + if (!getIsModifiable()) + { + return; + } + + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + std::string lookup_url=region->getCapability("GetCreatorExperiences"); + if(!lookup_url.empty()) + { + LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t success = + boost::bind(&LLLiveLSLEditor::receiveExperienceIds, _1, getDerivedHandle()); + + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url, success); + } + } +} + +/*static*/ +void LLLiveLSLEditor::receiveExperienceIds(LLSD result, LLHandle hparent) +{ + LLLiveLSLEditor* parent = hparent.get(); + if (!parent) + return; + + parent->setExperienceIds(result["experience_ids"]); +} + + +/// --------------------------------------------------------------------------- +/// LLScriptEdContainer +/// --------------------------------------------------------------------------- + +LLScriptEdContainer::LLScriptEdContainer(const LLSD& key) : + LLPreview(key) +, mScriptEd(NULL) +{ +} + +std::string LLScriptEdContainer::getTmpFileName(const std::string& script_name) +{ + // 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); + + if (script_name.empty()) + { + return std::string(LLFile::tmpdir()) + "sl_script_" + script_id_hash_str + ".lsl"; + } + else + { + return std::string(LLFile::tmpdir()) + "sl_script_" + script_name + "_" + 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; +} + +bool LLScriptEdContainer::handleKeyHere(KEY key, MASK mask) +{ + if (('A' == key) && (MASK_CONTROL == (mask & MASK_MODIFIERS))) + { + mScriptEd->selectAll(); + return true; + } + + if (!LLPreview::handleKeyHere(key, mask)) + { + return mScriptEd->handleKeyHere(key, mask); + } + return true; +} + +/// --------------------------------------------------------------------------- +/// LLPreviewLSL +/// --------------------------------------------------------------------------- + +struct LLScriptSaveInfo +{ + LLUUID mItemUUID; + std::string mDescription; + LLTransactionID mTransactionID; + + LLScriptSaveInfo(const LLUUID& uuid, const std::string& desc, LLTransactionID tid) : + mItemUUID(uuid), mDescription(desc), mTransactionID(tid) {} +}; + + + +//static +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 ) +: LLScriptEdContainer(key), + mPendingUploads(0) +{ + mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this); + + mItemObserver = new LLScriptMovedObserver(this); +} + +LLPreviewLSL::~LLPreviewLSL() +{ + delete mItemObserver; + mItemObserver = NULL; +} + +// virtual +bool LLPreviewLSL::postBuild() +{ + const LLInventoryItem* item = getItem(); + + llassert(item); + if (item) + { + getChild("desc")->setValue(item->getDescription()); + + std::string item_path = get_category_path(item->getParentUUID()); + getChild("path_txt")->setValue(item_path); + getChild("path_txt")->setToolTip(item_path); + } + childSetCommitCallback("desc", LLPreview::onText, this); + getChild("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); + + return LLPreview::postBuild(); +} + +void LLPreviewLSL::draw() +{ + const LLInventoryItem* item = getItem(); + if(!item) + { + setTitle(LLTrans::getString("ScriptWasDeleted")); + mScriptEd->setItemRemoved(true); + } + else if (mDirty) + { + std::string item_path = get_category_path(item->getParentUUID()); + getChild("path_txt")->setValue(item_path); + getChild("path_txt")->setToolTip(item_path); + } + LLPreview::draw(); +} +// virtual +void LLPreviewLSL::callbackLSLCompileSucceeded() +{ + LL_INFOS() << "LSL Bytecode saved" << LL_ENDL; + mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); + closeIfNeeded(); +} + +// virtual +void LLPreviewLSL::callbackLSLCompileFailed(const LLSD& compile_errors) +{ + LL_INFOS() << "Compile failed!" << LL_ENDL; + + for(LLSD::array_const_iterator line = compile_errors.beginArray(); + line < compile_errors.endArray(); + line++) + { + LLSD row; + std::string error_message = line->asString(); + LLStringUtil::stripNonprintable(error_message); + row["columns"][0]["value"] = error_message; + row["columns"][0]["font"] = "OCRA"; + mScriptEd->mErrorList->addElement(row); + } + mScriptEd->selectFirstError(); + closeIfNeeded(); +} + +void LLPreviewLSL::loadAsset() +{ + // *HACK: we poke into inventory to see if it's there, and if so, + // then it might be part of the inventory library. If it's in the + // library, then you can see the script, but not modify it. + const LLInventoryItem* item = gInventory.getItem(mItemUUID); + bool is_library = item + && !gInventory.isObjectDescendentOf(mItemUUID, + gInventory.getRootFolderID()); + if(!item) + { + // do the more generic search. + getItem(); + } + if(item) + { + bool is_copyable = gAgent.allowOperation(PERM_COPY, + item->getPermissions(), GP_OBJECT_MANIPULATE); + bool is_modifiable = gAgent.allowOperation(PERM_MODIFY, + item->getPermissions(), GP_OBJECT_MANIPULATE); + if (gAgent.isGodlike() || (is_copyable && (is_modifiable || is_library))) + { + LLUUID* new_uuid = new LLUUID(mItemUUID); + gAssetStorage->getInvItemAsset(LLHost(), + gAgent.getID(), + gAgent.getSessionID(), + item->getPermissions().getOwner(), + LLUUID::null, + item->getUUID(), + item->getAssetUUID(), + item->getType(), + &LLPreviewLSL::onLoadComplete, + (void*)new_uuid, + true); + mAssetStatus = PREVIEW_ASSET_LOADING; + } + else + { + mScriptEd->setScriptText(mScriptEd->getString("can_not_view"), false); + mScriptEd->mEditor->makePristine(); + mScriptEd->mFunctions->setEnabled(false); + mAssetStatus = PREVIEW_ASSET_LOADED; + } + 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; + } +} + + +bool LLPreviewLSL::canClose() +{ + return mScriptEd->canClose(); +} + +void LLPreviewLSL::closeIfNeeded() +{ + // Find our window and close it if requested. + getWindow()->decBusyCount(); + mPendingUploads--; + if (mPendingUploads <= 0 && mCloseAfterSave) + { + closeFloater(); + } +} + +void LLPreviewLSL::onSearchReplace(void* userdata) +{ + LLPreviewLSL* self = (LLPreviewLSL*)userdata; + LLScriptEdCore* sec = self->mScriptEd; + LLFloaterScriptSearch::show(sec); +} + +// static +void LLPreviewLSL::onLoad(void* userdata) +{ + LLPreviewLSL* self = (LLPreviewLSL*)userdata; + self->loadAsset(); +} + +// static +void LLPreviewLSL::onSave(void* userdata, bool close_after_save) +{ + LLPreviewLSL* self = (LLPreviewLSL*)userdata; + self->mCloseAfterSave = close_after_save; + self->saveIfNeeded(); +} + +/*static*/ +void LLPreviewLSL::finishedLSLUpload(LLUUID itemId, LLSD response) +{ + // Find our window and close it if requested. + LLPreviewLSL* preview = LLFloaterReg::findTypedInstance("preview_script", LLSD(itemId)); + if (preview) + { + // Bytecode save completed + if (response["compiled"]) + { + preview->callbackLSLCompileSucceeded(); + } + else + { + preview->callbackLSLCompileFailed(response["errors"]); + } + } +} + +bool LLPreviewLSL::failedLSLUpload(LLUUID itemId, LLUUID taskId, LLSD response, std::string reason) +{ + LLSD floater_key; + if (taskId.notNull()) + { + floater_key["taskid"] = taskId; + floater_key["itemid"] = itemId; + } + else + { + floater_key = LLSD(itemId); + } + + LLPreviewLSL* preview = LLFloaterReg::findTypedInstance("preview_script", floater_key); + if (preview) + { + // unfreeze floater + LLSD errors; + errors.append(LLTrans::getString("UploadFailed") + reason); + preview->callbackLSLCompileFailed(errors); + return true; + } + + return false; +} + +// 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. +void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/) +{ + if (!mScriptEd->hasChanged()) + { + return; + } + + mPendingUploads = 0; + mScriptEd->mErrorList->deleteAllItems(); + mScriptEd->mEditor->makePristine(); + + if (sync) + { + mScriptEd->sync(); + } + + if (!gAgent.getRegion()) return; + const LLInventoryItem *inv_item = getItem(); + // save it out to asset server + std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent"); + if(inv_item) + { + getWindow()->incBusyCount(); + mPendingUploads++; + if (!url.empty()) + { + std::string buffer(mScriptEd->mEditor->getText()); + + LLUUID old_asset_id = inv_item->getAssetUUID().isNull() ? mScriptEd->getAssetID() : inv_item->getAssetUUID(); + + LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared(mItemUUID, buffer, + [old_asset_id](LLUUID itemId, LLUUID, LLUUID, LLSD response) { + LLFileSystem::removeFile(old_asset_id, LLAssetType::AT_LSL_TEXT); + LLPreviewLSL::finishedLSLUpload(itemId, response); + }, + LLPreviewLSL::failedLSLUpload)); + + LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); + } + } +} + +// static +void LLPreviewLSL::onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status) +{ + LL_DEBUGS() << "LLPreviewLSL::onLoadComplete: got uuid " << asset_uuid + << LL_ENDL; + LLUUID* item_uuid = (LLUUID*)user_data; + LLPreviewLSL* preview = LLFloaterReg::findTypedInstance("preview_script", *item_uuid); + if( preview ) + { + if(0 == status) + { + LLFileSystem file(asset_uuid, type); + S32 file_length = file.getSize(); + + std::vector buffer(file_length+1); + file.read((U8*)&buffer[0], file_length); + + // put a EOS at the end + buffer[file_length] = 0; + preview->mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), true); + preview->mScriptEd->mEditor->makePristine(); + + std::string script_name = DEFAULT_SCRIPT_NAME; + LLInventoryItem* item = gInventory.getItem(*item_uuid); + bool is_modifiable = false; + if (item) + { + if (!item->getName().empty()) + { + script_name = item->getName(); + } + if (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) + { + is_modifiable = true; + } + } + preview->mScriptEd->setScriptName(script_name); + preview->mScriptEd->setEnableEditing(is_modifiable); + preview->mScriptEd->setAssetID(asset_uuid); + preview->mAssetStatus = PREVIEW_ASSET_LOADED; + } + else + { + if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || + LL_ERR_FILE_EMPTY == status) + { + LLNotificationsUtil::add("ScriptMissing"); + } + else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) + { + LLNotificationsUtil::add("ScriptNoPermissions"); + } + else + { + LLNotificationsUtil::add("UnableToLoadScript"); + } + + preview->mAssetStatus = PREVIEW_ASSET_ERROR; + LL_WARNS() << "Problem loading script: " << status << LL_ENDL; + } + } + delete item_uuid; +} + + +/// --------------------------------------------------------------------------- +/// LLLiveLSLEditor +/// --------------------------------------------------------------------------- + + +//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) : + LLScriptEdContainer(key), + mAskedForRunningInfo(false), + mHaveRunningInfo(false), + mCloseAfterSave(false), + mPendingUploads(0), + mIsModifiable(false), + mIsNew(false), + mIsSaving(false), + mObjectName("") +{ + mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); +} + +bool LLLiveLSLEditor::postBuild() +{ + childSetCommitCallback("running", LLLiveLSLEditor::onRunningCheckboxClicked, this); + getChildView("running")->setEnabled(false); + + childSetAction("Reset",&LLLiveLSLEditor::onReset,this); + getChildView("Reset")->setEnabled(true); + + mMonoCheckbox = getChild("mono"); + childSetCommitCallback("mono", &LLLiveLSLEditor::onMonoCheckboxClicked, this); + getChildView("mono")->setEnabled(true); + + mScriptEd->mEditor->makePristine(); + mScriptEd->mEditor->setFocus(true); + + + mExperiences = getChild("Experiences..."); + mExperiences->setCommitCallback(boost::bind(&LLLiveLSLEditor::experienceChanged, this)); + + mExperienceEnabled = getChild("enable_xp"); + + childSetCommitCallback("enable_xp", onToggleExperience, this); + childSetCommitCallback("view_profile", onViewProfile, this); + + + return LLPreview::postBuild(); +} + +// virtual +void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id, + const LLUUID& item_id, + bool is_script_running) +{ + LL_DEBUGS() << "LSL Bytecode saved" << LL_ENDL; + mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); + getChild("running")->set(is_script_running); + mIsSaving = false; + closeIfNeeded(); +} + +// virtual +void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors) +{ + LL_DEBUGS() << "Compile failed!" << LL_ENDL; + for(LLSD::array_const_iterator line = compile_errors.beginArray(); + line < compile_errors.endArray(); + line++) + { + LLSD row; + std::string error_message = line->asString(); + LLStringUtil::stripNonprintable(error_message); + row["columns"][0]["value"] = error_message; + // *TODO: change to "MONOSPACE" and change llfontgl.cpp? + row["columns"][0]["font"] = "OCRA"; + mScriptEd->mErrorList->addElement(row); + } + mScriptEd->selectFirstError(); + mIsSaving = false; + closeIfNeeded(); +} + +void LLLiveLSLEditor::loadAsset() +{ + //LL_INFOS() << "LLLiveLSLEditor::loadAsset()" << LL_ENDL; + if(!mIsNew) + { + LLViewerObject* object = gObjectList.findObject(mObjectUUID); + if(object) + { + LLViewerInventoryItem* item = dynamic_cast(object->getInventoryObject(mItemUUID)); + + if(item) + { + LLViewerRegion* region = object->getRegion(); + std::string url = std::string(); + if(region) + { + url = region->getCapability("GetMetadata"); + } + LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), url, + boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle(), _1)); + + bool isGodlike = gAgent.isGodlike(); + bool copyManipulate = gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE); + mIsModifiable = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); + + if(!isGodlike && (!copyManipulate || !mIsModifiable)) + { + mItem = new LLViewerInventoryItem(item); + mScriptEd->setScriptText(getString("not_allowed"), false); + mScriptEd->mEditor->makePristine(); + mScriptEd->enableSave(false); + mAssetStatus = PREVIEW_ASSET_LOADED; + } + else if(copyManipulate || isGodlike) + { + mItem = new LLViewerInventoryItem(item); + // request the text from the object + LLSD* user_data = new LLSD(); + user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID); + gAssetStorage->getInvItemAsset(object->getRegion()->getHost(), + gAgent.getID(), + gAgent.getSessionID(), + item->getPermissions().getOwner(), + object->getID(), + item->getUUID(), + item->getAssetUUID(), + item->getType(), + &LLLiveLSLEditor::onLoadComplete, + (void*)user_data, + true); + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_GetScriptRunning); + msg->nextBlockFast(_PREHASH_Script); + msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID); + msg->addUUIDFast(_PREHASH_ItemID, mItemUUID); + msg->sendReliable(object->getRegion()->getHost()); + mAskedForRunningInfo = true; + mAssetStatus = PREVIEW_ASSET_LOADING; + } + } + + if(mItem.isNull()) + { + mScriptEd->setScriptText(LLStringUtil::null, false); + mScriptEd->mEditor->makePristine(); + mAssetStatus = PREVIEW_ASSET_LOADED; + mIsModifiable = false; + } + + refreshFromItem(); + getChild("obj_name")->setValue(mObjectName); + // This is commented out, because we don't completely + // handle script exports yet. + /* + // request the exports from the object + gMessageSystem->newMessage("GetScriptExports"); + gMessageSystem->nextBlock("ScriptBlock"); + gMessageSystem->addUUID("AgentID", gAgent.getID()); + U32 local_id = object->getLocalID(); + gMessageSystem->addData("LocalID", &local_id); + gMessageSystem->addUUID("ItemID", mItemUUID); + LLHost host(object->getRegion()->getIP(), + object->getRegion()->getPort()); + gMessageSystem->sendReliable(host); + */ + } + } + else + { + mScriptEd->setScriptText(std::string(HELLO_LSL), true); + mScriptEd->enableSave(false); + LLPermissions perm; + perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, gAgent.getGroupID()); + perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, PERM_MOVE | PERM_TRANSFER); + mItem = new LLViewerInventoryItem(mItemUUID, + mObjectUUID, + perm, + LLUUID::null, + LLAssetType::AT_LSL_TEXT, + LLInventoryType::IT_LSL, + DEFAULT_SCRIPT_NAME, + DEFAULT_SCRIPT_DESC, + LLSaleInfo::DEFAULT, + LLInventoryItemFlags::II_FLAGS_NONE, + time_corrected()); + mAssetStatus = PREVIEW_ASSET_LOADED; + } + + requestExperiences(); +} + +// static +void LLLiveLSLEditor::onLoadComplete(const LLUUID& asset_id, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status) +{ + LL_DEBUGS() << "LLLiveLSLEditor::onLoadComplete: got uuid " << asset_id + << LL_ENDL; + LLSD* floater_key = (LLSD*)user_data; + + LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance("preview_scriptedit", *floater_key); + + if(instance ) + { + if( LL_ERR_NOERR == status ) + { + instance->loadScriptText(asset_id, type); + instance->mScriptEd->setEnableEditing(true); + instance->mAssetStatus = PREVIEW_ASSET_LOADED; + instance->mScriptEd->setAssetID(asset_id); + } + else + { + if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || + LL_ERR_FILE_EMPTY == status) + { + LLNotificationsUtil::add("ScriptMissing"); + } + else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) + { + LLNotificationsUtil::add("ScriptNoPermissions"); + } + else + { + LLNotificationsUtil::add("UnableToLoadScript"); + } + instance->mAssetStatus = PREVIEW_ASSET_ERROR; + } + } + + delete floater_key; +} + +void LLLiveLSLEditor::loadScriptText(const LLUUID &uuid, LLAssetType::EType type) +{ + LLFileSystem file(uuid, type); + S32 file_length = file.getSize(); + std::vector buffer(file_length + 1); + file.read((U8*)&buffer[0], file_length); + + if (file.getLastBytesRead() != file_length || + file_length <= 0) + { + LL_WARNS() << "Error reading " << uuid << ":" << type << LL_ENDL; + } + + buffer[file_length] = '\0'; + + mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), true); + mScriptEd->makeEditorPristine(); + + std::string script_name = DEFAULT_SCRIPT_NAME; + const LLInventoryItem* inv_item = getItem(); + + if(inv_item) + { + script_name = inv_item->getName(); + } + mScriptEd->setScriptName(script_name); +} + + +void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata ) +{ + LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; + LLViewerObject* object = gObjectList.findObject( self->mObjectUUID ); + LLCheckBoxCtrl* runningCheckbox = self->getChild("running"); + bool running = runningCheckbox->get(); + //self->mRunningCheckbox->get(); + if( object ) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_SetScriptRunning); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Script); + msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectUUID); + msg->addUUIDFast(_PREHASH_ItemID, self->mItemUUID); + msg->addBOOLFast(_PREHASH_Running, running); + msg->sendReliable(object->getRegion()->getHost()); + } + else + { + runningCheckbox->set(!running); + LLNotificationsUtil::add("CouldNotStartStopScript"); + } +} + +void LLLiveLSLEditor::onReset(void *userdata) +{ + LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; + + LLViewerObject* object = gObjectList.findObject( self->mObjectUUID ); + if(object) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ScriptReset); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Script); + msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectUUID); + msg->addUUIDFast(_PREHASH_ItemID, self->mItemUUID); + msg->sendReliable(object->getRegion()->getHost()); + } + else + { + LLNotificationsUtil::add("CouldNotStartStopScript"); + } +} + +void LLLiveLSLEditor::draw() +{ + LLViewerObject* object = gObjectList.findObject(mObjectUUID); + LLCheckBoxCtrl* runningCheckbox = getChild( "running"); + if(object && mAskedForRunningInfo && mHaveRunningInfo) + { + if(object->permAnyOwner()) + { + runningCheckbox->setLabel(getString("script_running")); + runningCheckbox->setEnabled(!mIsSaving); + } + else + { + runningCheckbox->setLabel(getString("public_objects_can_not_run")); + runningCheckbox->setEnabled(false); + + // *FIX: Set it to false so that the ui is correct for + // a box that is released to public. It could be + // incorrect after a release/claim cycle, but will be + // correct after clicking on it. + runningCheckbox->set(false); + mMonoCheckbox->set(false); + } + } + else if(!object) + { + // HACK: Display this information in the title bar. + // Really ought to put in main window. + setTitle(LLTrans::getString("ObjectOutOfRange")); + runningCheckbox->setEnabled(false); + mMonoCheckbox->setEnabled(false); + // object may have fallen out of range. + mHaveRunningInfo = false; + } + + LLPreview::draw(); +} + + +void LLLiveLSLEditor::onSearchReplace(void* userdata) +{ + LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; + + LLScriptEdCore* sec = self->mScriptEd; + LLFloaterScriptSearch::show(sec); +} + +struct LLLiveLSLSaveData +{ + LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, bool active); + LLUUID mSaveObjectID; + LLPointer mItem; + bool mActive; +}; + +LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id, + const LLViewerInventoryItem* item, + bool active) : + mSaveObjectID(id), + mActive(active) +{ + llassert(item); + mItem = new LLViewerInventoryItem(item); +} + +/*static*/ +void LLLiveLSLEditor::finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, bool isRunning) +{ + LLSD floater_key; + floater_key["taskid"] = taskId; + floater_key["itemid"] = itemId; + + LLLiveLSLEditor* preview = LLFloaterReg::findTypedInstance("preview_scriptedit", floater_key); + if (preview) + { + preview->mItem->setAssetUUID(newAssetId); + preview->mScriptEd->setAssetID(newAssetId); + + // Bytecode save completed + if (response["compiled"]) + { + preview->callbackLSLCompileSucceeded(taskId, itemId, isRunning); + } + else + { + preview->callbackLSLCompileFailed(response["errors"]); + } + } +} + +// virtual +void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) +{ + LLViewerObject* object = gObjectList.findObject(mObjectUUID); + if (!object) + { + LLNotificationsUtil::add("SaveScriptFailObjectNotFound"); + return; + } + + if (mItem.isNull() || !mItem->isFinished()) + { + // $NOTE: While the error message may not be exactly correct, + // it's pretty close. + LLNotificationsUtil::add("SaveScriptFailObjectNotFound"); + return; + } + + // get the latest info about it. We used to be losing the script + // name on save, because the viewer object version of the item, + // and the editor version would get out of synch. Here's a good + // place to synch them back up. + LLInventoryItem* inv_item = dynamic_cast(object->getInventoryObject(mItemUUID)); + if (inv_item) + { + mItem->copyItem(inv_item); + } + + // Don't need to save if we're pristine + if (!mScriptEd->hasChanged()) + { + return; + } + + mPendingUploads = 0; + + // save the script + mScriptEd->enableSave(false); + mScriptEd->mEditor->makePristine(); + mScriptEd->mErrorList->deleteAllItems(); + mScriptEd->mEditor->makePristine(); + + if (sync) + { + mScriptEd->sync(); + } + + bool isRunning = getChild("running")->get(); + getWindow()->incBusyCount(); + mPendingUploads++; + + std::string url = object->getRegion()->getCapability("UpdateScriptTask"); + + if (!url.empty()) + { + std::string buffer(mScriptEd->mEditor->getText()); + LLUUID old_asset_id = mScriptEd->getAssetID(); + + LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared(mObjectUUID, mItemUUID, + monoChecked() ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2, + isRunning, mScriptEd->getAssociatedExperience(), buffer, + [isRunning, old_asset_id](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) { + LLFileSystem::removeFile(old_asset_id, LLAssetType::AT_LSL_TEXT); + LLLiveLSLEditor::finishLSLUpload(itemId, taskId, newAssetId, response, isRunning); + }, + nullptr)); // needs failure handling? + + LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); + } +} + +bool LLLiveLSLEditor::canClose() +{ + return mScriptEd->canClose(); +} + +void LLLiveLSLEditor::closeIfNeeded() +{ + getWindow()->decBusyCount(); + mPendingUploads--; + if ((mPendingUploads <= 0) && mCloseAfterSave) + { + closeFloater(); + } +} + +// static +void LLLiveLSLEditor::onLoad(void* userdata) +{ + LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; + self->loadAsset(); +} + +// static +void LLLiveLSLEditor::onSave(void* userdata, bool close_after_save) +{ + if (LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata) + { + self->mCloseAfterSave = close_after_save; + self->mScriptEd->mErrorList->setCommentText(""); + self->saveIfNeeded(); + } +} + +// static +void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) +{ + LLUUID item_id; + LLUUID object_id; + msg->getUUIDFast(_PREHASH_Script, _PREHASH_ObjectID, object_id); + msg->getUUIDFast(_PREHASH_Script, _PREHASH_ItemID, item_id); + + LLSD floater_key; + floater_key["taskid"] = object_id; + floater_key["itemid"] = item_id; + if (LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance("preview_scriptedit", floater_key)) + { + instance->mHaveRunningInfo = true; + bool running; + msg->getBOOLFast(_PREHASH_Script, _PREHASH_Running, running); + LLCheckBoxCtrl* runningCheckbox = instance->getChild("running"); + runningCheckbox->set(running); + bool mono; + msg->getBOOLFast(_PREHASH_Script, "Mono", mono); + LLCheckBoxCtrl* monoCheckbox = instance->getChild("mono"); + monoCheckbox->setEnabled(instance->getIsModifiable() && have_script_upload_cap(object_id)); + monoCheckbox->set(mono); + } +} + +void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata) +{ + LLLiveLSLEditor* self = static_cast(userdata); + self->mMonoCheckbox->setEnabled(have_script_upload_cap(self->mObjectUUID)); + self->mScriptEd->enableSave(self->getIsModifiable()); +} + +bool LLLiveLSLEditor::monoChecked() const +{ + return mMonoCheckbox && mMonoCheckbox->getValue(); +} + +void LLLiveLSLEditor::setAssociatedExperience( LLHandle editor, const LLSD& experience ) +{ + if (LLLiveLSLEditor* scriptEd = editor.get()) + { + LLUUID id; + if (experience.has(LLExperienceCache::EXPERIENCE_ID)) + { + id=experience[LLExperienceCache::EXPERIENCE_ID].asUUID(); + } + scriptEd->mScriptEd->setAssociatedExperience(id); + scriptEd->updateExperiencePanel(); + } +} -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/newview/llpreviewscript.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llpreviewscript.cpp') diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index a6ab08601d..c2188ea638 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1203,9 +1203,9 @@ struct LLEntryAndEdCore void LLScriptEdCore::deleteBridges() { - S32 count = mBridges.size(); + auto count = mBridges.size(); LLEntryAndEdCore* eandc; - for(S32 i = 0; i < count; i++) + for(size_t i = 0; i < count; i++) { eandc = mBridges.at(i); delete eandc; -- cgit v1.2.3 From 04f95e78e38a682d4933ead0403e78507cbe79a6 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 18 Jul 2024 18:14:22 +0300 Subject: viewer#2061 Crash in ~LLScriptEdCore() --- indra/newview/llpreviewscript.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'indra/newview/llpreviewscript.cpp') diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index c2188ea638..b7c929f0b5 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -414,7 +414,13 @@ LLScriptEdCore::~LLScriptEdCore() if (script_search && script_search->getEditorCore() == this) { script_search->closeFloater(); - delete script_search; + // closeFloater can delete instance since it's not reusable nor single instance + // so make sure instance is still there before deleting + script_search = LLFloaterScriptSearch::getInstance(); + if (script_search) + { + delete script_search; + } } delete mLiveFile; -- cgit v1.2.3