aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llpreviewscript.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llpreviewscript.cpp284
1 files changed, 278 insertions, 6 deletions
diff --git a/linden/indra/newview/llpreviewscript.cpp b/linden/indra/newview/llpreviewscript.cpp
index d2d9ed5..a1c05c7 100644
--- a/linden/indra/newview/llpreviewscript.cpp
+++ b/linden/indra/newview/llpreviewscript.cpp
@@ -178,7 +178,11 @@ LLScriptEdCore::LLScriptEdCore(
178 mLastHelpToken(NULL), 178 mLastHelpToken(NULL),
179 mLiveHelpHistorySize(0), 179 mLiveHelpHistorySize(0),
180 mEnableSave(FALSE), 180 mEnableSave(FALSE),
181 mHasScriptData(FALSE) 181 mEnableXEd(FALSE),
182 mHasScriptData(FALSE),
183 // We need to check for a new file every five seconds, or autosave every 60.
184 // There's probably a better solution to both of the above.
185 LLEventTimer((gSavedSettings.getString("LSLExternalEditor").length() < 3) ? 60 : 5)
182{ 186{
183 setFollowsAll(); 187 setFollowsAll();
184 setBorderVisible(FALSE); 188 setBorderVisible(FALSE);
@@ -209,11 +213,30 @@ LLScriptEdCore::LLScriptEdCore(
209 tooltips.push_back(ll_safe_string(gScriptLibrary.mFunctions[i]->mDesc)); 213 tooltips.push_back(ll_safe_string(gScriptLibrary.mFunctions[i]->mDesc));
210 } 214 }
211 } 215 }
216
217 //gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keywords.ini")
218 std::string keyword_path = gDirUtilp->getUserSkinDir() + gDirUtilp->getDirDelimiter() + "keywords.ini";
219 if(!LLFile::isfile(keyword_path))
220 {
221 llinfos << "nothing at " << keyword_path << llendl;
222 keyword_path = gDirUtilp->getSkinDir() + gDirUtilp->getDirDelimiter() + "keywords.ini";
223 if(!LLFile::isfile(keyword_path))
224 {
225 llinfos << "nothing at " << keyword_path << " ; will use default" << llendl;
226 keyword_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "keywords.ini");
227 }
228 else
229 {
230 llinfos << "loaded skin-specific keywords from " << keyword_path << llendl;
231 }
232 }
233 else
234 {
235 llinfos << "loaded skin-specific keywords from " << keyword_path << llendl;
236 }
212 LLColor3 color(0.5f, 0.0f, 0.15f); 237 LLColor3 color(0.5f, 0.0f, 0.15f);
213 238 mEditor->loadKeywords(keyword_path, funcs, tooltips, color);
214 mEditor->loadKeywords(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keywords.ini"), funcs, tooltips, color);
215 239
216
217 LLKeywordToken *token; 240 LLKeywordToken *token;
218 LLKeywords::keyword_iterator_t token_it; 241 LLKeywords::keyword_iterator_t token_it;
219 for (token_it = mEditor->keywordsBegin(); token_it != mEditor->keywordsEnd(); ++token_it) 242 for (token_it = mEditor->keywordsBegin(); token_it != mEditor->keywordsEnd(); ++token_it)
@@ -233,7 +256,6 @@ LLScriptEdCore::LLScriptEdCore(
233 256
234 childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this); 257 childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this);
235 childSetAction("Save_btn", onBtnSave,this); 258 childSetAction("Save_btn", onBtnSave,this);
236
237 initMenu(); 259 initMenu();
238 260
239 // Do the work that addTabPanel() normally does. 261 // Do the work that addTabPanel() normally does.
@@ -250,6 +272,23 @@ LLScriptEdCore::~LLScriptEdCore()
250 deleteBridges(); 272 deleteBridges();
251} 273}
252 274
275BOOL LLScriptEdCore::tick()
276{
277 //autoSave();
278 if (gSavedSettings.getString("LSLExternalEditor").length() < 3)
279 {
280 if (hasChanged(this))
281 {
282 autoSave();
283 }
284 }
285 else
286 {
287 XedUpd();
288 }
289 return FALSE;
290}
291
253void LLScriptEdCore::initMenu() 292void LLScriptEdCore::initMenu()
254{ 293{
255 294
@@ -297,6 +336,14 @@ void LLScriptEdCore::initMenu()
297 menuItem->setMenuCallback(onBtnHelp, this); 336 menuItem->setMenuCallback(onBtnHelp, this);
298 menuItem->setEnabledCallback(NULL); 337 menuItem->setEnabledCallback(NULL);
299 338
339 menuItem = getChild<LLMenuItemCallGL>("Set External Editor...");
340 menuItem->setMenuCallback(onSetExternalEditor, this);
341 menuItem->setEnabledCallback(NULL);
342
343 menuItem = getChild<LLMenuItemCallGL>("Open in External Editor");
344 menuItem->setMenuCallback(onBtnXEd, this);
345 menuItem->setEnabledCallback(enableExternalEditor);
346
300 menuItem = getChild<LLMenuItemCallGL>("Import Script..."); 347 menuItem = getChild<LLMenuItemCallGL>("Import Script...");
301 menuItem->setMenuCallback(onBtnLoadFromDisc, this); 348 menuItem->setMenuCallback(onBtnLoadFromDisc, this);
302 menuItem->setEnabledCallback(NULL); 349 menuItem->setEnabledCallback(NULL);
@@ -318,7 +365,9 @@ void LLScriptEdCore::setScriptText(const std::string& text, BOOL is_valid)
318{ 365{
319 if (mEditor) 366 if (mEditor)
320 { 367 {
321 mEditor->setText(text); 368 std::string new_text(text);
369 LLStringUtil::replaceTabsWithSpaces(new_text, 4); // fix tabs in text
370 mEditor->setText(new_text);
322 mHasScriptData = is_valid; 371 mHasScriptData = is_valid;
323 } 372 }
324} 373}
@@ -416,6 +465,175 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate)
416 setHelpPage(LLStringUtil::null); 465 setHelpPage(LLStringUtil::null);
417 } 466 }
418} 467}
468//dim
469void LLScriptEdCore::xedLaunch()
470{
471 //llinfos << "LLScriptEdCore::autoSave()" << llendl;
472
473 std::string editor = gSavedSettings.getString("LSLExternalEditor");
474 if (!gDirUtilp->fileExists(editor))
475 {
476 llwarns << "External editor " + editor + " not found" << llendl;
477
478 LLSD row;
479 row["columns"][0]["value"] = "Couldn't open external editor '" + editor + "'. File not found.";
480 row["columns"][0]["font"] = "SANSSERIF_SMALL";
481 mErrorList->addElement(row);
482 return;
483 }
484
485 //std::string filepath = gDirUtilp->getExpandedFilename(gDirUtilp->getTempDir(),asset_id.asString());
486 if( mXfname.empty() )
487 {
488 std::string asfilename = gDirUtilp->getTempFilename();
489 asfilename.replace( asfilename.length()-4, 12, "_Xed.lsl" );
490 mXfname = asfilename;
491 //mAutosaveFilename = llformat("%s.lsl", asfilename.c_str());
492 }
493
494 FILE* fp = LLFile::fopen(mXfname.c_str(), "wb");
495 if(!fp)
496 {
497 llwarns << "Unable to write to " << mXfname << llendl;
498
499 LLSD row;
500 row["columns"][0]["value"] = "Error writing to temp file. Is your hard drive full?";
501 row["columns"][0]["font"] = "SANSSERIF_SMALL";
502 mErrorList->addElement(row);
503 return;
504 }
505 mEditor->setEnabled(FALSE);
506 std::string utf8text = mEditor->getText();
507 fputs(utf8text.c_str(), fp);
508 fclose(fp);
509 fp = NULL;
510 llinfos << "XEditor: " << mXfname << llendl;
511 //record the stat
512 stat(mXfname.c_str(), &mXstbuf);
513 //launch
514#if LL_WINDOWS
515 //just to get rid of the pesky black window
516 std::string exe = gSavedSettings.getString("LSLExternalEditor");
517 S32 spaces=0;
518 for(S32 i=0; i!=exe.size(); ++i)
519 {
520 spaces+=( exe.at(i)==' ');
521 }
522 if(spaces > 0)
523 {
524 exe = "\""+exe+"\"";
525 }
526 std::string theCMD("%COMSPEC% /c START \"External Editor\" " + exe + " " + mXfname + " & exit");
527 llinfos << "FINAL COMMAND IS :"<<
528 theCMD.c_str() << llendl;
529
530 std::system(theCMD.c_str());
531#elif LL_DARWIN
532 // Use Launch Services for this - launching another instance is fail (and incorrect on OS X)
533 CFStringRef strPath = CFStringCreateWithCString(kCFAllocatorDefault, mXfname.c_str(), kCFStringEncodingUTF8);
534 CFURLRef tempPath = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, strPath, kCFURLPOSIXPathStyle, false);
535 CFURLRef tempPathArray[1] = { tempPath };
536 CFArrayRef arguments = CFArrayCreate(kCFAllocatorDefault, (const void **)tempPathArray, 1, NULL);
537 LSApplicationParameters appParams;
538 memset(&appParams, 0, sizeof(appParams));
539 FSRef ref;
540 FSPathMakeRef((UInt8*)gSavedSettings.getString("LSLExternalEditor").c_str(), &ref, NULL);
541 appParams.application = &ref;
542 appParams.flags = kLSLaunchAsync | kLSLaunchStartClassic;
543 LSOpenURLsWithRole(arguments, kLSRolesAll, NULL, &appParams, NULL, 0);
544 CFRelease(arguments);
545 CFRelease(tempPath);
546 CFRelease(strPath);
547#else
548 //std::system(std::string(gSavedSettings.getString("LSLExternalEditor") + " " + mXfname).c_str());
549
550 // Any approach involving std::system will fail because SL eats signals.
551 // This was stolen from floaterskinfinder.cpp.
552 std::string exe = gSavedSettings.getString("LSLExternalEditor");
553 const char *zargv[] = {exe.c_str(), mXfname.c_str(), NULL};
554 fflush(NULL);
555 pid_t id = vfork();
556 if(id == 0)
557 {
558 execv(exe.c_str(), (char **)zargv);
559 _exit(0); // This shouldn't ever be reached.
560 }
561#endif
562}
563
564void LLScriptEdCore::XedUpd()
565{
566 struct stat stbuf;
567 stat(this->mXfname.c_str() , &stbuf);
568 if (this->mXstbuf.st_mtime != stbuf.st_mtime)
569 {
570 this->mErrorList->addCommentText(std::string("Change Detected... Updating"));
571
572 this->mXstbuf = stbuf;
573 LLFILE* file = LLFile::fopen(this->mXfname, "rb"); /*Flawfinder: ignore*/
574 if(file)
575 {
576 // read in the whole file
577 fseek(file, 0L, SEEK_END);
578 S64 file_length = ftell(file);
579 fseek(file, 0L, SEEK_SET);
580 char* buffer = new char[file_length+1];
581 size_t nread = fread(buffer, 1, file_length, file);
582 if (nread < (size_t) file_length)
583 {
584 llwarns << "Short read" << llendl;
585 }
586 buffer[nread] = '\0';
587 fclose(file);
588 std::string ttext = LLStringExplicit(buffer);
589 LLStringUtil::replaceTabsWithSpaces(ttext, 4);
590 mEditor->setText(ttext);
591 LLScriptEdCore::doSave( this, FALSE );
592 //mEditor->makePristine();
593 delete[] buffer;
594 buffer = NULL;
595 }
596 else
597 {
598 llwarns << "Error opening " << this->mXfname << llendl;
599 }
600 }
601}
602//end dim
603void LLScriptEdCore::autoSave()
604{
605 //llinfos << "LLScriptEdCore::autoSave()" << llendl;
606 if(mEditor->isPristine())
607 {
608 return;
609 }
610 //std::string filepath = gDirUtilp->getExpandedFilename(gDirUtilp->getTempDir(),asset_id.asString());
611 if( mAutosaveFilename.empty() )
612 {
613 std::string asfilename = gDirUtilp->getTempFilename();
614 asfilename.replace( asfilename.length()-4, 12, "_autosave.lsl" );
615 mAutosaveFilename = asfilename;
616 //mAutosaveFilename = llformat("%s.lsl", asfilename.c_str());
617 }
618
619 FILE* fp = LLFile::fopen(mAutosaveFilename.c_str(), "wb");
620 if(!fp)
621 {
622 llwarns << "Unable to write to " << mAutosaveFilename << llendl;
623
624 LLSD row;
625 row["columns"][0]["value"] = "Error writing to temp file. Is your hard drive full?";
626 row["columns"][0]["font"] = "SANSSERIF_SMALL";
627 mErrorList->addElement(row);
628 return;
629 }
630
631 std::string utf8text = mEditor->getText();
632 fputs(utf8text.c_str(), fp);
633 fclose(fp);
634 fp = NULL;
635 llinfos << "autosave: " << mAutosaveFilename << llendl;
636}
419 637
420void LLScriptEdCore::setHelpPage(const std::string& help_string) 638void LLScriptEdCore::setHelpPage(const std::string& help_string)
421{ 639{
@@ -507,6 +725,11 @@ bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLS
507 break; 725 break;
508 726
509 case 1: // "No" 727 case 1: // "No"
728 if( !mXfname.empty())
729 {
730 llinfos << "remove autosave: " << mXfname << llendl;
731 LLFile::remove(mXfname.c_str());
732 }
510 mForceClose = TRUE; 733 mForceClose = TRUE;
511 // This will close immediately because mForceClose is true, so we won't 734 // This will close immediately because mForceClose is true, so we won't
512 // infinite loop with these dialogs. JC 735 // infinite loop with these dialogs. JC
@@ -724,6 +947,34 @@ void LLScriptEdCore::onBtnSave(void* data)
724} 947}
725 948
726// static 949// static
950void LLScriptEdCore::onSetExternalEditor(void* data)
951{
952 std::string cur_name(gSavedSettings.getString("LSLExternalEditor"));
953
954 LLFilePicker& picker = LLFilePicker::instance();
955 if (! picker.getOpenFile(LLFilePicker::FFLOAD_APP) )
956 {
957 return; //Canceled!
958 }
959 std::string file_name = picker.getFirstFile();
960 if (!file_name.empty() && file_name != cur_name)
961 {
962 gSavedSettings.setString("LSLExternalEditor", file_name);
963 }
964 else
965 {
966 gSavedSettings.setString("LSLExternalEditor", "");
967 }
968}
969
970//static
971void LLScriptEdCore::onBtnXEd(void* data)
972{
973 LLScriptEdCore* self = (LLScriptEdCore*)data;
974 self->xedLaunch();
975}
976
977// static
727void LLScriptEdCore::onBtnUndoChanges( void* userdata ) 978void LLScriptEdCore::onBtnUndoChanges( void* userdata )
728{ 979{
729 LLScriptEdCore* self = (LLScriptEdCore*) userdata; 980 LLScriptEdCore* self = (LLScriptEdCore*) userdata;
@@ -904,6 +1155,12 @@ BOOL LLScriptEdCore::enableDeselectMenu(void* userdata)
904} 1155}
905 1156
906// static 1157// static
1158BOOL LLScriptEdCore::enableExternalEditor(void* userdata)
1159{
1160 return (gSavedSettings.getString("LSLExternalEditor").length() > 3);
1161}
1162
1163// static
907void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data) 1164void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data)
908{ 1165{
909 LLScriptEdCore* self = (LLScriptEdCore*)user_data; 1166 LLScriptEdCore* self = (LLScriptEdCore*)user_data;
@@ -989,6 +1246,11 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask)
989 if(mSaveCallback) 1246 if(mSaveCallback)
990 { 1247 {
991 // don't close after saving 1248 // don't close after saving
1249 if (!hasChanged(this))
1250 {
1251 llinfos << "Save Not Needed" << llendl;
1252 return TRUE;
1253 }
992 mSaveCallback(mUserdata, FALSE); 1254 mSaveCallback(mUserdata, FALSE);
993 } 1255 }
994 1256
@@ -1181,6 +1443,11 @@ void LLPreviewLSL::closeIfNeeded()
1181 mPendingUploads--; 1443 mPendingUploads--;
1182 if (mPendingUploads <= 0 && mCloseAfterSave) 1444 if (mPendingUploads <= 0 && mCloseAfterSave)
1183 { 1445 {
1446 if( !mScriptEd->mXfname.empty())
1447 {
1448 llinfos << "remove autosave: " << mScriptEd->mXfname << llendl;
1449 LLFile::remove(mScriptEd->mXfname.c_str());
1450 }
1184 close(); 1451 close();
1185 } 1452 }
1186} 1453}
@@ -2349,6 +2616,11 @@ void LLLiveLSLEditor::closeIfNeeded()
2349 mPendingUploads--; 2616 mPendingUploads--;
2350 if (mPendingUploads <= 0 && mCloseAfterSave) 2617 if (mPendingUploads <= 0 && mCloseAfterSave)
2351 { 2618 {
2619 if( !mScriptEd->mXfname.empty())
2620 {
2621 llinfos << "remove autosave: " << mScriptEd->mXfname << llendl;
2622 LLFile::remove(mScriptEd->mXfname.c_str());
2623 }
2352 close(); 2624 close();
2353 } 2625 }
2354} 2626}