00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llpreviewscript.h"
00035
00036 #include "llassetstorage.h"
00037 #include "llassetuploadresponders.h"
00038 #include "llbutton.h"
00039 #include "llcheckboxctrl.h"
00040 #include "llcombobox.h"
00041 #include "lldir.h"
00042 #include "llinventorymodel.h"
00043 #include "llkeyboard.h"
00044 #include "lllineeditor.h"
00045
00046 #include "llresmgr.h"
00047 #include "llscrollbar.h"
00048 #include "llscrollcontainer.h"
00049 #include "llscrolllistctrl.h"
00050 #include "llslider.h"
00051 #include "lscript_rt_interface.h"
00052 #include "lscript_export.h"
00053 #include "lltextbox.h"
00054 #include "lltooldraganddrop.h"
00055 #include "llvfile.h"
00056
00057 #include "llagent.h"
00058 #include "llnotify.h"
00059 #include "llmenugl.h"
00060 #include "roles_constants.h"
00061 #include "llselectmgr.h"
00062 #include "llviewerinventory.h"
00063 #include "llviewermenu.h"
00064 #include "llviewerobject.h"
00065 #include "llviewerobjectlist.h"
00066 #include "llviewerregion.h"
00067 #include "llkeyboard.h"
00068 #include "llscrollcontainer.h"
00069 #include "llcheckboxctrl.h"
00070 #include "llselectmgr.h"
00071 #include "lltooldraganddrop.h"
00072 #include "llscrolllistctrl.h"
00073 #include "lltextbox.h"
00074 #include "llslider.h"
00075 #include "lldir.h"
00076 #include "llcombobox.h"
00077
00078 #include "llviewerstats.h"
00079 #include "llviewertexteditor.h"
00080 #include "llviewerwindow.h"
00081 #include "lluictrlfactory.h"
00082 #include "llwebbrowserctrl.h"
00083 #include "lluictrlfactory.h"
00084
00085 #include "llviewercontrol.h"
00086 #include "llappviewer.h"
00087
00088 #include "llpanelinventory.h"
00089
00090
00091 const char HELLO_LSL[] =
00092 "default\n"
00093 "{\n"
00094 " state_entry()\n"
00095 " {\n"
00096 " llSay(0, \"Hello, Avatar!\");\n"
00097 " }\n"
00098 "\n"
00099 " touch_start(integer total_number)\n"
00100 " {\n"
00101 " llSay(0, \"Touched.\");\n"
00102 " }\n"
00103 "}\n";
00104 const char HELP_LSL[] = "lsl_guide.html";
00105
00106 const char DEFAULT_SCRIPT_NAME[] = "New Script";
00107 const char DEFAULT_SCRIPT_DESC[] = "(No Description)";
00108
00109
00110
00111 const S32 SCRIPT_BORDER = 4;
00112 const S32 SCRIPT_PAD = 5;
00113 const S32 SCRIPT_BUTTON_WIDTH = 128;
00114 const S32 SCRIPT_BUTTON_HEIGHT = 24;
00115 const S32 LINE_COLUMN_HEIGHT = 14;
00116 const S32 BTN_PAD = 8;
00117
00118 const S32 SCRIPT_EDITOR_MIN_HEIGHT = 2 * SCROLLBAR_SIZE + 2 * LLPANEL_BORDER_WIDTH + 128;
00119
00120 const S32 SCRIPT_MIN_WIDTH =
00121 2 * SCRIPT_BORDER +
00122 2 * SCRIPT_BUTTON_WIDTH +
00123 SCRIPT_PAD + RESIZE_HANDLE_WIDTH +
00124 SCRIPT_PAD;
00125
00126 const S32 SCRIPT_MIN_HEIGHT =
00127 2 * SCRIPT_BORDER +
00128 3*(SCRIPT_BUTTON_HEIGHT + SCRIPT_PAD) +
00129 LINE_COLUMN_HEIGHT +
00130 SCRIPT_EDITOR_MIN_HEIGHT;
00131
00132 const S32 MAX_EXPORT_SIZE = 1000;
00133
00134 const S32 SCRIPT_SEARCH_WIDTH = 300;
00135 const S32 SCRIPT_SEARCH_HEIGHT = 120;
00136 const S32 SCRIPT_SEARCH_LABEL_WIDTH = 50;
00137 const S32 SCRIPT_SEARCH_BUTTON_WIDTH = 80;
00138 const S32 TEXT_EDIT_COLUMN_HEIGHT = 16;
00139 const S32 MAX_HISTORY_COUNT = 10;
00140 const F32 LIVE_HELP_REFRESH_TIME = 1.f;
00141
00145 class LLFloaterScriptSearch : public LLFloater
00146 {
00147 public:
00148 LLFloaterScriptSearch(std::string title, LLRect rect, LLScriptEdCore* editor_core);
00149 ~LLFloaterScriptSearch();
00150
00151 static void show(LLScriptEdCore* editor_core);
00152 static void onBtnSearch(void* userdata);
00153 void handleBtnSearch();
00154
00155 static void onBtnReplace(void* userdata);
00156 void handleBtnReplace();
00157
00158 static void onBtnReplaceAll(void* userdata);
00159 void handleBtnReplaceAll();
00160
00161 LLScriptEdCore* getEditorCore() { return mEditorCore; }
00162 static LLFloaterScriptSearch* getInstance() { return sInstance; }
00163
00164 void open();
00165
00166 private:
00167
00168 LLScriptEdCore* mEditorCore;
00169
00170 static LLFloaterScriptSearch* sInstance;
00171 };
00172
00173 LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL;
00174
00175 LLFloaterScriptSearch::LLFloaterScriptSearch(std::string title, LLRect rect, LLScriptEdCore* editor_core)
00176 : LLFloater("script search",rect,title), mEditorCore(editor_core)
00177 {
00178
00179 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_search.xml");
00180
00181 childSetAction("search_btn", onBtnSearch,this);
00182 childSetAction("replace_btn", onBtnReplace,this);
00183 childSetAction("replace_all_btn", onBtnReplaceAll,this);
00184
00185 setDefaultBtn("search_btn");
00186
00187 if (!getHost())
00188 {
00189 LLRect curRect = getRect();
00190 translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
00191 }
00192
00193 sInstance = this;
00194
00195 childSetFocus("search_text", TRUE);
00196
00197
00198 LLView* viewp = (LLView*)editor_core;
00199 while(viewp)
00200 {
00201 LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp);
00202 if (floaterp)
00203 {
00204 floaterp->addDependentFloater(this);
00205 break;
00206 }
00207 viewp = viewp->getParent();
00208 }
00209 }
00210
00211
00212 void LLFloaterScriptSearch::show(LLScriptEdCore* editor_core)
00213 {
00214 if (sInstance && sInstance->mEditorCore && sInstance->mEditorCore != editor_core)
00215 {
00216 sInstance->close();
00217 delete sInstance;
00218 }
00219
00220 if (!sInstance)
00221 {
00222 S32 left = 0;
00223 S32 top = 0;
00224 gFloaterView->getNewFloaterPosition(&left,&top);
00225
00226
00227 new LLFloaterScriptSearch("Script Search",LLRect(left,top,left + SCRIPT_SEARCH_WIDTH,top - SCRIPT_SEARCH_HEIGHT),editor_core);
00228 }
00229
00230 sInstance->open();
00231 }
00232
00233 LLFloaterScriptSearch::~LLFloaterScriptSearch()
00234 {
00235 sInstance = NULL;
00236 }
00237
00238
00239 void LLFloaterScriptSearch::onBtnSearch(void *userdata)
00240 {
00241 LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata;
00242 self->handleBtnSearch();
00243 }
00244
00245 void LLFloaterScriptSearch::handleBtnSearch()
00246 {
00247 LLCheckBoxCtrl* caseChk = getChild<LLCheckBoxCtrl>("case_text");
00248 mEditorCore->mEditor->selectNext(childGetText("search_text"), caseChk->get());
00249 }
00250
00251
00252 void LLFloaterScriptSearch::onBtnReplace(void *userdata)
00253 {
00254 LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata;
00255 self->handleBtnReplace();
00256 }
00257
00258 void LLFloaterScriptSearch::handleBtnReplace()
00259 {
00260 LLCheckBoxCtrl* caseChk = getChild<LLCheckBoxCtrl>("case_text");
00261 mEditorCore->mEditor->replaceText(childGetText("search_text"), childGetText("replace_text"), caseChk->get());
00262 }
00263
00264
00265 void LLFloaterScriptSearch::onBtnReplaceAll(void *userdata)
00266 {
00267 LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata;
00268 self->handleBtnReplaceAll();
00269 }
00270
00271 void LLFloaterScriptSearch::handleBtnReplaceAll()
00272 {
00273 LLCheckBoxCtrl* caseChk = getChild<LLCheckBoxCtrl>("case_text");
00274 mEditorCore->mEditor->replaceTextAll(childGetText("search_text"), childGetText("replace_text"), caseChk->get());
00275 }
00276
00277 void LLFloaterScriptSearch::open()
00278 {
00279 LLFloater::open();
00280 childSetFocus("search_text", TRUE);
00281 }
00282
00286
00287 LLScriptEdCore::LLScriptEdCore(
00288 const std::string& name,
00289 const LLRect& rect,
00290 const std::string& sample,
00291 const std::string& help,
00292 const LLHandle<LLFloater>& floater_handle,
00293 void (*load_callback)(void*),
00294 void (*save_callback)(void*, BOOL),
00295 void (*search_replace_callback) (void* userdata),
00296 void* userdata,
00297 S32 bottom_pad)
00298 :
00299 LLPanel( "name", rect ),
00300 mSampleText(sample),
00301 mHelpFile ( help ),
00302 mEditor( NULL ),
00303 mLoadCallback( load_callback ),
00304 mSaveCallback( save_callback ),
00305 mSearchReplaceCallback( search_replace_callback ),
00306 mUserdata( userdata ),
00307 mForceClose( FALSE ),
00308 mLastHelpToken(NULL),
00309 mLiveHelpHistorySize(0)
00310 {
00311 setFollowsAll();
00312 setBorderVisible(FALSE);
00313
00314
00315 LLUICtrlFactory::getInstance()->buildPanel(this, "floater_script_ed_panel.xml");
00316
00317 mErrorList = getChild<LLScrollListCtrl>("lsl errors");
00318
00319 mFunctions = getChild<LLComboBox>( "Insert...");
00320
00321 childSetCommitCallback("Insert...", &LLScriptEdCore::onBtnInsertFunction, this);
00322
00323 mEditor = getChild<LLViewerTextEditor>("Script Editor");
00324 mEditor->setFollowsAll();
00325 mEditor->setHandleEditKeysDirectly(TRUE);
00326 mEditor->setEnabled(TRUE);
00327 mEditor->setWordWrap(TRUE);
00328
00329 LLDynamicArray<const char*> funcs;
00330 LLDynamicArray<const char*> tooltips;
00331 for (S32 i = 0; i < gScriptLibrary.mNextNumber; i++)
00332 {
00333
00334 if (!gScriptLibrary.mFunctions[i]->mGodOnly || gAgent.isGodlike())
00335 {
00336 funcs.put(gScriptLibrary.mFunctions[i]->mName);
00337 tooltips.put(gScriptLibrary.mFunctions[i]->mDesc);
00338 }
00339 }
00340 LLColor3 color(0.5f, 0.0f, 0.15f);
00341
00342 mEditor->loadKeywords(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keywords.ini"), funcs, tooltips, color);
00343
00344
00345 LLKeywordToken *token;
00346 LLKeywords::keyword_iterator_t token_it;
00347 for (token_it = mEditor->keywordsBegin(); token_it != mEditor->keywordsEnd(); ++token_it)
00348 {
00349 token = token_it->second;
00350 if (token->getColor() == color)
00351 mFunctions->add(wstring_to_utf8str(token->getToken()));
00352 }
00353
00354 for (token_it = mEditor->keywordsBegin(); token_it != mEditor->keywordsEnd(); ++token_it)
00355 {
00356 token = token_it->second;
00357 if (token->getColor() != color)
00358 mFunctions->add(wstring_to_utf8str(token->getToken()));
00359 }
00360
00361
00362 childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this);
00363 childSetAction("Save_btn", onBtnSave,this);
00364
00365 initMenu();
00366
00367
00368
00369
00370
00371
00372
00373
00374 }
00375
00376 LLScriptEdCore::~LLScriptEdCore()
00377 {
00378 deleteBridges();
00379
00380
00381 LLFloaterScriptSearch* script_search = LLFloaterScriptSearch::getInstance();
00382 if (script_search && script_search->getEditorCore() == this)
00383 {
00384 script_search->close();
00385 delete script_search;
00386 }
00387 }
00388
00389 void LLScriptEdCore::initMenu()
00390 {
00391
00392 LLMenuItemCallGL* menuItem = getChild<LLMenuItemCallGL>("Save");
00393 menuItem->setMenuCallback(onBtnSave, this);
00394 menuItem->setEnabledCallback(hasChanged);
00395
00396 menuItem = getChild<LLMenuItemCallGL>("Revert All Changes");
00397 menuItem->setMenuCallback(onBtnUndoChanges, this);
00398 menuItem->setEnabledCallback(hasChanged);
00399
00400 menuItem = getChild<LLMenuItemCallGL>("Undo");
00401 menuItem->setMenuCallback(onUndoMenu, this);
00402 menuItem->setEnabledCallback(enableUndoMenu);
00403
00404 menuItem = getChild<LLMenuItemCallGL>("Redo");
00405 menuItem->setMenuCallback(onRedoMenu, this);
00406 menuItem->setEnabledCallback(enableRedoMenu);
00407
00408 menuItem = getChild<LLMenuItemCallGL>("Cut");
00409 menuItem->setMenuCallback(onCutMenu, this);
00410 menuItem->setEnabledCallback(enableCutMenu);
00411
00412 menuItem = getChild<LLMenuItemCallGL>("Copy");
00413 menuItem->setMenuCallback(onCopyMenu, this);
00414 menuItem->setEnabledCallback(enableCopyMenu);
00415
00416 menuItem = getChild<LLMenuItemCallGL>("Paste");
00417 menuItem->setMenuCallback(onPasteMenu, this);
00418 menuItem->setEnabledCallback(enablePasteMenu);
00419
00420 menuItem = getChild<LLMenuItemCallGL>("Select All");
00421 menuItem->setMenuCallback(onSelectAllMenu, this);
00422 menuItem->setEnabledCallback(enableSelectAllMenu);
00423
00424 menuItem = getChild<LLMenuItemCallGL>("Search / Replace...");
00425 menuItem->setMenuCallback(onSearchMenu, this);
00426 menuItem->setEnabledCallback(NULL);
00427
00428 menuItem = getChild<LLMenuItemCallGL>("Help...");
00429 menuItem->setMenuCallback(onBtnHelp, this);
00430 menuItem->setEnabledCallback(NULL);
00431
00432 menuItem = getChild<LLMenuItemCallGL>("LSL Wiki Help...");
00433 menuItem->setMenuCallback(onBtnDynamicHelp, this);
00434 menuItem->setEnabledCallback(NULL);
00435 }
00436
00437 BOOL LLScriptEdCore::hasChanged(void* userdata)
00438 {
00439 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00440 if (!self || !self->mEditor) return FALSE;
00441
00442 return !self->mEditor->isPristine();
00443 }
00444
00445 void LLScriptEdCore::draw()
00446 {
00447 BOOL script_changed = !mEditor->isPristine();
00448 childSetEnabled("Save_btn", script_changed);
00449
00450 if( mEditor->hasFocus() )
00451 {
00452 S32 line = 0;
00453 S32 column = 0;
00454 mEditor->getCurrentLineAndColumn( &line, &column, FALSE );
00455 std::string cursor_pos;
00456 cursor_pos = llformat("Line %d, Column %d", line, column );
00457 childSetText("line_col", cursor_pos);
00458 }
00459 else
00460 {
00461 childSetText("line_col", LLString::null);
00462 }
00463
00464 updateDynamicHelp();
00465
00466 LLPanel::draw();
00467 }
00468
00469 void LLScriptEdCore::updateDynamicHelp(BOOL immediate)
00470 {
00471 LLFloater* help_floater = mLiveHelpHandle.get();
00472 if (!help_floater) return;
00473
00474
00475 LLButton* fwd_button = help_floater->getChild<LLButton>("fwd_btn");
00476 LLButton* back_button = help_floater->getChild<LLButton>("back_btn");
00477 LLWebBrowserCtrl* browser = help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
00478 back_button->setEnabled(browser->canNavigateBack());
00479 fwd_button->setEnabled(browser->canNavigateForward());
00480
00481 if (!immediate && !gSavedSettings.getBOOL("ScriptHelpFollowsCursor"))
00482 {
00483 return;
00484 }
00485
00486 const LLTextSegment* segment = NULL;
00487 std::vector<const LLTextSegment*> selected_segments;
00488 mEditor->getSelectedSegments(selected_segments);
00489
00490
00491 std::vector<const LLTextSegment*>::iterator segment_iter;
00492 for (segment_iter = selected_segments.begin(); segment_iter != selected_segments.end(); ++segment_iter)
00493 {
00494 if((*segment_iter)->getToken() && (*segment_iter)->getToken()->getType() == LLKeywordToken::WORD)
00495 {
00496 segment = *segment_iter;
00497 break;
00498 }
00499 }
00500
00501
00502 if (!segment)
00503 {
00504 const LLTextSegment* test_segment = mEditor->getPreviousSegment();
00505 if(test_segment->getToken() && test_segment->getToken()->getType() == LLKeywordToken::WORD)
00506 {
00507 segment = test_segment;
00508 }
00509 }
00510
00511 if (segment)
00512 {
00513 if (segment->getToken() != mLastHelpToken)
00514 {
00515 mLastHelpToken = segment->getToken();
00516 mLiveHelpTimer.start();
00517 }
00518 if (immediate || (mLiveHelpTimer.getStarted() && mLiveHelpTimer.getElapsedTimeF32() > LIVE_HELP_REFRESH_TIME))
00519 {
00520 LLString help_string = mEditor->getText().substr(segment->getStart(), segment->getEnd() - segment->getStart());
00521 setHelpPage(help_string);
00522 mLiveHelpTimer.stop();
00523 }
00524 }
00525 else if (immediate)
00526 {
00527 setHelpPage("");
00528 }
00529 }
00530
00531 void LLScriptEdCore::setHelpPage(const LLString& help_string)
00532 {
00533 LLFloater* help_floater = mLiveHelpHandle.get();
00534 if (!help_floater) return;
00535
00536 LLWebBrowserCtrl* web_browser = help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
00537 if (!web_browser) return;
00538
00539 LLComboBox* history_combo = help_floater->getChild<LLComboBox>("history_combo");
00540 if (!history_combo) return;
00541
00542 LLUIString url_string = gSavedSettings.getString("LSLHelpURL");
00543 url_string.setArg("[APP_DIRECTORY]", gDirUtilp->getWorkingDir());
00544 url_string.setArg("[LSL_STRING]", help_string);
00545
00546 addHelpItemToHistory(help_string);
00547
00548 web_browser->navigateTo(url_string);
00549
00550 }
00551
00552 void LLScriptEdCore::addHelpItemToHistory(const LLString& help_string)
00553 {
00554 if (help_string.empty()) return;
00555
00556 LLFloater* help_floater = mLiveHelpHandle.get();
00557 if (!help_floater) return;
00558
00559 LLComboBox* history_combo = help_floater->getChild<LLComboBox>("history_combo");
00560 if (!history_combo) return;
00561
00562
00563 if (mLiveHelpHistorySize == 0)
00564 {
00565 LLSD row;
00566 row["columns"][0]["type"] = "separator";
00567 history_combo->addElement(row, ADD_TOP);
00568 }
00569
00570 while(mLiveHelpHistorySize > MAX_HISTORY_COUNT - 1)
00571 {
00572 history_combo->remove(mLiveHelpHistorySize - 1);
00573 mLiveHelpHistorySize--;
00574 }
00575
00576 history_combo->setSimple(help_string);
00577 S32 index = history_combo->getCurrentIndex();
00578
00579
00580 if (index >= 0)
00581 {
00582 S32 cur_index = history_combo->getCurrentIndex();
00583 if (cur_index < mLiveHelpHistorySize)
00584 {
00585
00586 history_combo->remove(history_combo->getCurrentIndex());
00587 mLiveHelpHistorySize--;
00588 }
00589 }
00590 history_combo->add(help_string, LLSD(help_string), ADD_TOP);
00591 history_combo->selectFirstItem();
00592 mLiveHelpHistorySize++;
00593 }
00594
00595 BOOL LLScriptEdCore::canClose()
00596 {
00597 if(mForceClose || mEditor->isPristine())
00598 {
00599 return TRUE;
00600 }
00601 else
00602 {
00603
00604 gViewerWindow->alertXml("SaveChanges", LLScriptEdCore::handleSaveChangesDialog, this);
00605 return FALSE;
00606 }
00607 }
00608
00609
00610 void LLScriptEdCore::handleSaveChangesDialog( S32 option, void* userdata )
00611 {
00612 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
00613 switch( option )
00614 {
00615 case 0:
00616
00617 LLScriptEdCore::doSave( self, TRUE );
00618 break;
00619
00620 case 1:
00621 self->mForceClose = TRUE;
00622
00623
00624 ((LLFloater*) self->getParent())->close();
00625 break;
00626
00627 case 2:
00628 default:
00629
00630 LLAppViewer::instance()->abortQuit();
00631 break;
00632 }
00633 }
00634
00635
00636 void LLScriptEdCore::onHelpWebDialog(S32 option, void* userdata)
00637 {
00638 LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
00639
00640 switch(option)
00641 {
00642 case 0:
00643 load_url_local_file(corep->mHelpFile.c_str());
00644 break;
00645 default:
00646 break;
00647 }
00648 }
00649
00650
00651 void LLScriptEdCore::onBtnHelp(void* userdata)
00652 {
00653 gViewerWindow->alertXml("WebLaunchLSLGuide",
00654 onHelpWebDialog,
00655 userdata);
00656 }
00657
00658
00659 void LLScriptEdCore::onBtnDynamicHelp(void* userdata)
00660 {
00661 LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
00662
00663 LLFloater* live_help_floater = corep->mLiveHelpHandle.get();
00664 if (live_help_floater)
00665 {
00666 live_help_floater->setFocus(TRUE);
00667 corep->updateDynamicHelp(TRUE);
00668
00669 return;
00670 }
00671
00672 live_help_floater = new LLFloater("lsl_help");
00673 LLUICtrlFactory::getInstance()->buildFloater(live_help_floater, "floater_lsl_guide.xml");
00674 ((LLFloater*)corep->getParent())->addDependentFloater(live_help_floater, TRUE);
00675 live_help_floater->childSetCommitCallback("lock_check", onCheckLock, userdata);
00676 live_help_floater->childSetValue("lock_check", gSavedSettings.getBOOL("ScriptHelpFollowsCursor"));
00677 live_help_floater->childSetCommitCallback("history_combo", onHelpComboCommit, userdata);
00678 live_help_floater->childSetAction("back_btn", onClickBack, userdata);
00679 live_help_floater->childSetAction("fwd_btn", onClickForward, userdata);
00680
00681 LLWebBrowserCtrl* browser = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
00682 browser->setAlwaysRefresh(TRUE);
00683
00684 LLComboBox* help_combo = live_help_floater->getChild<LLComboBox>("history_combo");
00685 LLKeywordToken *token;
00686 LLKeywords::keyword_iterator_t token_it;
00687 for (token_it = corep->mEditor->keywordsBegin();
00688 token_it != corep->mEditor->keywordsEnd();
00689 ++token_it)
00690 {
00691 token = token_it->second;
00692 help_combo->add(wstring_to_utf8str(token->getToken()));
00693 }
00694 help_combo->sortByName();
00695
00696
00697 corep->mLastHelpToken = NULL;
00698 corep->mLiveHelpHandle = live_help_floater->getHandle();
00699 corep->mLiveHelpHistorySize = 0;
00700 corep->updateDynamicHelp(TRUE);
00701 }
00702
00703
00704 void LLScriptEdCore::onClickBack(void* userdata)
00705 {
00706 LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
00707 LLFloater* live_help_floater = corep->mLiveHelpHandle.get();
00708 if (live_help_floater)
00709 {
00710 LLWebBrowserCtrl* browserp = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
00711 if (browserp)
00712 {
00713 browserp->navigateBack();
00714 }
00715 }
00716 }
00717
00718
00719 void LLScriptEdCore::onClickForward(void* userdata)
00720 {
00721 LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
00722 LLFloater* live_help_floater = corep->mLiveHelpHandle.get();
00723 if (live_help_floater)
00724 {
00725 LLWebBrowserCtrl* browserp = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
00726 if (browserp)
00727 {
00728 browserp->navigateForward();
00729 }
00730 }
00731 }
00732
00733
00734 void LLScriptEdCore::onCheckLock(LLUICtrl* ctrl, void* userdata)
00735 {
00736 LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
00737
00738
00739 gSavedSettings.setBOOL("ScriptHelpFollowsCursor", ctrl->getValue().asBoolean());
00740
00741 corep->mLastHelpToken = NULL;
00742 }
00743
00744
00745 void LLScriptEdCore::onBtnInsertSample(void* userdata)
00746 {
00747 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
00748
00749
00750 self->mEditor->selectAll();
00751 self->mEditor->cut();
00752 self->mEditor->insertText(self->mSampleText);
00753 }
00754
00755
00756 void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata)
00757 {
00758 LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
00759
00760 LLFloater* live_help_floater = corep->mLiveHelpHandle.get();
00761 if (live_help_floater)
00762 {
00763 LLString help_string = ctrl->getValue().asString();
00764
00765 corep->addHelpItemToHistory(help_string);
00766
00767 LLWebBrowserCtrl* web_browser = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
00768 LLUIString url_string = gSavedSettings.getString("LSLHelpURL");
00769 url_string.setArg("[APP_DIRECTORY]", gDirUtilp->getWorkingDir());
00770 url_string.setArg("[LSL_STRING]", help_string);
00771 web_browser->navigateTo(url_string);
00772 }
00773 }
00774
00775
00776 void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata)
00777 {
00778 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
00779
00780
00781 if(self->mEditor->getEnabled())
00782 {
00783 self->mEditor->insertText(self->mFunctions->getSimple());
00784 }
00785 self->mEditor->setFocus(TRUE);
00786 self->setHelpPage(self->mFunctions->getSimple());
00787 }
00788
00789
00790 void LLScriptEdCore::doSave( void* userdata, BOOL close_after_save )
00791 {
00792 LLViewerStats::getInstance()->incStat( LLViewerStats::ST_LSL_SAVE_COUNT );
00793
00794 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
00795
00796 if( self->mSaveCallback )
00797 {
00798 self->mSaveCallback( self->mUserdata, close_after_save );
00799 }
00800 }
00801
00802
00803 void LLScriptEdCore::onBtnSave(void* data)
00804 {
00805
00806 doSave(data, FALSE);
00807 }
00808
00809
00810 void LLScriptEdCore::onBtnUndoChanges( void* userdata )
00811 {
00812 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
00813 if( !self->mEditor->tryToRevertToPristineState() )
00814 {
00815 gViewerWindow->alertXml("ScriptCannotUndo",
00816 LLScriptEdCore::handleReloadFromServerDialog, self);
00817 }
00818 }
00819
00820 void LLScriptEdCore::onSearchMenu(void* userdata)
00821 {
00822 LLScriptEdCore* sec = (LLScriptEdCore*)userdata;
00823 LLFloaterScriptSearch::show(sec);
00824 }
00825
00826
00827 void LLScriptEdCore::onUndoMenu(void* userdata)
00828 {
00829 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00830 if (!self || !self->mEditor) return;
00831 self->mEditor->undo();
00832 }
00833
00834
00835 void LLScriptEdCore::onRedoMenu(void* userdata)
00836 {
00837 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00838 if (!self || !self->mEditor) return;
00839 self->mEditor->redo();
00840 }
00841
00842
00843 void LLScriptEdCore::onCutMenu(void* userdata)
00844 {
00845 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00846 if (!self || !self->mEditor) return;
00847 self->mEditor->cut();
00848 }
00849
00850
00851 void LLScriptEdCore::onCopyMenu(void* userdata)
00852 {
00853 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00854 if (!self || !self->mEditor) return;
00855 self->mEditor->copy();
00856 }
00857
00858
00859 void LLScriptEdCore::onPasteMenu(void* userdata)
00860 {
00861 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00862 if (!self || !self->mEditor) return;
00863 self->mEditor->paste();
00864 }
00865
00866
00867 void LLScriptEdCore::onSelectAllMenu(void* userdata)
00868 {
00869 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00870 if (!self || !self->mEditor) return;
00871 self->mEditor->selectAll();
00872 }
00873
00874
00875 void LLScriptEdCore::onDeselectMenu(void* userdata)
00876 {
00877 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00878 if (!self || !self->mEditor) return;
00879 self->mEditor->deselect();
00880 }
00881
00882
00883 BOOL LLScriptEdCore::enableUndoMenu(void* userdata)
00884 {
00885 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00886 if (!self || !self->mEditor) return FALSE;
00887 return self->mEditor->canUndo();
00888 }
00889
00890
00891 BOOL LLScriptEdCore::enableRedoMenu(void* userdata)
00892 {
00893 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00894 if (!self || !self->mEditor) return FALSE;
00895 return self->mEditor->canRedo();
00896 }
00897
00898
00899 BOOL LLScriptEdCore::enableCutMenu(void* userdata)
00900 {
00901 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00902 if (!self || !self->mEditor) return FALSE;
00903 return self->mEditor->canCut();
00904 }
00905
00906
00907 BOOL LLScriptEdCore::enableCopyMenu(void* userdata)
00908 {
00909 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00910 if (!self || !self->mEditor) return FALSE;
00911 return self->mEditor->canCopy();
00912 }
00913
00914
00915 BOOL LLScriptEdCore::enablePasteMenu(void* userdata)
00916 {
00917 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00918 if (!self || !self->mEditor) return FALSE;
00919 return self->mEditor->canPaste();
00920 }
00921
00922
00923 BOOL LLScriptEdCore::enableSelectAllMenu(void* userdata)
00924 {
00925 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00926 if (!self || !self->mEditor) return FALSE;
00927 return self->mEditor->canSelectAll();
00928 }
00929
00930
00931 BOOL LLScriptEdCore::enableDeselectMenu(void* userdata)
00932 {
00933 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
00934 if (!self || !self->mEditor) return FALSE;
00935 return self->mEditor->canDeselect();
00936 }
00937
00938
00939 void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data)
00940 {
00941 LLScriptEdCore* self = (LLScriptEdCore*)user_data;
00942 LLScrollListItem* item = self->mErrorList->getFirstSelected();
00943 if(item)
00944 {
00945
00946
00947 S32 row = 0;
00948 S32 column = 0;
00949 const LLScrollListCell* cell = item->getColumn(0);
00950 LLString line(cell->getValue().asString());
00951 line.erase(0, 1);
00952 LLString::replaceChar(line, ',',' ');
00953 LLString::replaceChar(line, ')',' ');
00954 sscanf(line.c_str(), "%d %d", &row, &column);
00955
00956
00957 self->mEditor->setCursor(row, column);
00958 self->mEditor->setFocus(TRUE);
00959 }
00960 }
00961
00962
00963 void LLScriptEdCore::handleReloadFromServerDialog( S32 option, void* userdata )
00964 {
00965 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
00966 switch( option )
00967 {
00968 case 0:
00969 if( self->mLoadCallback )
00970 {
00971 self->mEditor->setText( self->getString("loading") );
00972 self->mLoadCallback( self->mUserdata );
00973 }
00974 break;
00975
00976 case 1:
00977 break;
00978
00979 default:
00980 llassert(0);
00981 break;
00982 }
00983 }
00984
00985 void LLScriptEdCore::selectFirstError()
00986 {
00987
00988 mErrorList->selectFirstItem();
00989 onErrorList(mErrorList, this);
00990 }
00991
00992
00993 struct LLEntryAndEdCore
00994 {
00995 LLScriptEdCore* mCore;
00996 LLEntryAndEdCore(LLScriptEdCore* core) :
00997 mCore(core)
00998 {}
00999 };
01000
01001 void LLScriptEdCore::deleteBridges()
01002 {
01003 S32 count = mBridges.count();
01004 LLEntryAndEdCore* eandc;
01005 for(S32 i = 0; i < count; i++)
01006 {
01007 eandc = mBridges.get(i);
01008 delete eandc;
01009 mBridges[i] = NULL;
01010 }
01011 mBridges.reset();
01012 }
01013
01014
01015 BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask)
01016 {
01017 bool just_control = MASK_CONTROL == (mask & MASK_MODIFIERS);
01018
01019 if(('S' == key) && just_control)
01020 {
01021 if(mSaveCallback)
01022 {
01023
01024 mSaveCallback(mUserdata, FALSE);
01025 }
01026
01027 return TRUE;
01028 }
01029
01030 if(('F' == key) && just_control)
01031 {
01032 if(mSearchReplaceCallback)
01033 {
01034 mSearchReplaceCallback(mUserdata);
01035 }
01036
01037 return TRUE;
01038 }
01039
01040 return FALSE;
01041 }
01042
01046
01047 struct LLScriptSaveInfo
01048 {
01049 LLUUID mItemUUID;
01050 LLString mDescription;
01051 LLTransactionID mTransactionID;
01052
01053 LLScriptSaveInfo(const LLUUID& uuid, const LLString& desc, LLTransactionID tid) :
01054 mItemUUID(uuid), mDescription(desc), mTransactionID(tid) {}
01055 };
01056
01057
01058
01059
01060 void* LLPreviewLSL::createScriptEdPanel(void* userdata)
01061 {
01062
01063 LLPreviewLSL *self = (LLPreviewLSL*)userdata;
01064
01065 self->mScriptEd = new LLScriptEdCore("script panel",
01066 LLRect(),
01067 HELLO_LSL,
01068 HELP_LSL,
01069 self->getHandle(),
01070 LLPreviewLSL::onLoad,
01071 LLPreviewLSL::onSave,
01072 LLPreviewLSL::onSearchReplace,
01073 self,
01074 0);
01075
01076 return self->mScriptEd;
01077 }
01078
01079
01080 LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect,
01081 const std::string& title, const LLUUID& item_id )
01082 : LLPreview( name, rect, title, item_id, LLUUID::null, TRUE,
01083 SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT ),
01084 mPendingUploads(0)
01085 {
01086
01087 LLRect curRect = rect;
01088
01089
01090 LLCallbackMap::map_t factory_map;
01091 factory_map["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this);
01092
01093
01094 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_preview.xml", &factory_map);
01095
01096 const LLInventoryItem* item = getItem();
01097
01098 childSetCommitCallback("desc", LLPreview::onText, this);
01099 childSetText("desc", item->getDescription());
01100 childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
01101
01102 if (!getFloaterHost() && !getHost() && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
01103 {
01104 loadAsset();
01105 }
01106
01107 setTitle(title);
01108
01109 if (!getHost())
01110 {
01111 reshape(curRect.getWidth(), curRect.getHeight(), TRUE);
01112 setRect(curRect);
01113 }
01114 }
01115
01116
01117 void LLPreviewLSL::callbackLSLCompileSucceeded()
01118 {
01119 llinfos << "LSL Bytecode saved" << llendl;
01120 mScriptEd->mErrorList->addCommentText("Compile successful!");
01121 mScriptEd->mErrorList->addCommentText("Save complete.");
01122 closeIfNeeded();
01123 }
01124
01125
01126 void LLPreviewLSL::callbackLSLCompileFailed(const LLSD& compile_errors)
01127 {
01128 llinfos << "Compile failed!" << llendl;
01129
01130 for(LLSD::array_const_iterator line = compile_errors.beginArray();
01131 line < compile_errors.endArray();
01132 line++)
01133 {
01134 LLSD row;
01135 row["columns"][0]["value"] = line->asString();
01136 row["columns"][0]["font"] = "OCRA";
01137 mScriptEd->mErrorList->addElement(row);
01138 }
01139 mScriptEd->selectFirstError();
01140 closeIfNeeded();
01141 }
01142
01143 void LLPreviewLSL::loadAsset()
01144 {
01145
01146
01147
01148 const LLInventoryItem* item = gInventory.getItem(mItemUUID);
01149 BOOL is_library = item
01150 && !gInventory.isObjectDescendentOf(mItemUUID,
01151 gAgent.getInventoryRootID());
01152 if(!item)
01153 {
01154
01155 getItem();
01156 }
01157 if(item)
01158 {
01159 BOOL is_copyable = gAgent.allowOperation(PERM_COPY,
01160 item->getPermissions(), GP_OBJECT_MANIPULATE);
01161 BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY,
01162 item->getPermissions(), GP_OBJECT_MANIPULATE);
01163 if (gAgent.isGodlike() || (is_copyable && (is_modifiable || is_library)))
01164 {
01165 LLUUID* new_uuid = new LLUUID(mItemUUID);
01166 gAssetStorage->getInvItemAsset(LLHost::invalid,
01167 gAgent.getID(),
01168 gAgent.getSessionID(),
01169 item->getPermissions().getOwner(),
01170 LLUUID::null,
01171 item->getUUID(),
01172 item->getAssetUUID(),
01173 item->getType(),
01174 &LLPreviewLSL::onLoadComplete,
01175 (void*)new_uuid,
01176 TRUE);
01177 mAssetStatus = PREVIEW_ASSET_LOADING;
01178 }
01179 else
01180 {
01181 mScriptEd->mEditor->setText(mScriptEd->getString("can_not_view"));
01182 mScriptEd->mEditor->makePristine();
01183 mScriptEd->mEditor->setEnabled(FALSE);
01184 mScriptEd->mFunctions->setEnabled(FALSE);
01185 mAssetStatus = PREVIEW_ASSET_LOADED;
01186 }
01187 childSetVisible("lock", !is_modifiable);
01188 mScriptEd->childSetEnabled("Insert...", is_modifiable);
01189 }
01190 else
01191 {
01192 mScriptEd->mEditor->setText(LLString(HELLO_LSL));
01193 mAssetStatus = PREVIEW_ASSET_LOADED;
01194 }
01195 }
01196
01197
01198 BOOL LLPreviewLSL::canClose()
01199 {
01200 return mScriptEd->canClose();
01201 }
01202
01203 void LLPreviewLSL::closeIfNeeded()
01204 {
01205
01206 getWindow()->decBusyCount();
01207 mPendingUploads--;
01208 if (mPendingUploads <= 0 && mCloseAfterSave)
01209 {
01210 close();
01211 }
01212 }
01213
01214
01215 void LLPreviewLSL::open()
01216 {
01217 LLFloater::open();
01218 }
01219
01220 void LLPreviewLSL::onSearchReplace(void* userdata)
01221 {
01222 LLPreviewLSL* self = (LLPreviewLSL*)userdata;
01223 LLScriptEdCore* sec = self->mScriptEd;
01224 LLFloaterScriptSearch::show(sec);
01225 }
01226
01227
01228 void LLPreviewLSL::onLoad(void* userdata)
01229 {
01230 LLPreviewLSL* self = (LLPreviewLSL*)userdata;
01231 self->loadAsset();
01232 }
01233
01234
01235 void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save)
01236 {
01237 LLPreviewLSL* self = (LLPreviewLSL*)userdata;
01238 self->mCloseAfterSave = close_after_save;
01239 self->saveIfNeeded();
01240 }
01241
01242
01243
01244
01245
01246 void LLPreviewLSL::saveIfNeeded()
01247 {
01248
01249 if(mScriptEd->mEditor->isPristine())
01250 {
01251 return;
01252 }
01253
01254 mPendingUploads = 0;
01255 mScriptEd->mErrorList->deleteAllItems();
01256 mScriptEd->mEditor->makePristine();
01257
01258
01259 LLTransactionID tid;
01260 tid.generate();
01261 LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
01262 std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString());
01263 std::string filename = llformat("%s.lsl", filepath.c_str());
01264
01265 LLFILE* fp = LLFile::fopen(filename.c_str(), "wb");
01266 if(!fp)
01267 {
01268 llwarns << "Unable to write to " << filename << llendl;
01269
01270 LLSD row;
01271 row["columns"][0]["value"] = "Error writing to local file. Is your hard drive full?";
01272 row["columns"][0]["font"] = "SANSSERIF_SMALL";
01273 mScriptEd->mErrorList->addElement(row);
01274 return;
01275 }
01276
01277 LLString utf8text = mScriptEd->mEditor->getText();
01278 fputs(utf8text.c_str(), fp);
01279 fclose(fp);
01280 fp = NULL;
01281
01282 const LLInventoryItem *inv_item = getItem();
01283
01284 std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgentInventory");
01285 if(inv_item)
01286 {
01287 getWindow()->incBusyCount();
01288 mPendingUploads++;
01289 if (!url.empty())
01290 {
01291 uploadAssetViaCaps(url, filename, mItemUUID);
01292 }
01293 else if (gAssetStorage)
01294 {
01295 uploadAssetLegacy(filename, mItemUUID, tid);
01296 }
01297 }
01298 }
01299
01300 void LLPreviewLSL::uploadAssetViaCaps(const std::string& url,
01301 const std::string& filename,
01302 const LLUUID& item_id)
01303 {
01304 llinfos << "Update Agent Inventory via capability" << llendl;
01305 LLSD body;
01306 body["item_id"] = item_id;
01307 LLHTTPClient::post(url, body, new LLUpdateAgentInventoryResponder(body, filename));
01308 }
01309
01310 void LLPreviewLSL::uploadAssetLegacy(const std::string& filename,
01311 const LLUUID& item_id,
01312 const LLTransactionID& tid)
01313 {
01314 LLLineEditor* descEditor = getChild<LLLineEditor>("desc");
01315 LLScriptSaveInfo* info = new LLScriptSaveInfo(item_id,
01316 descEditor->getText(),
01317 tid);
01318 gAssetStorage->storeAssetData(filename.c_str(), tid,
01319 LLAssetType::AT_LSL_TEXT,
01320 &LLPreviewLSL::onSaveComplete,
01321 info);
01322
01323 LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
01324 std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString());
01325 std::string dst_filename = llformat("%s.lso", filepath.c_str());
01326 std::string err_filename = llformat("%s.out", filepath.c_str());
01327
01328 if(!lscript_compile(filename.c_str(),
01329 dst_filename.c_str(),
01330 err_filename.c_str(),
01331 gAgent.isGodlike()))
01332 {
01333 llinfos << "Compile failed!" << llendl;
01334
01335
01336
01337
01338
01339 LLFILE* fp = LLFile::fopen(err_filename.c_str(), "r");
01340 if(fp)
01341 {
01342 char buffer[MAX_STRING];
01343 LLString line;
01344 while(!feof(fp))
01345 {
01346 if (fgets(buffer, MAX_STRING, fp) == NULL)
01347 {
01348 buffer[0] = '\0';
01349 }
01350 if(feof(fp))
01351 {
01352 break;
01353 }
01354 else
01355 {
01356 line.assign(buffer);
01357 LLString::stripNonprintable(line);
01358
01359 LLSD row;
01360 row["columns"][0]["value"] = line;
01361 row["columns"][0]["font"] = "OCRA";
01362 mScriptEd->mErrorList->addElement(row);
01363 }
01364 }
01365 fclose(fp);
01366 mScriptEd->selectFirstError();
01367 }
01368 }
01369 else
01370 {
01371 llinfos << "Compile worked!" << llendl;
01372 if(gAssetStorage)
01373 {
01374 getWindow()->incBusyCount();
01375 mPendingUploads++;
01376 LLUUID* this_uuid = new LLUUID(mItemUUID);
01377 gAssetStorage->storeAssetData(dst_filename.c_str(),
01378 tid,
01379 LLAssetType::AT_LSL_BYTECODE,
01380 &LLPreviewLSL::onSaveBytecodeComplete,
01381 (void**)this_uuid);
01382 }
01383 }
01384
01385
01386 LLFile::remove(filename.c_str());
01387 LLFile::remove(err_filename.c_str());
01388 LLFile::remove(dst_filename.c_str());
01389 }
01390
01391
01392
01393 void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status)
01394 {
01395 LLScriptSaveInfo* info = reinterpret_cast<LLScriptSaveInfo*>(user_data);
01396 if(0 == status)
01397 {
01398 if (info)
01399 {
01400 const LLViewerInventoryItem* item;
01401 item = (const LLViewerInventoryItem*)gInventory.getItem(info->mItemUUID);
01402 if(item)
01403 {
01404 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
01405 new_item->setAssetUUID(asset_uuid);
01406 new_item->setTransactionID(info->mTransactionID);
01407 new_item->updateServer(FALSE);
01408 gInventory.updateItem(new_item);
01409 gInventory.notifyObservers();
01410 }
01411 else
01412 {
01413 llwarns << "Inventory item for script " << info->mItemUUID
01414 << " is no longer in agent inventory." << llendl
01415 }
01416
01417
01418 LLPreviewLSL* self = (LLPreviewLSL*)LLPreview::find(info->mItemUUID);
01419 if (self)
01420 {
01421 getWindow()->decBusyCount();
01422 self->mPendingUploads--;
01423 if (self->mPendingUploads <= 0
01424 && self->mCloseAfterSave)
01425 {
01426 self->close();
01427 }
01428 }
01429 }
01430 }
01431 else
01432 {
01433 llwarns << "Problem saving script: " << status << llendl;
01434 LLStringBase<char>::format_map_t args;
01435 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
01436 gViewerWindow->alertXml("SaveScriptFailReason", args);
01437 }
01438 delete info;
01439 }
01440
01441
01442 void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status)
01443 {
01444 LLUUID* instance_uuid = (LLUUID*)user_data;
01445 LLPreviewLSL* self = NULL;
01446 if(instance_uuid)
01447 {
01448 self = LLPreviewLSL::getInstance(*instance_uuid);
01449 }
01450 if (0 == status)
01451 {
01452 if (self)
01453 {
01454 LLSD row;
01455 row["columns"][0]["value"] = "Compile successful!";
01456 row["columns"][0]["font"] = "SANSSERIF_SMALL";
01457 self->mScriptEd->mErrorList->addElement(row);
01458
01459
01460 self->getWindow()->decBusyCount();
01461 self->mPendingUploads--;
01462 if (self->mPendingUploads <= 0
01463 && self->mCloseAfterSave)
01464 {
01465 self->close();
01466 }
01467 }
01468 }
01469 else
01470 {
01471 llwarns << "Problem saving LSL Bytecode (Preview)" << llendl;
01472 LLStringBase<char>::format_map_t args;
01473 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
01474 gViewerWindow->alertXml("SaveBytecodeFailReason", args);
01475 }
01476 delete instance_uuid;
01477 }
01478
01479
01480 void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAssetType::EType type,
01481 void* user_data, S32 status, LLExtStat ext_status)
01482 {
01483 lldebugs << "LLPreviewLSL::onLoadComplete: got uuid " << asset_uuid
01484 << llendl;
01485 LLUUID* item_uuid = (LLUUID*)user_data;
01486 LLPreviewLSL* preview = LLPreviewLSL::getInstance(*item_uuid);
01487 if( preview )
01488 {
01489 if(0 == status)
01490 {
01491 LLVFile file(vfs, asset_uuid, type);
01492 S32 file_length = file.getSize();
01493
01494 char* buffer = new char[file_length+1];
01495 file.read((U8*)buffer, file_length);
01496
01497
01498 buffer[file_length] = 0;
01499 preview->mScriptEd->mEditor->setText(LLStringExplicit(buffer));
01500 preview->mScriptEd->mEditor->makePristine();
01501 delete [] buffer;
01502 LLInventoryItem* item = gInventory.getItem(*item_uuid);
01503 BOOL is_modifiable = FALSE;
01504 if(item
01505 && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
01506 GP_OBJECT_MANIPULATE))
01507 {
01508 is_modifiable = TRUE;
01509 }
01510 preview->mScriptEd->mEditor->setEnabled(is_modifiable);
01511 preview->mAssetStatus = PREVIEW_ASSET_LOADED;
01512 }
01513 else
01514 {
01515 LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
01516
01517 if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
01518 LL_ERR_FILE_EMPTY == status)
01519 {
01520 LLNotifyBox::showXml("ScriptMissing");
01521 }
01522 else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
01523 {
01524 LLNotifyBox::showXml("ScriptNoPermissions");
01525 }
01526 else
01527 {
01528 LLNotifyBox::showXml("UnableToLoadScript");
01529 }
01530
01531 preview->mAssetStatus = PREVIEW_ASSET_ERROR;
01532 llwarns << "Problem loading script: " << status << llendl;
01533 }
01534 }
01535 delete item_uuid;
01536 }
01537
01538
01539 LLPreviewLSL* LLPreviewLSL::getInstance( const LLUUID& item_uuid )
01540 {
01541 LLPreview* instance = NULL;
01542 preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
01543 if(found_it != LLPreview::sInstances.end())
01544 {
01545 instance = found_it->second;
01546 }
01547 return (LLPreviewLSL*)instance;
01548 }
01549
01550 void LLPreviewLSL::reshape(S32 width, S32 height, BOOL called_from_parent)
01551 {
01552 LLPreview::reshape( width, height, called_from_parent );
01553
01554 if( !isMinimized() )
01555 {
01556
01557
01558 gSavedSettings.setRect("PreviewScriptRect", getRect());
01559 }
01560 }
01561
01565
01566 LLMap<LLUUID, LLLiveLSLEditor*> LLLiveLSLEditor::sInstances;
01567
01568
01569
01570
01571 void* LLLiveLSLEditor::createScriptEdPanel(void* userdata)
01572 {
01573
01574 LLLiveLSLEditor *self = (LLLiveLSLEditor*)userdata;
01575
01576 self->mScriptEd = new LLScriptEdCore("script ed panel",
01577 LLRect(),
01578 HELLO_LSL,
01579 HELP_LSL,
01580 self->getHandle(),
01581 &LLLiveLSLEditor::onLoad,
01582 &LLLiveLSLEditor::onSave,
01583 &LLLiveLSLEditor::onSearchReplace,
01584 self,
01585 0);
01586
01587 return self->mScriptEd;
01588 }
01589
01590
01591 LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name,
01592 const LLRect& rect,
01593 const std::string& title,
01594 const LLUUID& object_id,
01595 const LLUUID& item_id) :
01596 LLPreview(name, rect, title, item_id, object_id, TRUE, SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT),
01597 mObjectID(object_id),
01598 mItemID(item_id),
01599 mScriptEd(NULL),
01600 mAskedForRunningInfo(FALSE),
01601 mHaveRunningInfo(FALSE),
01602 mCloseAfterSave(FALSE),
01603 mPendingUploads(0)
01604 {
01605
01606
01607 BOOL is_new = FALSE;
01608 if(mItemID.isNull())
01609 {
01610 mItemID.generate();
01611 is_new = TRUE;
01612 }
01613
01614
01615 LLLiveLSLEditor::sInstances.addData(mItemID ^ mObjectID, this);
01616
01617
01618
01619 LLCallbackMap::map_t factory_map;
01620 factory_map["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this);
01621
01622 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_live_lsleditor.xml", &factory_map);
01623
01624
01625 childSetCommitCallback("running", LLLiveLSLEditor::onRunningCheckboxClicked, this);
01626 childSetEnabled("running", FALSE);
01627
01628 childSetAction("Reset",&LLLiveLSLEditor::onReset,this);
01629 childSetEnabled("Reset", TRUE);
01630
01631
01632 mScriptEd->mEditor->makePristine();
01633 loadAsset(is_new);
01634 mScriptEd->mEditor->setFocus(TRUE);
01635
01636
01637 if (!getHost())
01638 {
01639 LLRect curRect = getRect();
01640 translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
01641 }
01642
01643
01644 setTitle(title);
01645 }
01646
01647 LLLiveLSLEditor::~LLLiveLSLEditor()
01648 {
01649 LLLiveLSLEditor::sInstances.removeData(mItemID ^ mObjectID);
01650 }
01651
01652
01653 void LLLiveLSLEditor::loadAsset()
01654 {
01655 loadAsset(FALSE);
01656 }
01657
01658
01659 void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id,
01660 const LLUUID& item_id,
01661 bool is_script_running)
01662 {
01663 lldebugs << "LSL Bytecode saved" << llendl;
01664 mScriptEd->mErrorList->addCommentText("Compile successful!");
01665 mScriptEd->mErrorList->addCommentText("Save complete.");
01666 closeIfNeeded();
01667 }
01668
01669
01670 void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors)
01671 {
01672 lldebugs << "Compile failed!" << llendl;
01673 for(LLSD::array_const_iterator line = compile_errors.beginArray();
01674 line < compile_errors.endArray();
01675 line++)
01676 {
01677 LLSD row;
01678 row["columns"][0]["value"] = line->asString();
01679 row["columns"][0]["font"] = "OCRA";
01680 mScriptEd->mErrorList->addElement(row);
01681 }
01682 mScriptEd->selectFirstError();
01683 closeIfNeeded();
01684 }
01685
01686 void LLLiveLSLEditor::loadAsset(BOOL is_new)
01687 {
01688
01689 if(!is_new)
01690 {
01691 LLViewerObject* object = gObjectList.findObject(mObjectID);
01692 if(object)
01693 {
01694
01695 LLViewerInventoryItem* item = (LLViewerInventoryItem*)object->getInventoryObject(mItemID);
01696 if(item
01697 && (gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE)
01698 || gAgent.isGodlike()))
01699 {
01700 mItem = new LLViewerInventoryItem(item);
01701
01702 }
01703
01704 if(!gAgent.isGodlike()
01705 && (item
01706 && (!gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE)
01707 || !gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE))))
01708 {
01709 mItem = new LLViewerInventoryItem(item);
01710 mScriptEd->mEditor->setText(getString("not_allowed"));
01711 mScriptEd->mEditor->makePristine();
01712 mScriptEd->mEditor->setEnabled(FALSE);
01713 mAssetStatus = PREVIEW_ASSET_LOADED;
01714 }
01715 else if(item && mItem.notNull())
01716 {
01717
01718 LLUUID* user_data = new LLUUID(mItemID ^ mObjectID);
01719 gAssetStorage->getInvItemAsset(object->getRegion()->getHost(),
01720 gAgent.getID(),
01721 gAgent.getSessionID(),
01722 item->getPermissions().getOwner(),
01723 object->getID(),
01724 item->getUUID(),
01725 item->getAssetUUID(),
01726 item->getType(),
01727 &LLLiveLSLEditor::onLoadComplete,
01728 (void*)user_data,
01729 TRUE);
01730 LLMessageSystem* msg = gMessageSystem;
01731 msg->newMessageFast(_PREHASH_GetScriptRunning);
01732 msg->nextBlockFast(_PREHASH_Script);
01733 msg->addUUIDFast(_PREHASH_ObjectID, mObjectID);
01734 msg->addUUIDFast(_PREHASH_ItemID, mItemID);
01735 msg->sendReliable(object->getRegion()->getHost());
01736 mAskedForRunningInfo = TRUE;
01737 mAssetStatus = PREVIEW_ASSET_LOADING;
01738 }
01739 else
01740 {
01741 mScriptEd->mEditor->setText(LLString::null);
01742 mScriptEd->mEditor->makePristine();
01743 mAssetStatus = PREVIEW_ASSET_LOADED;
01744 }
01745
01746 if(item
01747 && !gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
01748 GP_OBJECT_MANIPULATE))
01749 {
01750 mScriptEd->mEditor->setEnabled(FALSE);
01751 }
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766 }
01767
01768
01769
01770 if(mItem.isNull())
01771 {
01772
01773
01774
01775 mItem = new LLViewerInventoryItem();
01776 mScriptEd->mEditor->setText(LLString::null);
01777 mScriptEd->mEditor->makePristine();
01778 mScriptEd->mEditor->setEnabled(FALSE);
01779 mAssetStatus = PREVIEW_ASSET_LOADED;
01780 }
01781 }
01782 else
01783 {
01784 mScriptEd->mEditor->setText(LLString(HELLO_LSL));
01785
01786
01787 LLPermissions perm;
01788 perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, gAgent.getGroupID());
01789 perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, PERM_MOVE | PERM_TRANSFER);
01790 mItem = new LLViewerInventoryItem(mItemID,
01791 mObjectID,
01792 perm,
01793 LLUUID::null,
01794 LLAssetType::AT_LSL_TEXT,
01795 LLInventoryType::IT_LSL,
01796 DEFAULT_SCRIPT_NAME,
01797 DEFAULT_SCRIPT_DESC,
01798 LLSaleInfo::DEFAULT,
01799 LLInventoryItem::II_FLAGS_NONE,
01800 time_corrected());
01801 mAssetStatus = PREVIEW_ASSET_LOADED;
01802 }
01803 }
01804
01805
01806 void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
01807 LLAssetType::EType type,
01808 void* user_data, S32 status, LLExtStat ext_status)
01809 {
01810 lldebugs << "LLLiveLSLEditor::onLoadComplete: got uuid " << asset_id
01811 << llendl;
01812 LLLiveLSLEditor* instance = NULL;
01813 LLUUID* xored_id = (LLUUID*)user_data;
01814
01815 if( LLLiveLSLEditor::sInstances.checkData(*xored_id) )
01816 {
01817 instance = LLLiveLSLEditor::sInstances[*xored_id];
01818 if( LL_ERR_NOERR == status )
01819 {
01820 instance->loadScriptText(vfs, asset_id, type);
01821 instance->mAssetStatus = PREVIEW_ASSET_LOADED;
01822 }
01823 else
01824 {
01825 LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
01826
01827 if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
01828 LL_ERR_FILE_EMPTY == status)
01829 {
01830 LLNotifyBox::showXml("ScriptMissing");
01831 }
01832 else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
01833 {
01834 LLNotifyBox::showXml("ScriptNoPermissions");
01835 }
01836 else
01837 {
01838 LLNotifyBox::showXml("UnableToLoadScript");
01839 }
01840 instance->mAssetStatus = PREVIEW_ASSET_ERROR;
01841 }
01842 }
01843
01844 delete xored_id;
01845 }
01846
01847 void LLLiveLSLEditor::loadScriptText(const char* filename)
01848 {
01849 if(!filename)
01850 {
01851 llerrs << "Filename is Empty!" << llendl;
01852 return;
01853 }
01854 LLFILE* file = LLFile::fopen(filename, "rb");
01855 if(file)
01856 {
01857
01858 fseek(file, 0L, SEEK_END);
01859 long file_length = ftell(file);
01860 fseek(file, 0L, SEEK_SET);
01861 char* buffer = new char[file_length+1];
01862 size_t nread = fread(buffer, 1, file_length, file);
01863 if (nread < (size_t) file_length)
01864 {
01865 llwarns << "Short read" << llendl;
01866 }
01867 buffer[nread] = '\0';
01868 fclose(file);
01869 mScriptEd->mEditor->setText(LLStringExplicit(buffer));
01870 mScriptEd->mEditor->makePristine();
01871 delete[] buffer;
01872 }
01873 else
01874 {
01875 llwarns << "Error opening " << filename << llendl;
01876 }
01877 }
01878
01879 void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
01880 {
01881 LLVFile file(vfs, uuid, type);
01882 S32 file_length = file.getSize();
01883 char *buffer = new char[file_length + 1];
01884 file.read((U8*)buffer, file_length);
01885
01886 if (file.getLastBytesRead() != file_length ||
01887 file_length <= 0)
01888 {
01889 llwarns << "Error reading " << uuid << ":" << type << llendl;
01890 }
01891
01892 buffer[file_length] = '\0';
01893
01894 mScriptEd->mEditor->setText(LLStringExplicit(buffer));
01895 mScriptEd->mEditor->makePristine();
01896 delete[] buffer;
01897
01898 }
01899
01900
01901 void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata )
01902 {
01903 LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata;
01904 LLViewerObject* object = gObjectList.findObject( self->mObjectID );
01905 LLCheckBoxCtrl* runningCheckbox = self->getChild<LLCheckBoxCtrl>("running");
01906 BOOL running = runningCheckbox->get();
01907
01908 if( object )
01909 {
01910 LLMessageSystem* msg = gMessageSystem;
01911 msg->newMessageFast(_PREHASH_SetScriptRunning);
01912 msg->nextBlockFast(_PREHASH_AgentData);
01913 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01914 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01915 msg->nextBlockFast(_PREHASH_Script);
01916 msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectID);
01917 msg->addUUIDFast(_PREHASH_ItemID, self->mItemID);
01918 msg->addBOOLFast(_PREHASH_Running, running);
01919 msg->sendReliable(object->getRegion()->getHost());
01920 }
01921 else
01922 {
01923 runningCheckbox->set(!running);
01924 gViewerWindow->alertXml("CouldNotStartStopScript");
01925 }
01926 }
01927
01928 void LLLiveLSLEditor::onReset(void *userdata)
01929 {
01930 LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata;
01931
01932 LLViewerObject* object = gObjectList.findObject( self->mObjectID );
01933 if(object)
01934 {
01935 LLMessageSystem* msg = gMessageSystem;
01936 msg->newMessageFast(_PREHASH_ScriptReset);
01937 msg->nextBlockFast(_PREHASH_AgentData);
01938 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01939 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01940 msg->nextBlockFast(_PREHASH_Script);
01941 msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectID);
01942 msg->addUUIDFast(_PREHASH_ItemID, self->mItemID);
01943 msg->sendReliable(object->getRegion()->getHost());
01944 }
01945 else
01946 {
01947 gViewerWindow->alertXml("CouldNotStartStopScript");
01948 }
01949 }
01950
01951 void LLLiveLSLEditor::draw()
01952 {
01953 LLViewerObject* object = gObjectList.findObject(mObjectID);
01954 LLCheckBoxCtrl* runningCheckbox = getChild<LLCheckBoxCtrl>( "running");
01955 if(object && mAskedForRunningInfo && mHaveRunningInfo)
01956 {
01957 if(object->permAnyOwner())
01958 {
01959 runningCheckbox->setLabel(getString("script_running"));
01960 runningCheckbox->setEnabled(TRUE);
01961 }
01962 else
01963 {
01964 runningCheckbox->setLabel(getString("public_objects_can_not_run"));
01965 runningCheckbox->setEnabled(FALSE);
01966
01967
01968
01969
01970 runningCheckbox->set(FALSE);
01971 }
01972 }
01973 else if(!object)
01974 {
01975
01976
01977 setTitle("Script (object out of range)");
01978 runningCheckbox->setEnabled(FALSE);
01979
01980 mHaveRunningInfo = FALSE;
01981 }
01982
01983 LLFloater::draw();
01984 }
01985
01986
01987 void LLLiveLSLEditor::onSearchReplace(void* userdata)
01988 {
01989 LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
01990
01991 LLScriptEdCore* sec = self->mScriptEd;
01992 LLFloaterScriptSearch::show(sec);
01993 }
01994
01995 struct LLLiveLSLSaveData
01996 {
01997 LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, BOOL active);
01998 LLUUID mObjectID;
01999 LLPointer<LLViewerInventoryItem> mItem;
02000 BOOL mActive;
02001 };
02002
02003 LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
02004 const LLViewerInventoryItem* item,
02005 BOOL active) :
02006 mObjectID(id),
02007 mActive(active)
02008 {
02009 llassert(item);
02010 mItem = new LLViewerInventoryItem(item);
02011 }
02012
02013 void LLLiveLSLEditor::saveIfNeeded()
02014 {
02015 llinfos << "LLLiveLSLEditor::saveIfNeeded()" << llendl;
02016 LLViewerObject* object = gObjectList.findObject(mObjectID);
02017 if(!object)
02018 {
02019 gViewerWindow->alertXml("SaveScriptFailObjectNotFound");
02020 return;
02021 }
02022
02023 if(mItem.isNull() || !mItem->isComplete())
02024 {
02025
02026
02027 gViewerWindow->alertXml("SaveScriptFailObjectNotFound");
02028 return;
02029 }
02030
02031
02032
02033
02034
02035
02036 LLInventoryItem* inv_item = (LLInventoryItem*)object->getInventoryObject(mItemID);
02037 if(inv_item)
02038 {
02039 mItem->copyItem(inv_item);
02040 }
02041
02042
02043 if(mScriptEd->mEditor->isPristine())
02044 {
02045 return;
02046 }
02047
02048 mPendingUploads = 0;
02049
02050
02051 mScriptEd->mEditor->makePristine();
02052 mScriptEd->mErrorList->deleteAllItems();
02053
02054
02055 mScriptEd->mEditor->makePristine();
02056 LLTransactionID tid;
02057 tid.generate();
02058 LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
02059 std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString());
02060 std::string filename = llformat("%s.lsl", filepath.c_str());
02061
02062 mItem->setAssetUUID(asset_id);
02063 mItem->setTransactionID(tid);
02064
02065
02066 LLFILE* fp = LLFile::fopen(filename.c_str(), "wb");
02067 if(!fp)
02068 {
02069 llwarns << "Unable to write to " << filename << llendl;
02070
02071 LLSD row;
02072 row["columns"][0]["value"] = "Error writing to local file. Is your hard drive full?";
02073 row["columns"][0]["font"] = "SANSSERIF_SMALL";
02074 mScriptEd->mErrorList->addElement(row);
02075 return;
02076 }
02077 LLString utf8text = mScriptEd->mEditor->getText();
02078
02079
02080 if ( utf8text.size() == 0 )
02081 {
02082 utf8text = " ";
02083 }
02084
02085 fputs(utf8text.c_str(), fp);
02086 fclose(fp);
02087 fp = NULL;
02088
02089
02090 std::string url = gAgent.getRegion()->getCapability("UpdateScriptTaskInventory");
02091 getWindow()->incBusyCount();
02092 mPendingUploads++;
02093 BOOL is_running = getChild<LLCheckBoxCtrl>( "running")->get();
02094 if (!url.empty())
02095 {
02096 uploadAssetViaCaps(url, filename, mObjectID,
02097 mItemID, is_running);
02098 }
02099 else if (gAssetStorage)
02100 {
02101 uploadAssetLegacy(filename, object, tid, is_running);
02102 }
02103 }
02104
02105 void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url,
02106 const std::string& filename,
02107 const LLUUID& task_id,
02108 const LLUUID& item_id,
02109 BOOL is_running)
02110 {
02111 llinfos << "Update Task Inventory via capability" << llendl;
02112 LLSD body;
02113 body["task_id"] = task_id;
02114 body["item_id"] = item_id;
02115 body["is_script_running"] = is_running;
02116 LLHTTPClient::post(url, body,
02117 new LLUpdateTaskInventoryResponder(body, filename));
02118 }
02119
02120 void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename,
02121 LLViewerObject* object,
02122 const LLTransactionID& tid,
02123 BOOL is_running)
02124 {
02125 LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectID,
02126 mItem,
02127 is_running);
02128 gAssetStorage->storeAssetData(filename.c_str(), tid,
02129 LLAssetType::AT_LSL_TEXT,
02130 &onSaveTextComplete,
02131 (void*)data,
02132 FALSE);
02133
02134 LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
02135 std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString());
02136 std::string dst_filename = llformat("%s.lso", filepath.c_str());
02137 std::string err_filename = llformat("%s.out", filepath.c_str());
02138
02139 LLFILE *fp;
02140 if(!lscript_compile(filename.c_str(),
02141 dst_filename.c_str(),
02142 err_filename.c_str(),
02143 gAgent.isGodlike()))
02144 {
02145
02146 llinfos << "Compile failed!" << llendl;
02147 if(NULL != (fp = LLFile::fopen(err_filename.c_str(), "r")))
02148 {
02149 char buffer[MAX_STRING];
02150 LLString line;
02151 while(!feof(fp))
02152 {
02153
02154 if (fgets(buffer, MAX_STRING, fp) == NULL)
02155 {
02156 buffer[0] = '\0';
02157 }
02158 if(feof(fp))
02159 {
02160 break;
02161 }
02162 else
02163 {
02164 line.assign(buffer);
02165 LLString::stripNonprintable(line);
02166
02167 LLSD row;
02168 row["columns"][0]["value"] = line;
02169 row["columns"][0]["font"] = "OCRA";
02170 mScriptEd->mErrorList->addElement(row);
02171 }
02172 }
02173 fclose(fp);
02174 mScriptEd->selectFirstError();
02175
02176
02177
02178 object->saveScript(mItem, FALSE, false);
02179 dialog_refresh_all();
02180 }
02181 }
02182 else
02183 {
02184 llinfos << "Compile worked!" << llendl;
02185 mScriptEd->mErrorList->addCommentText("Compile successful, saving...");
02186 if(gAssetStorage)
02187 {
02188 llinfos << "LLLiveLSLEditor::saveAsset "
02189 << mItem->getAssetUUID() << llendl;
02190 getWindow()->incBusyCount();
02191 mPendingUploads++;
02192 LLLiveLSLSaveData* data = NULL;
02193 data = new LLLiveLSLSaveData(mObjectID,
02194 mItem,
02195 is_running);
02196 gAssetStorage->storeAssetData(dst_filename.c_str(),
02197 tid,
02198 LLAssetType::AT_LSL_BYTECODE,
02199 &LLLiveLSLEditor::onSaveBytecodeComplete,
02200 (void*)data);
02201 dialog_refresh_all();
02202 }
02203 }
02204
02205
02206 LLFile::remove(filename.c_str());
02207 LLFile::remove(err_filename.c_str());
02208 LLFile::remove(dst_filename.c_str());
02209
02210
02211 LLCheckBoxCtrl* runningCheckbox = getChild<LLCheckBoxCtrl>( "running");
02212 runningCheckbox->setLabel(getString("script_running"));
02213 runningCheckbox->setEnabled(TRUE);
02214 }
02215
02216 void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status)
02217 {
02218 LLLiveLSLSaveData* data = (LLLiveLSLSaveData*)user_data;
02219
02220 if (status)
02221 {
02222 llwarns << "Unable to save text for a script." << llendl;
02223 LLStringBase<char>::format_map_t args;
02224 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
02225 gViewerWindow->alertXml("CompileQueueSaveText", args);
02226 }
02227 else
02228 {
02229 LLLiveLSLEditor* self = sInstances.getIfThere(data->mItem->getUUID() ^ data->mObjectID);
02230 if (self)
02231 {
02232 self->getWindow()->decBusyCount();
02233 self->mPendingUploads--;
02234 if (self->mPendingUploads <= 0
02235 && self->mCloseAfterSave)
02236 {
02237 self->close();
02238 }
02239 }
02240 }
02241 delete data;
02242 data = NULL;
02243 }
02244
02245
02246 void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status)
02247 {
02248 LLLiveLSLSaveData* data = (LLLiveLSLSaveData*)user_data;
02249 if(!data)
02250 return;
02251 if(0 ==status)
02252 {
02253 llinfos << "LSL Bytecode saved" << llendl;
02254 LLUUID xor_id = data->mItem->getUUID() ^ data->mObjectID;
02255 LLLiveLSLEditor* self = sInstances.getIfThere(xor_id);
02256 if(self)
02257 {
02258
02259 self->mScriptEd->mErrorList->addCommentText("Save complete.");
02260
02261 self->getWindow()->decBusyCount();
02262 self->mPendingUploads--;
02263 if (self->mPendingUploads <= 0
02264 && self->mCloseAfterSave)
02265 {
02266 self->close();
02267 }
02268 }
02269 LLViewerObject* object = gObjectList.findObject(data->mObjectID);
02270 if(object)
02271 {
02272 object->saveScript(data->mItem, data->mActive, false);
02273 dialog_refresh_all();
02274
02275
02276 }
02277 }
02278 else
02279 {
02280 llinfos << "Problem saving LSL Bytecode (Live Editor)" << llendl;
02281 llwarns << "Unable to save a compiled script." << llendl;
02282
02283 LLStringBase<char>::format_map_t args;
02284 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
02285 gViewerWindow->alertXml("CompileQueueSaveBytecode", args);
02286 }
02287
02288 std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_uuid.asString());
02289 std::string dst_filename = llformat("%s.lso", filepath.c_str());
02290 LLFile::remove(dst_filename.c_str());
02291 delete data;
02292 }
02293
02294 void LLLiveLSLEditor::open()
02295 {
02296 LLFloater::open();
02297 }
02298
02299 BOOL LLLiveLSLEditor::canClose()
02300 {
02301 return (mScriptEd->canClose());
02302 }
02303
02304 void LLLiveLSLEditor::closeIfNeeded()
02305 {
02306 getWindow()->decBusyCount();
02307 mPendingUploads--;
02308 if (mPendingUploads <= 0 && mCloseAfterSave)
02309 {
02310 close();
02311 }
02312 }
02313
02314
02315 void LLLiveLSLEditor::onLoad(void* userdata)
02316 {
02317 LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
02318 self->loadAsset();
02319 }
02320
02321
02322 void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)
02323 {
02324 LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
02325 self->mCloseAfterSave = close_after_save;
02326 self->saveIfNeeded();
02327 }
02328
02329
02330 LLLiveLSLEditor* LLLiveLSLEditor::show(const LLUUID& script_id, const LLUUID& object_id)
02331 {
02332 LLLiveLSLEditor* instance = NULL;
02333 LLUUID xored_id = script_id ^ object_id;
02334 if(LLLiveLSLEditor::sInstances.checkData(xored_id))
02335 {
02336
02337 instance = LLLiveLSLEditor::sInstances[xored_id];
02338 instance->open();
02339 }
02340 return instance;
02341 }
02342
02343
02344 void LLLiveLSLEditor::hide(const LLUUID& script_id, const LLUUID& object_id)
02345 {
02346 LLUUID xored_id = script_id ^ object_id;
02347 if( LLLiveLSLEditor::sInstances.checkData( xored_id ) )
02348 {
02349 LLLiveLSLEditor* instance = LLLiveLSLEditor::sInstances[xored_id];
02350 if(instance->getParent())
02351 {
02352 instance->getParent()->removeChild(instance);
02353 }
02354 delete instance;
02355 }
02356 }
02357
02358 LLLiveLSLEditor* LLLiveLSLEditor::find(const LLUUID& script_id, const LLUUID& object_id)
02359 {
02360 LLUUID xored_id = script_id ^ object_id;
02361 return sInstances.getIfThere(xored_id);
02362 }
02363
02364
02365
02366 void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)
02367 {
02368 LLUUID item_id;
02369 LLUUID object_id;
02370 msg->getUUIDFast(_PREHASH_Script, _PREHASH_ObjectID, object_id);
02371 msg->getUUIDFast(_PREHASH_Script, _PREHASH_ItemID, item_id);
02372 LLUUID xored_id = item_id ^ object_id;
02373 if(LLLiveLSLEditor::sInstances.checkData(xored_id))
02374 {
02375 LLLiveLSLEditor* instance = LLLiveLSLEditor::sInstances[xored_id];
02376 instance->mHaveRunningInfo = TRUE;
02377 BOOL running;
02378 msg->getBOOLFast(_PREHASH_Script, _PREHASH_Running, running);
02379 LLCheckBoxCtrl* runningCheckbox = instance->getChild<LLCheckBoxCtrl>("running");
02380 runningCheckbox->set(running);
02381 }
02382 }
02383
02384 void LLLiveLSLEditor::reshape(S32 width, S32 height, BOOL called_from_parent)
02385 {
02386 LLFloater::reshape( width, height, called_from_parent );
02387
02388 if( !isMinimized() )
02389 {
02390
02391
02392 gSavedSettings.setRect("PreviewScriptRect", getRect());
02393 }
02394 }