diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llpreviewscript.cpp | 284 |
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 | ||
275 | BOOL 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 | |||
253 | void LLScriptEdCore::initMenu() | 292 | void 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 | ||
469 | void 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 | |||
564 | void 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 | ||
603 | void 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 | ||
420 | void LLScriptEdCore::setHelpPage(const std::string& help_string) | 638 | void 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 |
950 | void 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 | ||
971 | void LLScriptEdCore::onBtnXEd(void* data) | ||
972 | { | ||
973 | LLScriptEdCore* self = (LLScriptEdCore*)data; | ||
974 | self->xedLaunch(); | ||
975 | } | ||
976 | |||
977 | // static | ||
727 | void LLScriptEdCore::onBtnUndoChanges( void* userdata ) | 978 | void 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 |
1158 | BOOL LLScriptEdCore::enableExternalEditor(void* userdata) | ||
1159 | { | ||
1160 | return (gSavedSettings.getString("LSLExternalEditor").length() > 3); | ||
1161 | } | ||
1162 | |||
1163 | // static | ||
907 | void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data) | 1164 | void 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 | } |