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