aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llpreviewscript.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llpreviewscript.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llpreviewscript.cpp')
-rw-r--r--linden/indra/newview/llpreviewscript.cpp2007
1 files changed, 2007 insertions, 0 deletions
diff --git a/linden/indra/newview/llpreviewscript.cpp b/linden/indra/newview/llpreviewscript.cpp
new file mode 100644
index 0000000..c13da9b
--- /dev/null
+++ b/linden/indra/newview/llpreviewscript.cpp
@@ -0,0 +1,2007 @@
1/**
2 * @file llpreviewscript.cpp
3 * @brief LLPreviewScript class implementation
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llpreviewscript.h"
31
32#include "llassetstorage.h"
33#include "llbutton.h"
34#include "llcheckboxctrl.h"
35#include "llcombobox.h"
36#include "lldir.h"
37#include "llinventorymodel.h"
38#include "llkeyboard.h"
39#include "lllineeditor.h"
40
41#include "llresmgr.h"
42#include "llscrollbar.h"
43#include "llscrollcontainer.h"
44#include "llscrolllistctrl.h"
45#include "llslider.h"
46#include "lscript_rt_interface.h"
47#include "lscript_export.h"
48#include "lltextbox.h"
49#include "lltooldraganddrop.h"
50#include "llvfile.h"
51
52#include "llagent.h"
53#include "llnotify.h"
54#include "llmenugl.h"
55#include "roles_constants.h"
56#include "llselectmgr.h"
57#include "llviewerinventory.h"
58#include "llviewermenu.h"
59#include "llviewerobject.h"
60#include "llviewerobjectlist.h"
61#include "llviewerregion.h"
62#include "llkeyboard.h"
63#include "llscrollcontainer.h"
64#include "llcheckboxctrl.h"
65#include "llselectmgr.h"
66#include "lltooldraganddrop.h"
67#include "llscrolllistctrl.h"
68#include "lltextbox.h"
69#include "llslider.h"
70#include "viewer.h"
71#include "lldir.h"
72#include "llcombobox.h"
73//#include "llfloaterchat.h"
74#include "llviewerstats.h"
75#include "llviewertexteditor.h"
76#include "llviewerwindow.h"
77#include "llvieweruictrlfactory.h"
78#include "lluictrlfactory.h"
79
80#include "viewer.h"
81
82#include "llpanelinventory.h"
83
84
85const char HELLO_LSL[] =
86 "default\n"
87 "{\n"
88 " state_entry()\n"
89 " {\n"
90 " llSay(0, \"Hello, Avatar!\");\n"
91 " }\n"
92 "\n"
93 " touch_start(integer total_number)\n"
94 " {\n"
95 " llSay(0, \"Touched.\");\n"
96 " }\n"
97 "}\n";
98const char HELP_LSL[] = "lsl_guide.html";
99
100const char DEFAULT_SCRIPT_NAME[] = "New Script";
101const char DEFAULT_SCRIPT_DESC[] = "(No Description)";
102
103const char ENABLED_RUNNING_CHECKBOX_LABEL[] = "Running";
104const char DISABLED_RUNNING_CHECKBOX_LABEL[] = "Public Objects cannot run scripts";
105
106// Description and header information
107
108const S32 SCRIPT_BORDER = 4;
109const S32 SCRIPT_PAD = 5;
110const S32 SCRIPT_BUTTON_WIDTH = 128;
111const S32 SCRIPT_BUTTON_HEIGHT = 24; // HACK: Use BTN_HEIGHT where possible.
112const S32 LINE_COLUMN_HEIGHT = 14;
113const S32 BTN_PAD = 8;
114
115const S32 SCRIPT_EDITOR_MIN_HEIGHT = 2 * SCROLLBAR_SIZE + 2 * LLPANEL_BORDER_WIDTH + 128;
116
117const S32 SCRIPT_MIN_WIDTH =
118 2 * SCRIPT_BORDER +
119 2 * SCRIPT_BUTTON_WIDTH +
120 SCRIPT_PAD + RESIZE_HANDLE_WIDTH +
121 SCRIPT_PAD;
122
123const S32 SCRIPT_MIN_HEIGHT =
124 2 * SCRIPT_BORDER +
125 3*(SCRIPT_BUTTON_HEIGHT + SCRIPT_PAD) +
126 LINE_COLUMN_HEIGHT +
127 SCRIPT_EDITOR_MIN_HEIGHT;
128
129const S32 MAX_EXPORT_SIZE = 1000;
130
131const S32 SCRIPT_SEARCH_WIDTH = 300;
132const S32 SCRIPT_SEARCH_HEIGHT = 120;
133const S32 SCRIPT_SEARCH_LABEL_WIDTH = 50;
134const S32 SCRIPT_SEARCH_BUTTON_WIDTH = 80;
135const S32 TEXT_EDIT_COLUMN_HEIGHT = 16;
136/// ---------------------------------------------------------------------------
137/// LLFloaterScriptSearch
138/// ---------------------------------------------------------------------------
139class LLFloaterScriptSearch : public LLFloater
140{
141public:
142 LLFloaterScriptSearch(std::string title, LLRect rect, LLScriptEdCore* editor_core);
143 ~LLFloaterScriptSearch();
144
145 static void show(LLScriptEdCore* editor_core);
146 static void onBtnSearch(void* userdata);
147 void handleBtnSearch();
148
149 static void onBtnReplace(void* userdata);
150 void handleBtnReplace();
151
152 static void onBtnReplaceAll(void* userdata);
153 void handleBtnReplaceAll();
154
155 LLScriptEdCore* getEditorCore() { return mEditorCore; }
156 static LLFloaterScriptSearch* getInstance() { return sInstance; }
157
158 void open();
159
160private:
161
162 LLScriptEdCore* mEditorCore;
163
164 static LLFloaterScriptSearch* sInstance;
165};
166
167LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL;
168
169LLFloaterScriptSearch::LLFloaterScriptSearch(std::string title, LLRect rect, LLScriptEdCore* editor_core)
170 : LLFloater("script search",rect,title), mEditorCore(editor_core)
171{
172
173 gUICtrlFactory->buildFloater(this,"floater_script_search.xml");
174
175 childSetAction("search_btn", onBtnSearch,this);
176 childSetAction("replace_btn", onBtnReplace,this);
177 childSetAction("replace_all_btn", onBtnReplaceAll,this);
178
179 setDefaultBtn("search_btn");
180
181 if (!getHost())
182 {
183 LLRect curRect = getRect();
184 translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
185 }
186
187 sInstance = this;
188
189 childSetFocus("search_text", TRUE);
190}
191
192//static
193void LLFloaterScriptSearch::show(LLScriptEdCore* editor_core)
194{
195 if (sInstance && sInstance->mEditorCore && sInstance->mEditorCore != editor_core)
196 {
197 sInstance->close();
198 delete sInstance;
199 }
200
201 if (!sInstance)
202 {
203 S32 left = 0;
204 S32 top = 0;
205 gFloaterView->getNewFloaterPosition(&left,&top);
206
207 // sInstance will be assigned in the constructor.
208 new LLFloaterScriptSearch("Script Search",LLRect(left,top,left + SCRIPT_SEARCH_WIDTH,top - SCRIPT_SEARCH_HEIGHT),editor_core);
209 }
210
211 sInstance->open();
212}
213
214LLFloaterScriptSearch::~LLFloaterScriptSearch()
215{
216 sInstance = NULL;
217}
218
219// static
220void LLFloaterScriptSearch::onBtnSearch(void *userdata)
221{
222 LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata;
223 self->handleBtnSearch();
224}
225
226void LLFloaterScriptSearch::handleBtnSearch()
227{
228 LLCheckBoxCtrl* caseChk = LLUICtrlFactory::getCheckBoxByName(this,"case_text");
229 mEditorCore->mEditor->selectNext(childGetText("search_text"), caseChk->get());
230}
231
232// static
233void LLFloaterScriptSearch::onBtnReplace(void *userdata)
234{
235 LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata;
236 self->handleBtnReplace();
237}
238
239void LLFloaterScriptSearch::handleBtnReplace()
240{
241 LLCheckBoxCtrl* caseChk = LLUICtrlFactory::getCheckBoxByName(this,"case_text");
242 mEditorCore->mEditor->replaceText(childGetText("search_text"), childGetText("replace_text"), caseChk->get());
243}
244
245// static
246void LLFloaterScriptSearch::onBtnReplaceAll(void *userdata)
247{
248 LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata;
249 self->handleBtnReplaceAll();
250}
251
252void LLFloaterScriptSearch::handleBtnReplaceAll()
253{
254 LLCheckBoxCtrl* caseChk = LLUICtrlFactory::getCheckBoxByName(this,"case_text");
255 mEditorCore->mEditor->replaceTextAll(childGetText("search_text"), childGetText("replace_text"), caseChk->get());
256}
257
258void LLFloaterScriptSearch::open()
259{
260 LLFloater::open();
261 childSetFocus("search_text", TRUE);
262}
263/// ---------------------------------------------------------------------------
264/// LLScriptEdCore
265/// ---------------------------------------------------------------------------
266
267LLScriptEdCore::LLScriptEdCore(
268 const std::string& name,
269 const LLRect& rect,
270 const std::string& sample,
271 const std::string& help,
272 const LLViewHandle& floater_handle,
273 void (*load_callback)(void*),
274 void (*save_callback)(void*, BOOL),
275 void* userdata,
276 S32 bottom_pad)
277 :
278 LLPanel( "name", rect ),
279 mSampleText(sample),
280 mHelpFile ( help ),
281 mEditor( NULL ),
282 mLoadCallback( load_callback ),
283 mSaveCallback( save_callback ),
284 mUserdata( userdata ),
285 mForceClose( FALSE )
286{
287 setFollowsAll();
288 setBorderVisible(FALSE);
289
290
291 gUICtrlFactory->buildPanel(this, "floater_script_ed_panel.xml");
292
293 mErrorList = LLUICtrlFactory::getScrollListByName(this, "lsl errors");
294
295 mFunctions = LLUICtrlFactory::getComboBoxByName(this, "Insert...");
296
297 childSetCommitCallback("Insert...", &LLScriptEdCore::onBtnInsertFunction, this);
298 mFunctions->setLabel("Insert...");
299
300 mEditor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "Script Editor");
301 mEditor->setReadOnlyBgColor(gColors.getColor( "ScriptBgReadOnlyColor" ) );
302 mEditor->setFollowsAll();
303 mEditor->setHandleEditKeysDirectly(TRUE);
304 mEditor->setEnabled(TRUE);
305 mEditor->setWordWrap(TRUE);
306
307 LLDynamicArray<const char*> funcs;
308 LLDynamicArray<const char*> tooltips;
309 for (S32 i = 0; i < gScriptLibrary.mNextNumber; i++)
310 {
311 // Make sure this isn't a god only function, or the agent is a god.
312 if (!gScriptLibrary.mFunctions[i]->mGodOnly || gAgent.isGodlike())
313 {
314 funcs.put(gScriptLibrary.mFunctions[i]->mName);
315 tooltips.put(gScriptLibrary.mFunctions[i]->mDesc);
316 }
317 }
318 LLColor3 color(0.5f, 0.0f, 0.15f);
319
320 mEditor->loadKeywords(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keywords.ini"), funcs, tooltips, color);
321
322
323 LLKeywordToken *token;
324 LLKeywords::word_token_map_t::iterator token_it;
325 for (token_it = mEditor->mKeywords.mWordTokenMap.begin(); token_it != mEditor->mKeywords.mWordTokenMap.end(); ++token_it)
326 {
327 token = token_it->second;
328 if (token->mColor == color)
329 mFunctions->add(wstring_to_utf8str(token->mToken));
330 }
331
332 for (token_it = mEditor->mKeywords.mWordTokenMap.begin(); token_it != mEditor->mKeywords.mWordTokenMap.end(); ++token_it)
333 {
334 token = token_it->second;
335 if (token->mColor != color)
336 mFunctions->add(wstring_to_utf8str(token->mToken));
337 }
338
339
340 childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this);
341 childSetAction("Save_btn", onBtnSave,this);
342
343 initMenu();
344
345
346 // Do the work that addTabPanel() normally does.
347 //LLRect tab_panel_rect( 0, mRect.getHeight(), mRect.getWidth(), 0 );
348 //tab_panel_rect.stretch( -LLPANEL_BORDER_WIDTH );
349 //mCodePanel->setFollowsAll();
350 //mCodePanel->translate( tab_panel_rect.mLeft - mCodePanel->getRect().mLeft, tab_panel_rect.mBottom - mCodePanel->getRect().mBottom);
351 //mCodePanel->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE );
352
353}
354
355LLScriptEdCore::~LLScriptEdCore()
356{
357 deleteBridges();
358
359 // If the search window is up for this editor, close it.
360 LLFloaterScriptSearch* script_search = LLFloaterScriptSearch::getInstance();
361 if (script_search && script_search->getEditorCore() == this)
362 {
363 script_search->close();
364 delete script_search;
365 }
366}
367
368void LLScriptEdCore::initMenu()
369{
370
371 LLMenuItemCallGL* menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "Save");
372 menuItem->setMenuCallback(onBtnSave, this);
373 menuItem->setEnabledCallback(hasChanged);
374
375 menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "Revert All Changes");
376 menuItem->setMenuCallback(onBtnUndoChanges, this);
377 menuItem->setEnabledCallback(hasChanged);
378
379 menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "Undo");
380 menuItem->setMenuCallback(onUndoMenu, this);
381 menuItem->setEnabledCallback(enableUndoMenu);
382
383 menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "Redo");
384 menuItem->setMenuCallback(onRedoMenu, this);
385 menuItem->setEnabledCallback(enableRedoMenu);
386
387 menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "Cut");
388 menuItem->setMenuCallback(onCutMenu, this);
389 menuItem->setEnabledCallback(enableCutMenu);
390
391 menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "Copy");
392 menuItem->setMenuCallback(onCopyMenu, this);
393 menuItem->setEnabledCallback(enableCopyMenu);
394
395 menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "Paste");
396 menuItem->setMenuCallback(onPasteMenu, this);
397 menuItem->setEnabledCallback(enablePasteMenu);
398
399 menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "Select All");
400 menuItem->setMenuCallback(onSelectAllMenu, this);
401 menuItem->setEnabledCallback(enableSelectAllMenu);
402
403 menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "Search / Replace...");
404 menuItem->setMenuCallback(onSearchMenu, this);
405 menuItem->setEnabledCallback(NULL);
406
407 menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "Help...");
408 menuItem->setMenuCallback(onBtnHelp, this);
409 menuItem->setEnabledCallback(NULL);
410
411}
412
413BOOL LLScriptEdCore::hasChanged(void* userdata)
414{
415 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
416 if (!self || !self->mEditor) return FALSE;
417
418 return !self->mEditor->isPristine();
419}
420
421void LLScriptEdCore::draw()
422{
423 BOOL script_changed = !mEditor->isPristine();
424 childSetEnabled("Save_btn", script_changed);
425
426 if( mEditor->hasFocus() )
427 {
428 S32 line = 0;
429 S32 column = 0;
430 mEditor->getCurrentLineAndColumn( &line, &column, FALSE ); // don't include wordwrap
431 char cursor_pos[STD_STRING_BUF_SIZE];
432 sprintf( cursor_pos, "Line %d, Column %d", line, column );
433 childSetText("line_col", cursor_pos);
434 }
435 else
436 {
437 childSetText("line_col", "");
438 }
439
440 LLPanel::draw();
441}
442
443BOOL LLScriptEdCore::canClose()
444{
445 if(mForceClose || mEditor->isPristine())
446 {
447 return TRUE;
448 }
449 else
450 {
451 // Bring up view-modal dialog: Save changes? Yes, No, Cancel
452 gViewerWindow->alertXml("SaveChanges", LLScriptEdCore::handleSaveChangesDialog, this);
453 return FALSE;
454 }
455}
456
457// static
458void LLScriptEdCore::handleSaveChangesDialog( S32 option, void* userdata )
459{
460 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
461 switch( option )
462 {
463 case 0: // "Yes"
464 // close after saving
465 LLScriptEdCore::doSave( self, TRUE );
466 break;
467
468 case 1: // "No"
469 self->mForceClose = TRUE;
470 // This will close immediately because mForceClose is true, so we won't
471 // infinite loop with these dialogs. JC
472 ((LLFloater*) self->getParent())->close();
473 break;
474
475 case 2: // "Cancel"
476 default:
477 // If we were quitting, we didn't really mean it.
478 app_abort_quit();
479 break;
480 }
481}
482
483// static
484void LLScriptEdCore::onHelpWebDialog(S32 option, void* userdata)
485{
486 LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
487
488 switch(option)
489 {
490 case 0:
491 load_url_local_file(corep->mHelpFile.c_str());
492 break;
493 default:
494 break;
495 }
496}
497
498// static
499void LLScriptEdCore::onBtnHelp(void* userdata)
500{
501 gViewerWindow->alertXml("WebLaunchLSLGuide",
502 onHelpWebDialog,
503 userdata);
504}
505
506// static
507void LLScriptEdCore::onBtnInsertSample(void* userdata)
508{
509 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
510
511 // Insert sample code
512 self->mEditor->selectAll();
513 self->mEditor->cut();
514 self->mEditor->insertText(self->mSampleText);
515}
516
517// static
518void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata)
519{
520 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
521
522 // Insert sample code
523 if(self->mEditor->getEnabled())
524 {
525 self->mEditor->insertText(self->mFunctions->getSimple());
526 }
527 self->mEditor->setFocus(TRUE);
528}
529
530// static
531void LLScriptEdCore::doSave( void* userdata, BOOL close_after_save )
532{
533 if( gViewerStats )
534 {
535 gViewerStats->incStat( LLViewerStats::ST_LSL_SAVE_COUNT );
536 }
537
538 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
539
540 if( self->mSaveCallback )
541 {
542 self->mSaveCallback( self->mUserdata, close_after_save );
543 }
544}
545
546// static
547void LLScriptEdCore::onBtnSave(void* data)
548{
549 // do the save, but don't close afterwards
550 doSave(data, FALSE);
551}
552
553// static
554void LLScriptEdCore::onBtnUndoChanges( void* userdata )
555{
556 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
557 if( !self->mEditor->tryToRevertToPristineState() )
558 {
559 gViewerWindow->alertXml("ScriptCannotUndo",
560 LLScriptEdCore::handleReloadFromServerDialog, self);
561 }
562}
563
564void LLScriptEdCore::onSearchMenu(void* userdata)
565{
566 LLScriptEdCore* sec = (LLScriptEdCore*)userdata;
567 LLFloaterScriptSearch::show(sec);
568}
569
570// static
571void LLScriptEdCore::onUndoMenu(void* userdata)
572{
573 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
574 if (!self || !self->mEditor) return;
575 self->mEditor->undo();
576}
577
578// static
579void LLScriptEdCore::onRedoMenu(void* userdata)
580{
581 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
582 if (!self || !self->mEditor) return;
583 self->mEditor->redo();
584}
585
586// static
587void LLScriptEdCore::onCutMenu(void* userdata)
588{
589 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
590 if (!self || !self->mEditor) return;
591 self->mEditor->cut();
592}
593
594// static
595void LLScriptEdCore::onCopyMenu(void* userdata)
596{
597 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
598 if (!self || !self->mEditor) return;
599 self->mEditor->copy();
600}
601
602// static
603void LLScriptEdCore::onPasteMenu(void* userdata)
604{
605 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
606 if (!self || !self->mEditor) return;
607 self->mEditor->paste();
608}
609
610// static
611void LLScriptEdCore::onSelectAllMenu(void* userdata)
612{
613 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
614 if (!self || !self->mEditor) return;
615 self->mEditor->selectAll();
616}
617
618// static
619void LLScriptEdCore::onDeselectMenu(void* userdata)
620{
621 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
622 if (!self || !self->mEditor) return;
623 self->mEditor->deselect();
624}
625
626// static
627BOOL LLScriptEdCore::enableUndoMenu(void* userdata)
628{
629 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
630 if (!self || !self->mEditor) return FALSE;
631 return self->mEditor->canUndo();
632}
633
634// static
635BOOL LLScriptEdCore::enableRedoMenu(void* userdata)
636{
637 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
638 if (!self || !self->mEditor) return FALSE;
639 return self->mEditor->canRedo();
640}
641
642// static
643BOOL LLScriptEdCore::enableCutMenu(void* userdata)
644{
645 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
646 if (!self || !self->mEditor) return FALSE;
647 return self->mEditor->canCut();
648}
649
650// static
651BOOL LLScriptEdCore::enableCopyMenu(void* userdata)
652{
653 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
654 if (!self || !self->mEditor) return FALSE;
655 return self->mEditor->canCopy();
656}
657
658// static
659BOOL LLScriptEdCore::enablePasteMenu(void* userdata)
660{
661 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
662 if (!self || !self->mEditor) return FALSE;
663 return self->mEditor->canPaste();
664}
665
666// static
667BOOL LLScriptEdCore::enableSelectAllMenu(void* userdata)
668{
669 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
670 if (!self || !self->mEditor) return FALSE;
671 return self->mEditor->canSelectAll();
672}
673
674// static
675BOOL LLScriptEdCore::enableDeselectMenu(void* userdata)
676{
677 LLScriptEdCore* self = (LLScriptEdCore*)userdata;
678 if (!self || !self->mEditor) return FALSE;
679 return self->mEditor->canDeselect();
680}
681
682// static
683void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data)
684{
685 LLScriptEdCore* self = (LLScriptEdCore*)user_data;
686 LLScrollListItem* item = self->mErrorList->getFirstSelected();
687 if(item)
688 {
689 // *FIX: This fucked up little hack is here because we don't
690 // have a grep library. This is very brittle code.
691 S32 row = 0;
692 S32 column = 0;
693 const LLScrollListCell* cell = item->getColumn(0);
694 LLString line(cell->getText());
695 line.erase(0, 1);
696 LLString::replaceChar(line, ',',' ');
697 LLString::replaceChar(line, ')',' ');
698 sscanf(line.c_str(), "%d %d", &row, &column);
699 //llinfos << "LLScriptEdCore::onErrorList() - " << row << ", "
700 //<< column << llendl;
701 self->mEditor->setCursor(row, column);
702 self->mEditor->setFocus(TRUE);
703 }
704}
705
706// static
707void LLScriptEdCore::handleReloadFromServerDialog( S32 option, void* userdata )
708{
709 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
710 switch( option )
711 {
712 case 0: // "Yes"
713 if( self->mLoadCallback )
714 {
715 self->mEditor->setText( "Loading..." );
716 self->mLoadCallback( self->mUserdata );
717 }
718 break;
719
720 case 1: // "No"
721 break;
722
723 default:
724 llassert(0);
725 break;
726 }
727}
728
729void LLScriptEdCore::selectFirstError()
730{
731 // Select the first item;
732 mErrorList->selectFirstItem();
733 onErrorList(mErrorList, this);
734}
735
736
737struct LLEntryAndEdCore
738{
739 LLScriptEdCore* mCore;
740 LLEntryAndEdCore(LLScriptEdCore* core) :
741 mCore(core)
742 {}
743};
744
745void LLScriptEdCore::deleteBridges()
746{
747 S32 count = mBridges.count();
748 LLEntryAndEdCore* eandc;
749 for(S32 i = 0; i < count; i++)
750 {
751 eandc = mBridges.get(i);
752 delete eandc;
753 mBridges[i] = NULL;
754 }
755 mBridges.reset();
756}
757
758// virtual
759BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
760{
761 if(getVisible() && getEnabled())
762 {
763 if(('S' == key) && (MASK_CONTROL == (mask & MASK_CONTROL)))
764 {
765 if(mSaveCallback)
766 {
767 // don't close after saving
768 mSaveCallback(mUserdata, FALSE);
769 }
770
771 return TRUE;
772 }
773 }
774 return FALSE;
775}
776
777/// ---------------------------------------------------------------------------
778/// LLPreviewLSL
779/// ---------------------------------------------------------------------------
780
781struct LLScriptSaveInfo
782{
783 LLUUID mItemUUID;
784 LLString mDescription;
785 LLTransactionID mTransactionID;
786
787 LLScriptSaveInfo(const LLUUID& uuid, const LLString& desc, LLTransactionID tid) :
788 mItemUUID(uuid), mDescription(desc), mTransactionID(tid) {}
789};
790
791
792
793//static
794void* LLPreviewLSL::createScriptEdPanel(void* userdata)
795{
796
797 LLPreviewLSL *self = (LLPreviewLSL*)userdata;
798
799 self->mScriptEd = new LLScriptEdCore("script panel",
800 LLRect(),
801 HELLO_LSL,
802 HELP_LSL,
803 self->mViewHandle,
804 LLPreviewLSL::onLoad,
805 LLPreviewLSL::onSave,
806 self,
807 0);
808
809 return self->mScriptEd;
810}
811
812
813LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect,
814 const std::string& title, const LLUUID& item_id )
815: LLPreview( name, rect, title, item_id, LLUUID::null, TRUE,
816 SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT ),
817 mPendingUploads(0)
818{
819
820 LLRect curRect = rect;
821
822
823 LLCallbackMap::map_t factory_map;
824 factory_map["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this);
825
826
827 gUICtrlFactory->buildFloater(this,"floater_script_preview.xml", &factory_map);
828
829 moveResizeHandleToFront();
830
831
832 LLInventoryItem* item = getItem();
833
834 childSetCommitCallback("desc", LLPreview::onText, this);
835 childSetText("desc", item->getDescription());
836 childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
837
838 LLMultiFloater* hostp = getHost();
839
840 if (!sHostp && !hostp && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
841 {
842 loadAsset();
843 }
844
845 setTitle(title);
846
847 if (!getHost())
848 {
849 reshape(curRect.getWidth(), curRect.getHeight(), TRUE);
850 setRect(curRect);
851 }
852}
853
854
855void LLPreviewLSL::loadAsset()
856{
857 // *HACK: we poke into inventory to see if it's there, and if so,
858 // then it might be part of the inventory library. If it's in the
859 // library, then you can see the script, but not modify it.
860 LLInventoryItem* item = gInventory.getItem(mItemUUID);
861 BOOL is_library = item
862 && !gInventory.isObjectDescendentOf(mItemUUID,
863 gAgent.getInventoryRootID());
864 if(!item)
865 {
866 // do the more generic search.
867 getItem();
868 }
869 if(item)
870 {
871 BOOL is_copyable = gAgent.allowOperation(PERM_COPY,
872 item->getPermissions(), GP_OBJECT_MANIPULATE);
873 BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY,
874 item->getPermissions(), GP_OBJECT_MANIPULATE);
875 if (gAgent.isGodlike() || (is_copyable && (is_modifiable || is_library)))
876 {
877 LLUUID* new_uuid = new LLUUID(mItemUUID);
878 gAssetStorage->getInvItemAsset(LLHost::invalid,
879 gAgent.getID(),
880 gAgent.getSessionID(),
881 item->getPermissions().getOwner(),
882 LLUUID::null,
883 item->getUUID(),
884 item->getAssetUUID(),
885 item->getType(),
886 &LLPreviewLSL::onLoadComplete,
887 (void*)new_uuid,
888 TRUE);
889 mAssetStatus = PREVIEW_ASSET_LOADING;
890 }
891 else
892 {
893 mScriptEd->mEditor->setText("You are not allowed to view this script.");
894 mScriptEd->mEditor->makePristine();
895 mScriptEd->mEditor->setEnabled(FALSE);
896 mScriptEd->mFunctions->setEnabled(FALSE);
897 mAssetStatus = PREVIEW_ASSET_LOADED;
898 }
899 childSetVisible("lock", !is_modifiable);
900 mScriptEd->childSetEnabled("Insert...", is_modifiable);
901 }
902 else
903 {
904 mScriptEd->mEditor->setText(HELLO_LSL);
905 mAssetStatus = PREVIEW_ASSET_LOADED;
906 }
907}
908
909
910BOOL LLPreviewLSL::canClose()
911{
912 return mScriptEd->canClose();
913}
914
915//override the llpreview open which attempts to load asset, load after xml ui made
916void LLPreviewLSL::open()
917{
918 LLFloater::open();
919}
920
921// static
922void LLPreviewLSL::onLoad(void* userdata)
923{
924 LLPreviewLSL* self = (LLPreviewLSL*)userdata;
925 self->loadAsset();
926}
927
928// static
929void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save)
930{
931 LLPreviewLSL* self = (LLPreviewLSL*)userdata;
932 self->mCloseAfterSave = close_after_save;
933 self->saveIfNeeded();
934}
935
936
937// Save needs to compile the text in the buffer. If the compile
938// succeeds, then save both assets out to the database. If the compile
939// fails, go ahead and save the text anyway so that the user doesn't
940// get too fucked.
941void LLPreviewLSL::saveIfNeeded()
942{
943 // llinfos << "LLPreviewLSL::save()" << llendl;
944 if(!mScriptEd->mEditor->isPristine())
945 {
946 mPendingUploads = 0;
947 mScriptEd->mErrorList->deleteAllItems();
948 mScriptEd->mEditor->makePristine();
949
950 // We need to update the asset information
951 LLTransactionID tid;
952 LLAssetID uuid;
953 tid.generate();
954 uuid = tid.makeAssetID(gAgent.getSecureSessionID());
955 char uuid_string[UUID_STR_LENGTH];
956 uuid.toString(uuid_string);
957 char filename[LL_MAX_PATH];
958 sprintf(filename, "%s.lsl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str());
959 FILE* fp = LLFile::fopen(filename, "wb");
960 if(!fp)
961 {
962 llwarns << "Unable to write to " << filename << llendl;
963 LLScrollListItem* item = new LLScrollListItem();
964 item->addColumn("Error writing to local file. Is your hard drive full?", LLFontGL::sSansSerifSmall);
965 mScriptEd->mErrorList->addItem(item);
966 return;
967 }
968
969 LLString utf8text = mScriptEd->mEditor->getText();
970 //fprintf(fp, "%s|%s\n", LLAssetType::lookup(LLAssetType::AT_LSL_TEXT),
971 //uuid_string);
972 //fprintf(fp,"{\n%s}\n", text.c_str());
973 fputs(utf8text.c_str(), fp);
974 fclose(fp);
975 fp = NULL;
976
977 // also write it out to the vfs for upload
978 LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_TEXT, LLVFile::APPEND);
979 S32 size = utf8text.length() + 1;
980
981 file.setMaxSize(size);
982 file.write((U8*)utf8text.c_str(), size);
983
984 LLInventoryItem *inv_item = getItem();
985
986 // save it out to database
987 if(gAssetStorage && inv_item)
988 {
989 getWindow()->incBusyCount();
990 mPendingUploads++;
991 LLScriptSaveInfo* info = NULL;
992
993 LLLineEditor* descEditor = LLUICtrlFactory::getLineEditorByName(this, "desc");
994
995 info = new LLScriptSaveInfo(mItemUUID,
996 descEditor->getText(),
997 tid);
998 gAssetStorage->storeAssetData(tid, LLAssetType::AT_LSL_TEXT, &LLPreviewLSL::onSaveComplete, info);
999 }
1000
1001 char dst_filename[LL_MAX_PATH];
1002 sprintf(dst_filename, "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str());
1003 char err_filename[LL_MAX_PATH];
1004 sprintf(err_filename, "%s.out", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str());
1005 LLScrollListItem* item = NULL;
1006 const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA);
1007 if(!lscript_compile(filename, dst_filename, err_filename, gAgent.isGodlike()))
1008 {
1009 llinfos << "Compile failed!" << llendl;
1010 //char command[256];
1011 //sprintf(command, "type %s\n", err_filename);
1012 //system(command);
1013
1014 // load the error file into the error scrolllist
1015 if(NULL != (fp = LLFile::fopen(err_filename, "r")))
1016 {
1017 char buffer[MAX_STRING];
1018 LLString line;
1019 while(!feof(fp))
1020 {
1021
1022 fgets(buffer, MAX_STRING, fp);
1023 if(feof(fp))
1024 {
1025 break;
1026 }
1027 else if(!buffer)
1028 {
1029 continue;
1030 }
1031 else
1032 {
1033 line.assign(buffer);
1034 LLString::stripNonprintable(line);
1035 item = new LLScrollListItem();
1036 item->addColumn(line, err_font);
1037 mScriptEd->mErrorList->addItem(item);
1038 }
1039 }
1040 fclose(fp);
1041 mScriptEd->selectFirstError();
1042 }
1043 }
1044 else
1045 {
1046 llinfos << "Compile worked!" << llendl;
1047 if(gAssetStorage)
1048 {
1049 // move the compiled file into the vfs for transport
1050 FILE* fp = LLFile::fopen(dst_filename, "rb");
1051 LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_BYTECODE, LLVFile::APPEND);
1052
1053 fseek(fp, 0, SEEK_END);
1054 S32 size = ftell(fp);
1055 fseek(fp, 0, SEEK_SET);
1056
1057 file.setMaxSize(size);
1058
1059 const S32 buf_size = 65536;
1060 U8 copy_buf[buf_size];
1061 while ((size = fread(copy_buf, 1, buf_size, fp)))
1062 {
1063 file.write(copy_buf, size);
1064 }
1065 fclose(fp);
1066 fp = NULL;
1067 getWindow()->incBusyCount();
1068 mPendingUploads++;
1069 LLUUID* this_uuid = new LLUUID(mItemUUID);
1070 gAssetStorage->storeAssetData(tid,
1071 LLAssetType::AT_LSL_BYTECODE,
1072 &LLPreviewLSL::onSaveBytecodeComplete,
1073 (void**)this_uuid);
1074 }
1075 }
1076
1077 // get rid of any temp files left lying around
1078 LLFile::remove(filename);
1079 LLFile::remove(err_filename);
1080 LLFile::remove(dst_filename);
1081 }
1082}
1083
1084
1085// static
1086void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status) // StoreAssetData callback (fixed)
1087{
1088 LLScriptSaveInfo* info = reinterpret_cast<LLScriptSaveInfo*>(user_data);
1089 if(0 == status)
1090 {
1091 if (info)
1092 {
1093 LLViewerInventoryItem* item;
1094 item = (LLViewerInventoryItem*)gInventory.getItem(info->mItemUUID);
1095 if(item)
1096 {
1097 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
1098 new_item->setAssetUUID(asset_uuid);
1099 new_item->setTransactionID(info->mTransactionID);
1100 new_item->updateServer(FALSE);
1101 gInventory.updateItem(new_item);
1102 gInventory.notifyObservers();
1103 }
1104 else
1105 {
1106 llwarns << "Inventory item for script " << info->mItemUUID
1107 << " is no longer in agent inventory." << llendl
1108 }
1109
1110 // Find our window and close it if requested.
1111 LLPreviewLSL* self = (LLPreviewLSL*)LLPreview::find(info->mItemUUID);
1112 if (self)
1113 {
1114 getWindow()->decBusyCount();
1115 self->mPendingUploads--;
1116 if (self->mPendingUploads <= 0
1117 && self->mCloseAfterSave)
1118 {
1119 self->close();
1120 }
1121 }
1122 }
1123 }
1124 else
1125 {
1126 llwarns << "Problem saving script: " << status << llendl;
1127 LLStringBase<char>::format_map_t args;
1128 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
1129 gViewerWindow->alertXml("SaveScriptFailReason", args);
1130 }
1131 delete info;
1132}
1133
1134// static
1135void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status) // StoreAssetData callback (fixed)
1136{
1137 LLUUID* instance_uuid = (LLUUID*)user_data;
1138 LLPreviewLSL* self = NULL;
1139 if(instance_uuid)
1140 {
1141 self = LLPreviewLSL::getInstance(*instance_uuid);
1142 }
1143 if (0 == status)
1144 {
1145 if (self)
1146 {
1147 LLScrollListItem* item = new LLScrollListItem();
1148 item->addColumn("Compile successful!", LLFontGL::sSansSerifSmall);
1149 self->mScriptEd->mErrorList->addItem(item);
1150
1151 // Find our window and close it if requested.
1152 self->getWindow()->decBusyCount();
1153 self->mPendingUploads--;
1154 if (self->mPendingUploads <= 0
1155 && self->mCloseAfterSave)
1156 {
1157 self->close();
1158 }
1159 }
1160 }
1161 else
1162 {
1163 llwarns << "Problem saving LSL Bytecode (Preview)" << llendl;
1164 LLStringBase<char>::format_map_t args;
1165 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
1166 gViewerWindow->alertXml("SaveBytecodeFailReason", args);
1167 }
1168 delete instance_uuid;
1169}
1170
1171// static
1172void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAssetType::EType type,
1173 void* user_data, S32 status)
1174{
1175 lldebugs << "LLPreviewLSL::onLoadComplete: got uuid " << asset_uuid
1176 << llendl;
1177 LLUUID* item_uuid = (LLUUID*)user_data;
1178 LLPreviewLSL* preview = LLPreviewLSL::getInstance(*item_uuid);
1179 if( preview )
1180 {
1181 if(0 == status)
1182 {
1183 LLVFile file(vfs, asset_uuid, type);
1184 S32 file_length = file.getSize();
1185
1186 char* buffer = new char[file_length+1];
1187 file.read((U8*)buffer, file_length);
1188
1189 // put a EOS at the end
1190 buffer[file_length] = 0;
1191 preview->mScriptEd->mEditor->setText(buffer);
1192 preview->mScriptEd->mEditor->makePristine();
1193 delete [] buffer;
1194 LLInventoryItem* item = gInventory.getItem(*item_uuid);
1195 BOOL is_modifiable = FALSE;
1196 if(item
1197 && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
1198 GP_OBJECT_MANIPULATE))
1199 {
1200 is_modifiable = TRUE;
1201 }
1202 preview->mScriptEd->mEditor->setEnabled(is_modifiable);
1203 preview->mAssetStatus = PREVIEW_ASSET_LOADED;
1204 }
1205 else
1206 {
1207 if( gViewerStats )
1208 {
1209 gViewerStats->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
1210 }
1211
1212 if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
1213 LL_ERR_FILE_EMPTY == status)
1214 {
1215 LLNotifyBox::showXml("ScriptMissing");
1216 }
1217 else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
1218 {
1219 LLNotifyBox::showXml("ScriptNoPermissions");
1220 }
1221 else
1222 {
1223 LLNotifyBox::showXml("UnableToLoadScript");
1224 }
1225
1226 preview->mAssetStatus = PREVIEW_ASSET_ERROR;
1227 llwarns << "Problem loading script: " << status << llendl;
1228 }
1229 }
1230 delete item_uuid;
1231}
1232
1233// static
1234LLPreviewLSL* LLPreviewLSL::getInstance( const LLUUID& item_uuid )
1235{
1236 LLPreview* instance = NULL;
1237 preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
1238 if(found_it != LLPreview::sInstances.end())
1239 {
1240 instance = found_it->second;
1241 }
1242 return (LLPreviewLSL*)instance;
1243}
1244
1245void LLPreviewLSL::reshape(S32 width, S32 height, BOOL called_from_parent)
1246{
1247 LLPreview::reshape( width, height, called_from_parent );
1248
1249 if( !isMinimized() )
1250 {
1251 // So that next time you open a script it will have the same height and width
1252 // (although not the same position).
1253 gSavedSettings.setRect("PreviewScriptRect", mRect);
1254 }
1255}
1256
1257/// ---------------------------------------------------------------------------
1258/// LLLiveLSLEditor
1259/// ---------------------------------------------------------------------------
1260
1261LLMap<LLUUID, LLLiveLSLEditor*> LLLiveLSLEditor::sInstances;
1262
1263
1264
1265//static
1266void* LLLiveLSLEditor::createScriptEdPanel(void* userdata)
1267{
1268
1269 LLLiveLSLEditor *self = (LLLiveLSLEditor*)userdata;
1270
1271 self->mScriptEd = new LLScriptEdCore("script ed panel",
1272 LLRect(),
1273 HELLO_LSL,
1274 HELP_LSL,
1275 self->mViewHandle,
1276 &LLLiveLSLEditor::onLoad,
1277 &LLLiveLSLEditor::onSave,
1278 self,
1279 0);
1280
1281 return self->mScriptEd;
1282}
1283
1284
1285LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name,
1286 const LLRect& rect,
1287 const std::string& title,
1288 const LLUUID& object_id,
1289 const LLUUID& item_id) :
1290 LLFloater(name, rect, title, TRUE, SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT),
1291 mObjectID(object_id),
1292 mItemID(item_id),
1293 mScriptEd(NULL),
1294 mAskedForRunningInfo(FALSE),
1295 mHaveRunningInfo(FALSE),
1296 mCloseAfterSave(FALSE),
1297 mPendingUploads(0)
1298{
1299
1300
1301 BOOL is_new = FALSE;
1302 if(mItemID.isNull())
1303 {
1304 mItemID.generate();
1305 is_new = TRUE;
1306 }
1307
1308
1309 LLLiveLSLEditor::sInstances.addData(mItemID ^ mObjectID, this);
1310
1311
1312
1313 LLCallbackMap::map_t factory_map;
1314 factory_map["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this);
1315
1316 moveResizeHandleToFront();
1317
1318 gUICtrlFactory->buildFloater(this,"floater_live_lsleditor.xml", &factory_map);
1319
1320
1321 childSetCommitCallback("running", LLLiveLSLEditor::onRunningCheckboxClicked, this);
1322 childSetEnabled("running", FALSE);
1323
1324 childSetAction("Reset",&LLLiveLSLEditor::onReset,this);
1325 childSetEnabled("Reset", TRUE);
1326
1327
1328 mScriptEd->mEditor->makePristine();
1329 loadAsset(is_new);
1330 mScriptEd->mEditor->setFocus(TRUE);
1331
1332
1333 if (!getHost())
1334 {
1335 LLRect curRect = getRect();
1336 translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
1337 }
1338
1339
1340 setTitle(title);
1341
1342}
1343
1344LLLiveLSLEditor::~LLLiveLSLEditor()
1345{
1346 LLLiveLSLEditor::sInstances.removeData(mItemID ^ mObjectID);
1347}
1348
1349
1350void LLLiveLSLEditor::loadAsset(BOOL is_new)
1351{
1352 //llinfos << "LLLiveLSLEditor::loadAsset()" << llendl;
1353 if(!is_new)
1354 {
1355 LLViewerObject* object = gObjectList.findObject(mObjectID);
1356 if(object)
1357 {
1358 // HACK! we "know" that mItemID refers to a LLViewerInventoryItem...
1359 LLViewerInventoryItem* item = (LLViewerInventoryItem*)object->getInventoryObject(mItemID);
1360 if(item
1361 && (gAgent.allowOperation(PERM_COPY, item->getPermissions(),
1362 GP_OBJECT_MANIPULATE)
1363 || gAgent.isGodlike()))
1364 {
1365 mItem = new LLViewerInventoryItem(item);
1366 //llinfos << "asset id " << mItem->getAssetUUID() << llendl;
1367 }
1368
1369 if(!gAgent.isGodlike()
1370 && (item
1371 && (!gAgent.allowOperation(PERM_COPY, item->getPermissions(),
1372 GP_OBJECT_MANIPULATE)
1373 || !gAgent.allowOperation(PERM_MODIFY,
1374 item->getPermissions(), GP_OBJECT_MANIPULATE))))
1375
1376 {
1377 mScriptEd->mEditor->setText("You are not allowed to view this script.");
1378 mScriptEd->mEditor->makePristine();
1379 mScriptEd->mEditor->setEnabled(FALSE);
1380 }
1381 else if(mItem.notNull())
1382 {
1383 // request the text from the object
1384 LLUUID* user_data = new LLUUID(mItemID ^ mObjectID);
1385 gAssetStorage->getInvItemAsset(object->getRegion()->getHost(),
1386 gAgent.getID(),
1387 gAgent.getSessionID(),
1388 item->getPermissions().getOwner(),
1389 object->getID(),
1390 item->getUUID(),
1391 item->getAssetUUID(),
1392 item->getType(),
1393 &LLLiveLSLEditor::onLoadComplete,
1394 (void*)user_data,
1395 TRUE);
1396 LLMessageSystem* msg = gMessageSystem;
1397 msg->newMessageFast(_PREHASH_GetScriptRunning);
1398 msg->nextBlockFast(_PREHASH_Script);
1399 msg->addUUIDFast(_PREHASH_ObjectID, mObjectID);
1400 msg->addUUIDFast(_PREHASH_ItemID, mItemID);
1401 msg->sendReliable(object->getRegion()->getHost());
1402 mAskedForRunningInfo = TRUE;
1403 }
1404 else
1405 {
1406 mScriptEd->mEditor->setText("");
1407 mScriptEd->mEditor->makePristine();
1408 }
1409
1410 if(item
1411 && !gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
1412 GP_OBJECT_MANIPULATE))
1413 {
1414 mScriptEd->mEditor->setEnabled(FALSE);
1415 }
1416 // This is commented out, because we don't completely
1417 // handle script exports yet.
1418 /*
1419 // request the exports from the object
1420 gMessageSystem->newMessage("GetScriptExports");
1421 gMessageSystem->nextBlock("ScriptBlock");
1422 gMessageSystem->addUUID("AgentID", gAgent.getID());
1423 U32 local_id = object->getLocalID();
1424 gMessageSystem->addData("LocalID", &local_id);
1425 gMessageSystem->addUUID("ItemID", mItemID);
1426 LLHost host(object->getRegion()->getIP(),
1427 object->getRegion()->getPort());
1428 gMessageSystem->sendReliable(host);
1429 */
1430 }
1431 }
1432 else
1433 {
1434 mScriptEd->mEditor->setText(HELLO_LSL);
1435 //mScriptEd->mEditor->setText("");
1436 //mScriptEd->mEditor->makePristine();
1437 LLPermissions perm;
1438 perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, gAgent.getGroupID());
1439 perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, PERM_MOVE | PERM_TRANSFER);
1440 mItem = new LLViewerInventoryItem(mItemID,
1441 mObjectID,
1442 perm,
1443 LLUUID::null,
1444 LLAssetType::AT_LSL_TEXT,
1445 LLInventoryType::IT_LSL,
1446 DEFAULT_SCRIPT_NAME,
1447 DEFAULT_SCRIPT_DESC,
1448 LLSaleInfo::DEFAULT,
1449 LLInventoryItem::II_FLAGS_NONE,
1450 time_corrected());
1451 }
1452}
1453
1454// static
1455void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
1456 LLAssetType::EType type,
1457 void* user_data, S32 status)
1458{
1459 lldebugs << "LLLiveLSLEditor::onLoadComplete: got uuid " << asset_id
1460 << llendl;
1461 LLLiveLSLEditor* instance = NULL;
1462 LLUUID* xored_id = (LLUUID*)user_data;
1463
1464 if( LLLiveLSLEditor::sInstances.checkData(*xored_id) )
1465 {
1466 if( LL_ERR_NOERR == status )
1467 {
1468 instance = LLLiveLSLEditor::sInstances[*xored_id];
1469 instance->loadScriptText(vfs, asset_id, type);
1470 }
1471 else
1472 {
1473 if( gViewerStats )
1474 {
1475 gViewerStats->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
1476 }
1477
1478 if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
1479 LL_ERR_FILE_EMPTY == status)
1480 {
1481 LLNotifyBox::showXml("ScriptMissing");
1482 }
1483 else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
1484 {
1485 LLNotifyBox::showXml("ScriptNoPermissions");
1486 }
1487 else
1488 {
1489 LLNotifyBox::showXml("UnableToLoadScript");
1490 }
1491 }
1492 }
1493
1494 delete xored_id;
1495}
1496
1497void LLLiveLSLEditor::loadScriptText(const char* filename)
1498{
1499 FILE* file = LLFile::fopen(filename, "rb");
1500 if(file)
1501 {
1502 // read in the whole file
1503 fseek(file, 0L, SEEK_END);
1504 S32 file_length = ftell(file);
1505 fseek(file, 0L, SEEK_SET);
1506 char* buffer = new char[file_length+1];
1507 fread(buffer, file_length, 1, file);
1508 fclose(file);
1509 buffer[file_length] = 0;
1510 mScriptEd->mEditor->setText(buffer);
1511 mScriptEd->mEditor->makePristine();
1512 delete[] buffer;
1513 }
1514 else
1515 {
1516 llwarns << "Error opening " << filename << llendl;
1517 }
1518}
1519
1520void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
1521{
1522 LLVFile file(vfs, uuid, type);
1523 S32 file_length = file.getSize();
1524 char *buffer = new char[file_length + 1];
1525 file.read((U8*)buffer, file_length);
1526
1527 if (file.getLastBytesRead() != file_length ||
1528 file_length <= 0)
1529 {
1530 llwarns << "Error reading " << uuid << ":" << type << llendl;
1531 }
1532
1533 buffer[file_length] = '\0';
1534
1535 mScriptEd->mEditor->setText(buffer);
1536 mScriptEd->mEditor->makePristine();
1537 delete[] buffer;
1538
1539}
1540
1541
1542void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata )
1543{
1544 LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata;
1545 LLViewerObject* object = gObjectList.findObject( self->mObjectID );
1546 LLCheckBoxCtrl* runningCheckbox = LLUICtrlFactory::getCheckBoxByName(self, "running");
1547 BOOL running = runningCheckbox->get();
1548 //self->mRunningCheckbox->get();
1549 if( object )
1550 {
1551 LLMessageSystem* msg = gMessageSystem;
1552 msg->newMessageFast(_PREHASH_SetScriptRunning);
1553 msg->nextBlockFast(_PREHASH_AgentData);
1554 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
1555 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
1556 msg->nextBlockFast(_PREHASH_Script);
1557 msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectID);
1558 msg->addUUIDFast(_PREHASH_ItemID, self->mItemID);
1559 msg->addBOOLFast(_PREHASH_Running, running);
1560 msg->sendReliable(object->getRegion()->getHost());
1561 }
1562 else
1563 {
1564 runningCheckbox->set(!running);
1565 gViewerWindow->alertXml("CouldNotStartStopScript");
1566 }
1567}
1568
1569void LLLiveLSLEditor::onReset(void *userdata)
1570{
1571 LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata;
1572
1573 LLViewerObject* object = gObjectList.findObject( self->mObjectID );
1574 if(object)
1575 {
1576 LLMessageSystem* msg = gMessageSystem;
1577 msg->newMessageFast(_PREHASH_ScriptReset);
1578 msg->nextBlockFast(_PREHASH_AgentData);
1579 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
1580 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
1581 msg->nextBlockFast(_PREHASH_Script);
1582 msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectID);
1583 msg->addUUIDFast(_PREHASH_ItemID, self->mItemID);
1584 msg->sendReliable(object->getRegion()->getHost());
1585 }
1586 else
1587 {
1588 gViewerWindow->alertXml("CouldNotStartStopScript");
1589 }
1590}
1591
1592void LLLiveLSLEditor::draw()
1593{
1594 if(getVisible())
1595 {
1596 LLViewerObject* object = gObjectList.findObject(mObjectID);
1597 LLCheckBoxCtrl* runningCheckbox = LLUICtrlFactory::getCheckBoxByName(this, "running");
1598 if(object && mAskedForRunningInfo && mHaveRunningInfo)
1599 {
1600 if(object->permAnyOwner())
1601 {
1602 runningCheckbox->setLabel(ENABLED_RUNNING_CHECKBOX_LABEL);
1603 runningCheckbox->setEnabled(TRUE);
1604 }
1605 else
1606 {
1607 runningCheckbox->setLabel(DISABLED_RUNNING_CHECKBOX_LABEL);
1608 runningCheckbox->setEnabled(FALSE);
1609 // *FIX: Set it to false so that the ui is correct for
1610 // a box that is released to public. It could be
1611 // incorrect after a release/claim cycle, but will be
1612 // correct after clicking on it.
1613 runningCheckbox->set(FALSE);
1614 }
1615 }
1616 else if(!object)
1617 {
1618 // HACK: Display this information in the title bar.
1619 // Really ought to put in main window.
1620 setTitle("Script (object out of range)");
1621 runningCheckbox->setEnabled(FALSE);
1622 // object may have fallen out of range.
1623 mHaveRunningInfo = FALSE;
1624 }
1625 LLFloater::draw();
1626 }
1627}
1628
1629struct LLLiveLSLSaveData
1630{
1631 LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, BOOL active);
1632 LLUUID mObjectID;
1633 LLPointer<LLViewerInventoryItem> mItem;
1634 BOOL mActive;
1635};
1636
1637LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
1638 const LLViewerInventoryItem* item,
1639 BOOL active) :
1640 mObjectID(id),
1641 mActive(active)
1642{
1643 llassert(item);
1644 mItem = new LLViewerInventoryItem(item);
1645}
1646
1647void LLLiveLSLEditor::saveIfNeeded()
1648{
1649 llinfos << "LLLiveLSLEditor::saveIfNeeded()" << llendl;
1650 LLViewerObject* object = gObjectList.findObject(mObjectID);
1651 if(!object)
1652 {
1653 gViewerWindow->alertXml("SaveScriptFailObjectNotFound");
1654 return;
1655 }
1656
1657 // get the latest info about it. We used to be losing the script
1658 // name on save, because the viewer object version of the item,
1659 // and the editor version would get out of synch. Here's a good
1660 // place to synch them back up.
1661 // HACK! we "know" that mItemID refers to a LLInventoryItem...
1662 LLInventoryItem* inv_item = (LLInventoryItem*)object->getInventoryObject(mItemID);
1663 if(inv_item)
1664 {
1665 mItem->copy(inv_item);
1666 }
1667
1668 // Don't need to save if we're pristine
1669 if(mScriptEd->mEditor->isPristine())
1670 {
1671 return;
1672 }
1673
1674 mPendingUploads = 0;
1675
1676 // save the script
1677 mScriptEd->mEditor->makePristine();
1678 mScriptEd->mErrorList->deleteAllItems();
1679
1680 // set up the save on the local machine.
1681 mScriptEd->mEditor->makePristine();
1682 LLTransactionID tid;
1683 LLAssetID uuid;
1684 tid.generate();
1685 uuid = tid.makeAssetID(gAgent.getSecureSessionID());
1686 mItem->setAssetUUID(uuid);
1687 mItem->setTransactionID(tid);
1688
1689 // write out the data, and store it in the asset database
1690 char uuid_string[UUID_STR_LENGTH];
1691 uuid.toString(uuid_string);
1692 char filename[LL_MAX_PATH];
1693 sprintf(filename, "%s.lsl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str());
1694 FILE* fp = LLFile::fopen(filename, "wb");
1695 if(!fp)
1696 {
1697 llwarns << "Unable to write to " << filename << llendl;
1698 LLScrollListItem* item = new LLScrollListItem();
1699 item->addColumn("Error writing to local file. Is your hard drive full?", LLFontGL::sSansSerifSmall);
1700 mScriptEd->mErrorList->addItem(item);
1701 return;
1702 }
1703 LLString utf8text = mScriptEd->mEditor->getText();
1704 fputs(utf8text.c_str(), fp);
1705 fclose(fp);
1706
1707 LLCheckBoxCtrl* runningCheckbox = LLUICtrlFactory::getCheckBoxByName(this, "running");
1708
1709 // save it out to database
1710 if(gAssetStorage)
1711 {
1712 // write it out to the vfs for upload
1713 LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_TEXT, LLVFile::APPEND);
1714 S32 size = utf8text.length() + 1;
1715
1716 file.setMaxSize(size);
1717 file.write((U8*)utf8text.c_str(), size);
1718
1719 getWindow()->incBusyCount();
1720 mPendingUploads++;
1721 LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectID,
1722 mItem,
1723 runningCheckbox->get());
1724 gAssetStorage->storeAssetData(tid, LLAssetType::AT_LSL_TEXT, &onSaveTextComplete, (void*)data, FALSE);
1725 }
1726
1727#if LL_WINDOWS
1728 // This major hack was inserted because sometimes compilation
1729 // would fail because it couldn't open this file... I decided
1730 // to make a loop until open was successful. This seems to be
1731 // a problem specific to ntfs.
1732 fp = NULL;
1733 const U32 MAX_TRIES = 20;
1734 U32 tries = MAX_TRIES;
1735 while((!fp) && --tries)
1736 {
1737 ms_sleep(17);
1738 fp = LLFile::fopen(filename, "r");
1739 if(!fp)
1740 {
1741 llwarns << "Trying to open the source file " << filename
1742 << " again" << llendl;
1743 }
1744 else
1745 {
1746 fclose(fp);
1747 }
1748 }
1749 fp = NULL;
1750#endif
1751
1752 char dst_filename[LL_MAX_PATH];
1753 sprintf(dst_filename, "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str());
1754 char err_filename[LL_MAX_PATH];
1755 sprintf(err_filename, "%s.out", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str());
1756 LLScrollListItem* item = NULL;
1757 const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA);
1758 if(!lscript_compile(filename, dst_filename, err_filename, gAgent.isGodlike()))
1759 {
1760 // load the error file into the error scrolllist
1761 llinfos << "Compile failed!" << llendl;
1762 if(NULL != (fp = LLFile::fopen(err_filename, "r")))
1763 {
1764 char buffer[MAX_STRING];
1765 LLString line;
1766 while(!feof(fp))
1767 {
1768
1769 fgets(buffer, MAX_STRING, fp);
1770 if(feof(fp))
1771 {
1772 break;
1773 }
1774 else if(!buffer)
1775 {
1776 continue;
1777 }
1778 else
1779 {
1780 line.assign(buffer);
1781 LLString::stripNonprintable(line);
1782 item = new LLScrollListItem();
1783 item->addColumn(line, err_font);
1784 mScriptEd->mErrorList->addItem(item);
1785 }
1786 }
1787 fclose(fp);
1788 mScriptEd->selectFirstError();
1789 // don't set the asset id, because we want to save the
1790 // script, even though the compile failed.
1791 //mItem->setAssetUUID(LLUUID::null);
1792 object->saveScript(mItem, FALSE, false);
1793 dialog_refresh_all();
1794 }
1795 }
1796 else
1797 {
1798 llinfos << "Compile worked!" << llendl;
1799 mScriptEd->mErrorList->addSimpleItem("Compile successful, saving...");
1800 if(gAssetStorage)
1801 {
1802 llinfos << "LLLiveLSLEditor::saveAsset "
1803 << mItem->getAssetUUID() << llendl;
1804
1805 // move the compiled file into the vfs for transport
1806 FILE* fp = LLFile::fopen(dst_filename, "rb");
1807 LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_BYTECODE, LLVFile::APPEND);
1808
1809 fseek(fp, 0, SEEK_END);
1810 S32 size = ftell(fp);
1811 fseek(fp, 0, SEEK_SET);
1812
1813 file.setMaxSize(size);
1814
1815 const S32 buf_size = 65536;
1816 U8 copy_buf[buf_size];
1817 while ((size = fread(copy_buf, 1, buf_size, fp)))
1818 {
1819 file.write(copy_buf, size);
1820 }
1821 fclose(fp);
1822 fp = NULL;
1823
1824 getWindow()->incBusyCount();
1825 mPendingUploads++;
1826 LLLiveLSLSaveData* data = NULL;
1827 data = new LLLiveLSLSaveData(mObjectID,
1828 mItem,
1829 runningCheckbox->get());
1830 gAssetStorage->storeAssetData(tid,
1831 LLAssetType::AT_LSL_BYTECODE,
1832 &LLLiveLSLEditor::onSaveBytecodeComplete,
1833 (void*)data);
1834 dialog_refresh_all();
1835 }
1836 }
1837
1838 // get rid of any temp files left lying around
1839 LLFile::remove(filename);
1840 LLFile::remove(err_filename);
1841 LLFile::remove(dst_filename);
1842
1843 // If we successfully saved it, then we should be able to check/uncheck the running box!
1844 runningCheckbox->setLabel(ENABLED_RUNNING_CHECKBOX_LABEL);
1845 runningCheckbox->setEnabled(TRUE);
1846}
1847
1848void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_data, S32 status) // StoreAssetData callback (fixed)
1849{
1850 LLLiveLSLSaveData* data = (LLLiveLSLSaveData*)user_data;
1851
1852 if (status)
1853 {
1854 llwarns << "Unable to save text for a script." << llendl;
1855 LLStringBase<char>::format_map_t args;
1856 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
1857 gViewerWindow->alertXml("CompileQueueSaveText", args);
1858 }
1859 else
1860 {
1861 LLLiveLSLEditor* self = sInstances.getIfThere(data->mItem->getUUID() ^ data->mObjectID);
1862 if (self)
1863 {
1864 self->getWindow()->decBusyCount();
1865 self->mPendingUploads--;
1866 if (self->mPendingUploads <= 0
1867 && self->mCloseAfterSave)
1868 {
1869 self->close();
1870 }
1871 }
1872 }
1873 delete data;
1874 data = NULL;
1875}
1876
1877
1878void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status) // StoreAssetData callback (fixed)
1879{
1880 LLLiveLSLSaveData* data = (LLLiveLSLSaveData*)user_data;
1881 if(!data)
1882 return;
1883 if(0 ==status)
1884 {
1885 llinfos << "LSL Bytecode saved" << llendl;
1886 LLUUID xor_id = data->mItem->getUUID() ^ data->mObjectID;
1887 LLLiveLSLEditor* self = sInstances.getIfThere(xor_id);
1888 if(self)
1889 {
1890 // Tell the user that the compile worked.
1891 self->mScriptEd->mErrorList->addSimpleItem("Save complete.");
1892 // close the window if this completes both uploads
1893 self->getWindow()->decBusyCount();
1894 self->mPendingUploads--;
1895 if (self->mPendingUploads <= 0
1896 && self->mCloseAfterSave)
1897 {
1898 self->close();
1899 }
1900 }
1901 LLViewerObject* object = gObjectList.findObject(data->mObjectID);
1902 if(object)
1903 {
1904 object->saveScript(data->mItem, data->mActive, false);
1905 dialog_refresh_all();
1906 //LLToolDragAndDrop::dropScript(object, ids->first,
1907 // LLAssetType::AT_LSL_TEXT, FALSE);
1908 }
1909 }
1910 else
1911 {
1912 llinfos << "Problem saving LSL Bytecode (Live Editor)" << llendl;
1913 llwarns << "Unable to save a compiled script." << llendl;
1914
1915 LLStringBase<char>::format_map_t args;
1916 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
1917 gViewerWindow->alertXml("CompileQueueSaveBytecode", args);
1918 }
1919 char uuid_string[UUID_STR_LENGTH];
1920 data->mItem->getAssetUUID().toString(uuid_string);
1921 char dst_filename[LL_MAX_PATH];
1922 sprintf(dst_filename, "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str());
1923 LLFile::remove(dst_filename);
1924 sprintf(dst_filename, "%s.lsl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str());
1925 LLFile::remove(dst_filename);
1926 delete data;
1927}
1928
1929BOOL LLLiveLSLEditor::canClose()
1930{
1931 return (mScriptEd->canClose());
1932}
1933
1934// static
1935void LLLiveLSLEditor::onLoad(void* userdata)
1936{
1937 LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
1938 self->loadAsset();
1939}
1940
1941// static
1942void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)
1943{
1944 LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
1945 self->mCloseAfterSave = close_after_save;
1946 self->saveIfNeeded();
1947}
1948
1949// static
1950LLLiveLSLEditor* LLLiveLSLEditor::show(const LLUUID& script_id, const LLUUID& object_id)
1951{
1952 LLLiveLSLEditor* instance = NULL;
1953 LLUUID xored_id = script_id ^ object_id;
1954 if(LLLiveLSLEditor::sInstances.checkData(xored_id))
1955 {
1956 // Move the existing view to the front
1957 instance = LLLiveLSLEditor::sInstances[xored_id];
1958 instance->open();
1959 }
1960 return instance;
1961}
1962
1963// static
1964void LLLiveLSLEditor::hide(const LLUUID& script_id, const LLUUID& object_id)
1965{
1966 LLUUID xored_id = script_id ^ object_id;
1967 if( LLLiveLSLEditor::sInstances.checkData( xored_id ) )
1968 {
1969 LLLiveLSLEditor* instance = LLLiveLSLEditor::sInstances[xored_id];
1970 if(instance->getParent())
1971 {
1972 instance->getParent()->removeChild(instance);
1973 }
1974 delete instance;
1975 }
1976}
1977
1978// static
1979void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)
1980{
1981 LLUUID item_id;
1982 LLUUID object_id;
1983 msg->getUUIDFast(_PREHASH_Script, _PREHASH_ObjectID, object_id);
1984 msg->getUUIDFast(_PREHASH_Script, _PREHASH_ItemID, item_id);
1985 LLUUID xored_id = item_id ^ object_id;
1986 if(LLLiveLSLEditor::sInstances.checkData(xored_id))
1987 {
1988 LLLiveLSLEditor* instance = LLLiveLSLEditor::sInstances[xored_id];
1989 instance->mHaveRunningInfo = TRUE;
1990 BOOL running;
1991 msg->getBOOLFast(_PREHASH_Script, _PREHASH_Running, running);
1992 LLCheckBoxCtrl* runningCheckbox = LLUICtrlFactory::getCheckBoxByName(instance, "running");
1993 runningCheckbox->set(running);
1994 }
1995}
1996
1997void LLLiveLSLEditor::reshape(S32 width, S32 height, BOOL called_from_parent)
1998{
1999 LLFloater::reshape( width, height, called_from_parent );
2000
2001 if( !isMinimized() )
2002 {
2003 // So that next time you open a script it will have the same height and width
2004 // (although not the same position).
2005 gSavedSettings.setRect("PreviewScriptRect", mRect);
2006 }
2007}