llfilepicker.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llfilepicker.h"
00035 #include "llworld.h"
00036 #include "llviewerwindow.h"
00037 #include "llkeyboard.h"
00038 #include "lldir.h"
00039 #include "llframetimer.h"
00040 
00041 #if LL_SDL
00042 #include "llwindowsdl.h" // for some X/GTK utils to help with filepickers
00043 #endif // LL_SDL
00044 
00045 //
00046 // Globals
00047 //
00048 
00049 LLFilePicker LLFilePicker::sInstance;
00050 
00051 #if LL_WINDOWS
00052 #define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0"
00053 #define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"
00054 #define ANIM_FILTER L"Animations (*.bvh)\0*.bvh\0"
00055 #ifdef _CORY_TESTING
00056 #define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0"
00057 #endif
00058 #define XML_FILTER L"XML files (*.xml)\0*.xml\0"
00059 #define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
00060 #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
00061 #endif
00062 
00063 //
00064 // Implementation
00065 //
00066 #if LL_WINDOWS
00067 
00068 LLFilePicker::LLFilePicker() 
00069 {
00070         reset();
00071 
00072         mOFN.lStructSize = sizeof(OPENFILENAMEW);
00073         mOFN.hwndOwner = NULL;  // Set later
00074         mOFN.hInstance = NULL;
00075         mOFN.lpstrCustomFilter = NULL;
00076         mOFN.nMaxCustFilter = 0;
00077         mOFN.lpstrFile = NULL;                                                  // set in open and close
00078         mOFN.nMaxFile = LL_MAX_PATH;
00079         mOFN.lpstrFileTitle = NULL;
00080         mOFN.nMaxFileTitle = 0;
00081         mOFN.lpstrInitialDir = NULL;
00082         mOFN.lpstrTitle = NULL;
00083         mOFN.Flags = 0;                                                                 // set in open and close
00084         mOFN.nFileOffset = 0;
00085         mOFN.nFileExtension = 0;
00086         mOFN.lpstrDefExt = NULL;
00087         mOFN.lCustData = 0L;
00088         mOFN.lpfnHook = NULL;
00089         mOFN.lpTemplateName = NULL;
00090 }
00091 
00092 LLFilePicker::~LLFilePicker()
00093 {
00094         // nothing
00095 }
00096 
00097 BOOL LLFilePicker::setupFilter(ELoadFilter filter)
00098 {
00099         BOOL res = TRUE;
00100         switch (filter)
00101         {
00102         case FFLOAD_ALL:
00103                 mOFN.lpstrFilter = L"All Files (*.*)\0*.*\0" \
00104                 SOUND_FILTER \
00105                 IMAGE_FILTER \
00106                 ANIM_FILTER \
00107                 L"\0";
00108                 break;
00109         case FFLOAD_WAV:
00110                 mOFN.lpstrFilter = SOUND_FILTER \
00111                         L"\0";
00112                 break;
00113         case FFLOAD_IMAGE:
00114                 mOFN.lpstrFilter = IMAGE_FILTER \
00115                         L"\0";
00116                 break;
00117         case FFLOAD_ANIM:
00118                 mOFN.lpstrFilter = ANIM_FILTER \
00119                         L"\0";
00120                 break;
00121 #ifdef _CORY_TESTING
00122         case FFLOAD_GEOMETRY:
00123                 mOFN.lpstrFilter = GEOMETRY_FILTER \
00124                         L"\0";
00125                 break;
00126 #endif
00127         case FFLOAD_XML:
00128                 mOFN.lpstrFilter = XML_FILTER \
00129                         L"\0";
00130                 break;
00131         case FFLOAD_SLOBJECT:
00132                 mOFN.lpstrFilter = SLOBJECT_FILTER \
00133                         L"\0";
00134                 break;
00135         case FFLOAD_RAW:
00136                 mOFN.lpstrFilter = RAW_FILTER \
00137                         L"\0";
00138                 break;
00139         default:
00140                 res = FALSE;
00141                 break;
00142         }
00143         return res;
00144 }
00145 
00146 BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
00147 {
00148         if( mLocked )
00149         {
00150                 return FALSE;
00151         }
00152         BOOL success = FALSE;
00153         mMultiFile = FALSE;
00154 
00155         // don't provide default file selection
00156         mFilesW[0] = '\0';
00157 
00158         mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
00159         mOFN.lpstrFile = mFilesW;
00160         mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
00161         mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR ;
00162         mOFN.nFilterIndex = 1;
00163 
00164         setupFilter(filter);
00165         
00166         // Modal, so pause agent
00167         send_agent_pause();
00168         // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
00169         success = GetOpenFileName(&mOFN);
00170         if (success)
00171         {
00172                 LLString tstr = utf16str_to_utf8str(llutf16string(mFilesW));
00173                 memcpy(mFiles, tstr.c_str(), tstr.size()+1); /*Flawfinder: ignore*/
00174                 mCurrentFile = mFiles;
00175         }
00176         send_agent_resume();
00177 
00178         // Account for the fact that the app has been stalled.
00179         LLFrameTimer::updateFrameTime();
00180         return success;
00181 }
00182 
00183 BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
00184 {
00185         if( mLocked )
00186         {
00187                 return FALSE;
00188         }
00189         BOOL success = FALSE;
00190         mMultiFile = FALSE;
00191 
00192         // don't provide default file selection
00193         mFilesW[0] = '\0';
00194 
00195         mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
00196         mOFN.lpstrFile = mFilesW;
00197         mOFN.nFilterIndex = 1;
00198         mOFN.nMaxFile = FILENAME_BUFFER_SIZE;
00199         mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR |
00200                 OFN_EXPLORER | OFN_ALLOWMULTISELECT;
00201 
00202         setupFilter(filter);
00203         
00204         // Modal, so pause agent
00205         send_agent_pause();
00206         // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
00207         success = GetOpenFileName(&mOFN); // pauses until ok or cancel.
00208         if( success )
00209         {
00210                 // The getopenfilename api doesn't tell us if we got more than
00211                 // one file, so we have to test manually by checking string
00212                 // lengths.
00213                 if( wcslen(mOFN.lpstrFile) > mOFN.nFileOffset ) /*Flawfinder: ignore*/
00214                 {
00215                         mMultiFile = FALSE;
00216                         mCurrentFile = mFiles;
00217                         LLString tstr = utf16str_to_utf8str(llutf16string(mFilesW));
00218                         memcpy(mFiles, tstr.c_str(), tstr.size()+1); /*Flawfinder: ignore*/
00219                 }
00220                 else
00221                 {
00222                         mMultiFile = TRUE;
00223                         mCurrentFile = 0;
00224                         mLocked = TRUE;
00225                         WCHAR* tptrw = mFilesW;
00226                         char* tptr = mFiles;
00227                         memset( mFiles, 0, FILENAME_BUFFER_SIZE );
00228                         while(1)
00229                         {
00230                                 if (*tptrw == 0 && *(tptrw+1) == 0) // double '\0'
00231                                         break;
00232                                 if (*tptrw == 0 && !mCurrentFile)
00233                                         mCurrentFile = tptr+1;
00234                                 S32 tlen16,tlen8;
00235                                 tlen16 = utf16chars_to_utf8chars(tptrw, tptr, &tlen8);
00236                                 tptrw += tlen16;
00237                                 tptr += tlen8;
00238                         }
00239                 }
00240         }
00241         send_agent_resume();
00242 
00243         // Account for the fact that the app has been stalled.
00244         LLFrameTimer::updateFrameTime();
00245         return success;
00246 }
00247 
00248 BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
00249 {
00250         if( mLocked )
00251         {
00252                 return FALSE;
00253         }
00254         BOOL success = FALSE;
00255         mMultiFile = FALSE;
00256 
00257         mOFN.lpstrFile = mFilesW;
00258         if (filename)
00259         {
00260                 llutf16string tstring = utf8str_to_utf16str(filename);
00261                 wcsncpy(mFilesW, tstring.c_str(), FILENAME_BUFFER_SIZE);        }       /*Flawfinder: ignore*/
00262         else
00263         {
00264                 mFilesW[0] = '\0';
00265         }
00266         mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
00267 
00268         switch( filter )
00269         {
00270         case FFSAVE_ALL:
00271                 mOFN.lpstrDefExt = NULL;
00272                 mOFN.lpstrFilter =
00273                         L"All Files (*.*)\0*.*\0" \
00274                         L"WAV Sounds (*.wav)\0*.wav\0" \
00275                         L"Targa, Bitmap Images (*.tga; *.bmp)\0*.tga;*.bmp\0" \
00276                         L"\0";
00277                 break;
00278         case FFSAVE_WAV:
00279                 if (!filename)
00280                 {
00281                         wcsncpy( mFilesW,L"untitled.wav", FILENAME_BUFFER_SIZE);        /*Flawfinder: ignore*/
00282                 }
00283                 mOFN.lpstrDefExt = L"wav";
00284                 mOFN.lpstrFilter =
00285                         L"WAV Sounds (*.wav)\0*.wav\0" \
00286                         L"\0";
00287                 break;
00288         case FFSAVE_TGA:
00289                 if (!filename)
00290                 {
00291                         wcsncpy( mFilesW,L"untitled.tga", FILENAME_BUFFER_SIZE);        /*Flawfinder: ignore*/
00292                 }
00293                 mOFN.lpstrDefExt = L"tga";
00294                 mOFN.lpstrFilter =
00295                         L"Targa Images (*.tga)\0*.tga\0" \
00296                         L"\0";
00297                 break;
00298         case FFSAVE_BMP:
00299                 if (!filename)
00300                 {
00301                         wcsncpy( mFilesW,L"untitled.bmp", FILENAME_BUFFER_SIZE);        /*Flawfinder: ignore*/
00302                 }
00303                 mOFN.lpstrDefExt = L"bmp";
00304                 mOFN.lpstrFilter =
00305                         L"Bitmap Images (*.bmp)\0*.bmp\0" \
00306                         L"\0";
00307                 break;
00308         case FFSAVE_AVI:
00309                 if (!filename)
00310                 {
00311                         wcsncpy( mFilesW,L"untitled.avi", FILENAME_BUFFER_SIZE);        /*Flawfinder: ignore*/
00312                 }
00313                 mOFN.lpstrDefExt = L"avi";
00314                 mOFN.lpstrFilter =
00315                         L"AVI Movie File (*.avi)\0*.avi\0" \
00316                         L"\0";
00317                 break;
00318         case FFSAVE_ANIM:
00319                 if (!filename)
00320                 {
00321                         wcsncpy( mFilesW,L"untitled.xaf", FILENAME_BUFFER_SIZE);        /*Flawfinder: ignore*/
00322                 }
00323                 mOFN.lpstrDefExt = L"xaf";
00324                 mOFN.lpstrFilter =
00325                         L"XAF Anim File (*.xaf)\0*.xaf\0" \
00326                         L"\0";
00327                 break;
00328 #ifdef _CORY_TESTING
00329         case FFSAVE_GEOMETRY:
00330                 if (!filename)
00331                 {
00332                         wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE);        /*Flawfinder: ignore*/
00333                 }
00334                 mOFN.lpstrDefExt = L"slg";
00335                 mOFN.lpstrFilter =
00336                         L"SLG SL Geometry File (*.slg)\0*.slg\0" \
00337                         L"\0";
00338                 break;
00339 #endif
00340         case FFSAVE_XML:
00341                 if (!filename)
00342                 {
00343                         wcsncpy( mFilesW,L"untitled.xml", FILENAME_BUFFER_SIZE);        /*Flawfinder: ignore*/
00344                 }
00345 
00346                 mOFN.lpstrDefExt = L"xml";
00347                 mOFN.lpstrFilter =
00348                         L"XML File (*.xml)\0*.xml\0" \
00349                         L"\0";
00350                 break;
00351         case FFSAVE_COLLADA:
00352                 if (!filename)
00353                 {
00354                         wcsncpy( mFilesW,L"untitled.collada", FILENAME_BUFFER_SIZE);    /*Flawfinder: ignore*/
00355                 }
00356                 mOFN.lpstrDefExt = L"collada";
00357                 mOFN.lpstrFilter =
00358                         L"COLLADA File (*.collada)\0*.collada\0" \
00359                         L"\0";
00360                 break;
00361         case FFSAVE_RAW:
00362                 if (!filename)
00363                 {
00364                         wcsncpy( mFilesW,L"untitled.raw", FILENAME_BUFFER_SIZE);        /*Flawfinder: ignore*/
00365                 }
00366                 mOFN.lpstrDefExt = L"raw";
00367                 mOFN.lpstrFilter =      RAW_FILTER \
00368                                                         L"\0";
00369                 break;
00370         case FFSAVE_J2C:
00371                 if (!filename)
00372                 {
00373                         wcsncpy( mFilesW,L"untitled.j2c", FILENAME_BUFFER_SIZE);
00374                 }
00375                 mOFN.lpstrDefExt = L"j2c";
00376                 mOFN.lpstrFilter =
00377                         L"Compressed Images (*.j2c)\0*.j2c\0" \
00378                         L"\0";
00379                 break;
00380         default:
00381                 return FALSE;
00382         }
00383 
00384  
00385         mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
00386         mOFN.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
00387 
00388         // Modal, so pause agent
00389         send_agent_pause();
00390         {
00391                 // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
00392                 success = GetSaveFileName(&mOFN);
00393                 if (success)
00394                 {
00395                         LLString tstr = utf16str_to_utf8str(llutf16string(mFilesW));
00396                         memcpy(mFiles, tstr.c_str(), tstr.size()+1);  /*Flawfinder: ignore*/
00397                         mCurrentFile = mFiles;
00398                 }
00399                 gKeyboard->resetKeys();
00400         }
00401         send_agent_resume();
00402 
00403         // Account for the fact that the app has been stalled.
00404         LLFrameTimer::updateFrameTime();
00405         return success;
00406 }
00407 
00408 const char* LLFilePicker::getFirstFile()
00409 {
00410         if(mMultiFile)
00411         {
00412                 buildFilename();
00413                 return mFilename;
00414         }
00415         return mFiles;
00416 }
00417 
00418 const char* LLFilePicker::getNextFile()
00419 {
00420         if(mMultiFile)
00421         {
00422                 mCurrentFile += strlen(mCurrentFile) + 1;       /*Flawfinder: ignore*/
00423                 if( '\0' != mCurrentFile[0] )
00424                 {
00425                         buildFilename();
00426                         return mFilename;
00427                 }
00428                 else
00429                 {
00430                         mLocked = FALSE;
00431                 }
00432         }
00433         return NULL;
00434 }
00435 
00436 const char* LLFilePicker::getDirname()
00437 {
00438         if( '\0' != mCurrentFile[0] )
00439         {
00440                 return mCurrentFile;
00441         }
00442         return NULL;
00443 }
00444 
00445 void LLFilePicker::reset()
00446 {
00447         mLocked = FALSE;
00448         memset( mFiles, 0, FILENAME_BUFFER_SIZE );
00449         memset( mFilename, 0, LL_MAX_PATH );
00450         mCurrentFile = mFiles;
00451 }
00452 
00453 void LLFilePicker::buildFilename( void )
00454 {
00455         strncpy( mFilename, mFiles, LL_MAX_PATH );
00456         mFilename[LL_MAX_PATH-1] = '\0'; // stupid strncpy
00457         S32 len = strlen( mFilename );
00458 
00459         strncat(mFilename,gDirUtilp->getDirDelimiter().c_str(), sizeof(mFilename)-len+1);               /*Flawfinder: ignore*/
00460         len += strlen(gDirUtilp->getDirDelimiter().c_str());    /*Flawfinder: ignore*/
00461 
00462 //      mFilename[len++] = '\\';
00463         LLString::copy( mFilename + len, mCurrentFile, LL_MAX_PATH - len );
00464 }
00465 
00466 #elif LL_DARWIN
00467 
00468 LLFilePicker::LLFilePicker() 
00469 {
00470         reset();
00471 
00472         memset(&mNavOptions, 0, sizeof(mNavOptions));
00473         OSStatus        error = NavGetDefaultDialogCreationOptions(&mNavOptions);
00474         if (error == noErr)
00475         {
00476                 mNavOptions.modality = kWindowModalityAppModal;
00477         }
00478         mFileIndex = 0;
00479 }
00480 
00481 LLFilePicker::~LLFilePicker()
00482 {
00483         // nothing
00484 }
00485 
00486 Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
00487 {
00488         Boolean         result = true;
00489         ELoadFilter filter = *((ELoadFilter*) callBackUD);
00490         OSStatus        error = noErr;
00491         
00492         if (filterMode == kNavFilteringBrowserList && filter != FFLOAD_ALL && (theItem->descriptorType == typeFSRef || theItem->descriptorType == typeFSS))
00493         {
00494                 // navInfo is only valid for typeFSRef and typeFSS
00495                 NavFileOrFolderInfo     *navInfo = (NavFileOrFolderInfo*) info;
00496                 if (!navInfo->isFolder)
00497                 {
00498                         AEDesc  desc;
00499                         error = AECoerceDesc(theItem, typeFSRef, &desc);
00500                         if (error == noErr)
00501                         {
00502                                 FSRef   fileRef;
00503                                 error = AEGetDescData(&desc, &fileRef, sizeof(fileRef));
00504                                 if (error == noErr)
00505                                 {
00506                                         LSItemInfoRecord        fileInfo;
00507                                         error = LSCopyItemInfoForRef(&fileRef, kLSRequestExtension | kLSRequestTypeCreator, &fileInfo);
00508                                         if (error == noErr)
00509                                         {
00510                                                 if (filter == FFLOAD_IMAGE)
00511                                                 {
00512                                                         if (fileInfo.filetype != 'JPEG' && fileInfo.filetype != 'JPG ' && 
00513                                                                 fileInfo.filetype != 'BMP ' && fileInfo.filetype != 'TGA ' &&
00514                                                                 fileInfo.filetype != 'BMPf' && fileInfo.filetype != 'TPIC' &&
00515                                                                 fileInfo.filetype != 'PNG ' &&
00516                                                                 (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("jpeg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
00517                                                                 CFStringCompare(fileInfo.extension, CFSTR("jpg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
00518                                                                 CFStringCompare(fileInfo.extension, CFSTR("bmp"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
00519                                                                 CFStringCompare(fileInfo.extension, CFSTR("tga"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
00520                                                                 CFStringCompare(fileInfo.extension, CFSTR("png"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
00521                                                                 )
00522                                                         {
00523                                                                 result = false;
00524                                                         }
00525                                                 }
00526                                                 else if (filter == FFLOAD_WAV)
00527                                                 {
00528                                                         if (fileInfo.filetype != 'WAVE' && fileInfo.filetype != 'WAV ' && 
00529                                                                 (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("wave"), kCFCompareCaseInsensitive) != kCFCompareEqualTo && 
00530                                                                 CFStringCompare(fileInfo.extension, CFSTR("wav"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
00531                                                         )
00532                                                         {
00533                                                                 result = false;
00534                                                         }
00535                                                 }
00536                                                 else if (filter == FFLOAD_ANIM)
00537                                                 {
00538                                                         if (fileInfo.filetype != 'BVH ' && 
00539                                                                 (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
00540                                                         )
00541                                                         {
00542                                                                 result = false;
00543                                                         }
00544                                                 }
00545 #ifdef _CORY_TESTING
00546                                                 else if (filter == FFLOAD_GEOMETRY)
00547                                                 {
00548                                                         if (fileInfo.filetype != 'SLG ' && 
00549                                                                 (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("slg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
00550                                                         )
00551                                                         {
00552                                                                 result = false;
00553                                                         }
00554                                                 }
00555 #endif
00556                                                 else if (filter == FFLOAD_SLOBJECT)
00557                                                 {
00558                                                         llwarns << "*** navOpenFilterProc: FFLOAD_SLOBJECT NOT IMPLEMENTED ***" << llendl;
00559                                                 }
00560                                                 else if (filter == FFLOAD_RAW)
00561                                                 {
00562                                                         if (fileInfo.filetype != '\?\?\?\?' && 
00563                                                                 (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("raw"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
00564                                                         )
00565                                                         {
00566                                                                 result = false;
00567                                                         }
00568                                                 }
00569                                                 
00570                                                 if (fileInfo.extension)
00571                                                 {
00572                                                         CFRelease(fileInfo.extension);
00573                                                 }
00574                                         }
00575                                 }
00576                                 AEDisposeDesc(&desc);
00577                         }
00578                 }
00579         }
00580         return result;
00581 }
00582 
00583 OSStatus        LLFilePicker::doNavChooseDialog(ELoadFilter filter)
00584 {
00585         OSStatus                error = noErr;
00586         NavDialogRef    navRef = NULL;
00587         NavReplyRecord  navReply;
00588 
00589         memset(&navReply, 0, sizeof(navReply));
00590         mFiles[0] = '\0';
00591         mFileVector.clear();
00592         
00593         // NOTE: we are passing the address of a local variable here.  
00594         //   This is fine, because the object this call creates will exist for less than the lifetime of this function.
00595         //   (It is destroyed by NavDialogDispose() below.)
00596         error = NavCreateChooseFileDialog(&mNavOptions, NULL, NULL, NULL, navOpenFilterProc, (void*)(&filter), &navRef);
00597 
00598         gViewerWindow->mWindow->beforeDialog();
00599 
00600         if (error == noErr)
00601                 error = NavDialogRun(navRef);
00602 
00603         gViewerWindow->mWindow->afterDialog();
00604 
00605         if (error == noErr)
00606                 error = NavDialogGetReply(navRef, &navReply);
00607 
00608         if (navRef)
00609                 NavDialogDispose(navRef);
00610 
00611         if (error == noErr && navReply.validRecord)
00612         {
00613                 SInt32  count = 0;
00614                 SInt32  index;
00615                 
00616                 // AE indexes are 1 based...
00617                 error = AECountItems(&navReply.selection, &count);
00618                 for (index = 1; index <= count; index++)
00619                 {
00620                         FSRef           fsRef;
00621                         AEKeyword       theAEKeyword;
00622                         DescType        typeCode;
00623                         Size            actualSize = 0;
00624                         char            path[MAX_PATH]; /*Flawfinder: ignore*/
00625                         
00626                         memset(&fsRef, 0, sizeof(fsRef));
00627                         error = AEGetNthPtr(&navReply.selection, index, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
00628                         
00629                         if (error == noErr)
00630                                 error = FSRefMakePath(&fsRef, (UInt8*) path, sizeof(path));
00631                         
00632                         if (error == noErr)
00633                                 mFileVector.push_back(LLString(path));
00634                 }
00635         }
00636         
00637         return error;
00638 }
00639 
00640 OSStatus        LLFilePicker::doNavSaveDialog(ESaveFilter filter, const char* filename)
00641 {
00642         OSStatus                error = noErr;
00643         NavDialogRef    navRef = NULL;
00644         NavReplyRecord  navReply;
00645         
00646         memset(&navReply, 0, sizeof(navReply));
00647         mFiles[0] = '\0';
00648         mFileVector.clear();
00649         
00650         // Setup the type, creator, and extension
00651         OSType          type, creator;
00652         CFStringRef     extension = NULL;
00653         switch (filter)
00654         {
00655                 case FFSAVE_WAV:
00656                         type = 'WAVE';
00657                         creator = 'TVOD';
00658                         extension = CFSTR(".wav");
00659                         break;
00660                 
00661                 case FFSAVE_TGA:
00662                         type = 'TPIC';
00663                         creator = 'prvw';
00664                         extension = CFSTR(".tga");
00665                         break;
00666                 
00667                 case FFSAVE_BMP:
00668                         type = 'BMPf';
00669                         creator = 'prvw';
00670                         extension = CFSTR(".bmp");
00671                         break;
00672                 
00673                 case FFSAVE_AVI:
00674                         type = '\?\?\?\?';
00675                         creator = '\?\?\?\?';
00676                         extension = CFSTR(".mov");
00677                         break;
00678 
00679                 case FFSAVE_ANIM:
00680                         type = '\?\?\?\?';
00681                         creator = '\?\?\?\?';
00682                         extension = CFSTR(".xaf");
00683                         break;
00684 
00685 #ifdef _CORY_TESTING
00686                 case FFSAVE_GEOMETRY:
00687                         type = '\?\?\?\?';
00688                         creator = '\?\?\?\?';
00689                         extension = CFSTR(".slg");
00690                         break;
00691 #endif          
00692                 case FFSAVE_RAW:
00693                         type = '\?\?\?\?';
00694                         creator = '\?\?\?\?';
00695                         extension = CFSTR(".raw");
00696                         break;
00697 
00698                 case FFSAVE_J2C:
00699                         type = '\?\?\?\?';
00700                         creator = 'prvw';
00701                         extension = CFSTR(".j2c");
00702                         break;
00703                 
00704                 case FFSAVE_ALL:
00705                 default:
00706                         type = '\?\?\?\?';
00707                         creator = '\?\?\?\?';
00708                         extension = CFSTR("");
00709                         break;
00710         }
00711         
00712         // Create the dialog
00713         error = NavCreatePutFileDialog(&mNavOptions, type, creator, NULL, NULL, &navRef);
00714         if (error == noErr)
00715         {
00716                 CFStringRef     nameString = NULL;
00717                 bool            hasExtension = true;
00718                 
00719                 // Create a CFString of the initial file name
00720                 if (filename)
00721                         nameString = CFStringCreateWithCString(NULL, filename, kCFStringEncodingUTF8);
00722                 else
00723                         nameString = CFSTR("Untitled");
00724                         
00725                 // Add the extension if one was not provided
00726                 if (nameString && !CFStringHasSuffix(nameString, extension))
00727                 {
00728                         CFStringRef     tempString = nameString;
00729                         hasExtension = false;
00730                         nameString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), tempString, extension);
00731                         CFRelease(tempString);
00732                 }
00733                 
00734                 // Set the name in the dialog
00735                 if (nameString)
00736                 {
00737                         error = NavDialogSetSaveFileName(navRef, nameString);
00738                         CFRelease(nameString);
00739                 }
00740                 else
00741                 {
00742                         error = paramErr;
00743                 }
00744         }
00745         
00746         gViewerWindow->mWindow->beforeDialog();
00747 
00748         // Run the dialog
00749         if (error == noErr)
00750                 error = NavDialogRun(navRef);
00751 
00752         gViewerWindow->mWindow->afterDialog();
00753 
00754         if (error == noErr)
00755                 error = NavDialogGetReply(navRef, &navReply);
00756         
00757         if (navRef)
00758                 NavDialogDispose(navRef);
00759 
00760         if (error == noErr && navReply.validRecord)
00761         {
00762                 SInt32  count = 0;
00763                 
00764                 // AE indexes are 1 based...
00765                 error = AECountItems(&navReply.selection, &count);
00766                 if (count > 0)
00767                 {
00768                         // Get the FSRef to the containing folder
00769                         FSRef           fsRef;
00770                         AEKeyword       theAEKeyword;
00771                         DescType        typeCode;
00772                         Size            actualSize = 0;
00773                         
00774                         memset(&fsRef, 0, sizeof(fsRef));
00775                         error = AEGetNthPtr(&navReply.selection, 1, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
00776                         
00777                         if (error == noErr)
00778                         {
00779                                 char    path[PATH_MAX];         /*Flawfinder: ignore*/
00780                                 char    newFileName[SINGLE_FILENAME_BUFFER_SIZE];       /*Flawfinder: ignore*/
00781                                 
00782                                 error = FSRefMakePath(&fsRef, (UInt8*)path, PATH_MAX);
00783                                 if (error == noErr)
00784                                 {
00785                                         if (CFStringGetCString(navReply.saveFileName, newFileName, sizeof(newFileName), kCFStringEncodingUTF8))
00786                                         {
00787                                                 mFileVector.push_back(LLString(path) + LLString("/") +  LLString(newFileName));
00788                                         }
00789                                         else
00790                                         {
00791                                                 error = paramErr;
00792                                         }
00793                                 }
00794                                 else
00795                                 {
00796                                         error = paramErr;
00797                                 }
00798                         }
00799                 }
00800         }
00801         
00802         return error;
00803 }
00804 
00805 BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
00806 {
00807         if( mLocked ) return FALSE;
00808         mMultiFile = FALSE;
00809         BOOL success = FALSE;
00810 
00811         OSStatus        error = noErr;
00812         
00813         mFileVector.clear();
00814         mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
00815         // Modal, so pause agent
00816         send_agent_pause();
00817         {
00818                 error = doNavChooseDialog(filter);
00819         }
00820         send_agent_resume();
00821         if (error == noErr)
00822         {
00823                 if (mFileVector.size())
00824                         success = true;
00825         }
00826 
00827         // Account for the fact that the app has been stalled.
00828         LLFrameTimer::updateFrameTime();
00829         return success;
00830 }
00831 
00832 BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
00833 {
00834         if( mLocked ) return FALSE;
00835         mMultiFile = TRUE;
00836         BOOL success = FALSE;
00837 
00838         OSStatus        error = noErr;
00839         
00840         mFileVector.clear();
00841         mNavOptions.optionFlags |= kNavAllowMultipleFiles;
00842         // Modal, so pause agent
00843         send_agent_pause();
00844         {
00845                 error = doNavChooseDialog(filter);
00846         }
00847         send_agent_resume();
00848         if (error == noErr)
00849         {
00850                 if (mFileVector.size())
00851                         success = true;
00852                 if (mFileVector.size() > 1)
00853                         mLocked = TRUE;
00854         }
00855 
00856         // Account for the fact that the app has been stalled.
00857         LLFrameTimer::updateFrameTime();
00858         return success;
00859 }
00860 
00861 void LLFilePicker::getFilePath(SInt32 index)
00862 {
00863         mFiles[0] = 0;
00864         if (mFileVector.size())
00865         {
00866                 strncpy(mFiles, mFileVector[index].c_str(), sizeof(mFiles));
00867                 mFiles[sizeof(mFiles)-1] = '\0'; // stupid strncpy
00868         }
00869 }
00870 
00871 void LLFilePicker::getFileName(SInt32 index)
00872 {
00873         mFilename[0] = 0;
00874         if (mFileVector.size())
00875         {
00876                 char    *start = strrchr(mFileVector[index].c_str(), '/');
00877                 if (start && ((start + 1 - mFileVector[index].c_str()) < (mFileVector[index].size())))
00878                 {
00879                         strncpy(mFilename, start + 1, sizeof(mFilename));
00880                         mFilename[sizeof(mFilename)-1] = '\0';// stupid strncpy
00881                 }
00882         }
00883 }
00884 
00885 BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
00886 {
00887         if( mLocked ) return FALSE;
00888         BOOL success = FALSE;
00889         OSStatus        error = noErr;
00890 
00891         mFileVector.clear();
00892         mMultiFile = FALSE;
00893         mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
00894 
00895         // Modal, so pause agent
00896         send_agent_pause();
00897         {
00898                 error = doNavSaveDialog(filter, filename);
00899         }
00900         send_agent_resume();
00901         if (error == noErr)
00902         {
00903                 if (mFileVector.size())
00904                         success = true;
00905         }
00906 
00907         // Account for the fact that the app has been stalled.
00908         LLFrameTimer::updateFrameTime();
00909         return success;
00910 }
00911 
00912 const char* LLFilePicker::getFirstFile()
00913 {
00914         mFileIndex = 0;
00915         getFilePath(mFileIndex);
00916         return mFiles;
00917 }
00918 
00919 const char* LLFilePicker::getNextFile()
00920 {
00921         if(mMultiFile)
00922         {
00923                 mFileIndex++;
00924                 if (mFileIndex < mFileVector.size())
00925                 {
00926                         getFilePath(mFileIndex);
00927                         return mFiles;
00928                 }
00929                 else
00930                 {
00931                         mLocked = FALSE;
00932                 }
00933         }
00934         return NULL;
00935 }
00936 
00937 const char* LLFilePicker::getDirname()
00938 {
00939         if (mFileIndex < mFileVector.size())
00940         {
00941                 getFileName(mFileIndex);
00942                 return mFilename;
00943         }
00944         return NULL;
00945 }
00946 
00947 void LLFilePicker::reset()
00948 {
00949         mLocked = FALSE;
00950         memset( mFiles, 0, FILENAME_BUFFER_SIZE );
00951         memset( mFilename, 0, LL_MAX_PATH );
00952         mCurrentFile = mFiles;
00953 
00954         mFileIndex = 0;
00955         mFileVector.clear();
00956 }
00957 
00958 #elif LL_LINUX
00959 
00960 # if LL_GTK
00961 // This caches the previously-accessed path for a given context of the file
00962 // chooser, for user convenience.
00963 std::map <std::string, std::string> LLFilePicker::sContextToPathMap;
00964 
00965 LLFilePicker::LLFilePicker() 
00966 {
00967         reset();
00968 }
00969 
00970 LLFilePicker::~LLFilePicker()
00971 {
00972 }
00973 
00974 
00975 static void add_to_sfs(gpointer data, gpointer user_data)
00976 {
00977         StoreFilenamesStruct *sfs = (StoreFilenamesStruct*) user_data;
00978         gchar* filename_utf8 = g_filename_to_utf8((gchar*)data,
00979                                                   -1, NULL,
00980                                                   NULL,
00981                                                   NULL);
00982         sfs->fileVector.push_back(LLString(filename_utf8));
00983         g_free(filename_utf8);
00984 }
00985 
00986 
00987 void chooser_responder(GtkWidget *widget,
00988                        gint       response,
00989                        gpointer user_data) {
00990         StoreFilenamesStruct *sfs = (StoreFilenamesStruct*) user_data;
00991 
00992         lldebugs << "GTK DIALOG RESPONSE " << response << llendl;
00993 
00994         if (response == GTK_RESPONSE_ACCEPT)
00995         {
00996                 GSList *file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
00997                 g_slist_foreach(file_list, (GFunc)add_to_sfs, sfs);
00998                 g_slist_foreach(file_list, (GFunc)g_free, NULL);
00999                 g_slist_free (file_list);
01000         }
01001 
01002         // set the default path for this usage context.
01003         LLFilePicker::sContextToPathMap[sfs->contextName] =
01004                 gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
01005 
01006         gtk_widget_destroy(widget);
01007         gtk_main_quit();
01008 }
01009 
01010 
01011 GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder,
01012                                          std::string context)
01013 {
01014         if (ll_try_gtk_init() &&
01015             ! gViewerWindow->getWindow()->getFullscreen())
01016         {
01017                 GtkWidget *win = NULL;
01018                 GtkFileChooserAction pickertype =
01019                         is_save?
01020                         (is_folder?
01021                          GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER :
01022                          GTK_FILE_CHOOSER_ACTION_SAVE) :
01023                         (is_folder?
01024                          GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER :
01025                          GTK_FILE_CHOOSER_ACTION_OPEN);
01026 
01027                 win = gtk_file_chooser_dialog_new(NULL, NULL,
01028                                                   pickertype,
01029                                                   GTK_STOCK_CANCEL,
01030                                                    GTK_RESPONSE_CANCEL,
01031                                                   is_folder ?
01032                                                   GTK_STOCK_APPLY :
01033                                                   (is_save ? 
01034                                                    GTK_STOCK_SAVE :
01035                                                    GTK_STOCK_OPEN),
01036                                                    GTK_RESPONSE_ACCEPT,
01037                                                   NULL);
01038                 mStoreFilenames.win = win;
01039                 mStoreFilenames.contextName = context;
01040 
01041                 // get the default path for this usage context if it's been
01042                 // seen before.
01043                 std::map<std::string,std::string>::iterator
01044                         this_path = sContextToPathMap.find(context);
01045                 if (this_path != sContextToPathMap.end())
01046                 {
01047                         gtk_file_chooser_set_current_folder
01048                                 (GTK_FILE_CHOOSER(win),
01049                                  this_path->second.c_str());
01050                 }
01051 
01052 #  if LL_X11
01053                 // Make GTK tell the window manager to associate this
01054                 // dialog with our non-GTK raw X11 window, which should try
01055                 // to keep it on top etc.
01056                 Window XWindowID = get_SDL_XWindowID();
01057                 if (None != XWindowID)
01058                 {
01059                         gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
01060                         GdkWindow *gdkwin = gdk_window_foreign_new(XWindowID);
01061                         gdk_window_set_transient_for(GTK_WIDGET(win)->window,
01062                                                      gdkwin);
01063                 }
01064                 else
01065                 {
01066                         llwarns << "Hmm, couldn't get xwid to use for transient." << llendl;
01067                 }
01068 #  endif //LL_X11
01069 
01070                 g_signal_connect (GTK_FILE_CHOOSER(win),
01071                                   "response",
01072                                   G_CALLBACK(chooser_responder),
01073                                   &mStoreFilenames);
01074 
01075                 gtk_window_set_modal(GTK_WINDOW(win), TRUE);
01076 
01077                 /* GTK 2.6: if (is_folder)
01078                         gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(win),
01079                         TRUE); */
01080 
01081                 return GTK_WINDOW(win);
01082         }
01083         else
01084         {
01085                 return NULL;
01086         }
01087 }
01088 
01089 static void add_common_filters_to_gtkchooser(GtkFileFilter *gfilter,
01090                                              GtkWindow *picker,
01091                                              std::string filtername)
01092 {       
01093         gtk_file_filter_set_name(gfilter, filtername.c_str());
01094         gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
01095                                     gfilter);
01096         GtkFileFilter *allfilter = gtk_file_filter_new();
01097         gtk_file_filter_add_pattern(allfilter, "*");
01098         gtk_file_filter_set_name(allfilter, "All Files");
01099         gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter);
01100         gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter);
01101 }
01102 
01103 static std::string add_simple_pattern_filter_to_gtkchooser(GtkWindow *picker,
01104                                                            std::string pattern,
01105                                                            std::string filtername)
01106 {
01107         GtkFileFilter *gfilter = gtk_file_filter_new();
01108         gtk_file_filter_add_pattern(gfilter, pattern.c_str());
01109         add_common_filters_to_gtkchooser(gfilter, picker, filtername);
01110         return filtername;
01111 }
01112 
01113 static std::string add_simple_mime_filter_to_gtkchooser(GtkWindow *picker,
01114                                                         std::string mime,
01115                                                         std::string filtername)
01116 {
01117         GtkFileFilter *gfilter = gtk_file_filter_new();
01118         gtk_file_filter_add_mime_type(gfilter, mime.c_str());
01119         add_common_filters_to_gtkchooser(gfilter, picker, filtername);
01120         return filtername;
01121 }
01122 
01123 static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker)
01124 {
01125         return add_simple_mime_filter_to_gtkchooser(picker,  "audio/x-wav",
01126                                                     "Sounds (*.wav)");
01127 }
01128 
01129 static std::string add_bvh_filter_to_gtkchooser(GtkWindow *picker)
01130 {
01131         return add_simple_pattern_filter_to_gtkchooser(picker,  "*.bvh",
01132                                                        "Animations (*.bvh)");
01133 }
01134 
01135 static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
01136 {
01137         GtkFileFilter *gfilter = gtk_file_filter_new();
01138         gtk_file_filter_add_pattern(gfilter, "*.tga");
01139         gtk_file_filter_add_mime_type(gfilter, "image/jpeg");
01140         gtk_file_filter_add_mime_type(gfilter, "image/png");
01141         gtk_file_filter_add_mime_type(gfilter, "image/bmp");
01142         std::string filtername = "Images (*.tga; *.bmp; *.jpg; *.png)";
01143         add_common_filters_to_gtkchooser(gfilter, picker, filtername);
01144         return filtername;
01145 }
01146 
01147 
01148 BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename )
01149 {
01150         BOOL rtn = FALSE;
01151 
01152         gViewerWindow->mWindow->beforeDialog();
01153 
01154         reset();
01155         GtkWindow* picker = buildFilePicker(true, false, "savefile");
01156 
01157         if (picker)
01158         {
01159                 std::string suggest_name = "untitled";
01160                 std::string suggest_ext = "";
01161                 std::string caption = "Save ";
01162                 switch (filter)
01163                 {
01164                 case FFSAVE_WAV:
01165                         caption += add_wav_filter_to_gtkchooser(picker);
01166                         suggest_ext = ".wav";
01167                         break;
01168                 case FFSAVE_TGA:
01169                         caption += add_simple_pattern_filter_to_gtkchooser
01170                                 (picker, "*.tga", "Targa Images (*.tga)");
01171                         suggest_ext = ".tga";
01172                         break;
01173                 case FFSAVE_BMP:
01174                         caption += add_simple_mime_filter_to_gtkchooser
01175                                 (picker, "image/bmp", "Bitmap Images (*.bmp)");
01176                         suggest_ext = ".bmp";
01177                         break;
01178                 case FFSAVE_AVI:
01179                         caption += add_simple_mime_filter_to_gtkchooser
01180                                 (picker, "video/x-msvideo",
01181                                  "AVI Movie File (*.avi)");
01182                         suggest_ext = ".avi";
01183                         break;
01184                 case FFSAVE_ANIM:
01185                         caption += add_simple_pattern_filter_to_gtkchooser
01186                                 (picker, "*.xaf", "XAF Anim File (*.xaf)");
01187                         suggest_ext = ".xaf";
01188                         break;
01189                 case FFSAVE_XML:
01190                         caption += add_simple_pattern_filter_to_gtkchooser
01191                                 (picker, "*.xml", "XML File (*.xml)");
01192                         suggest_ext = ".xml";
01193                         break;
01194                 case FFSAVE_RAW:
01195                         caption += add_simple_pattern_filter_to_gtkchooser
01196                                 (picker, "*.raw", "RAW File (*.raw)");
01197                         suggest_ext = ".raw";
01198                         break;
01199                 case FFSAVE_J2C:
01200                         caption += add_simple_mime_filter_to_gtkchooser
01201                                 (picker, "images/jp2",
01202                                  "Compressed Images (*.j2c)");
01203                         suggest_ext = ".j2c";
01204                         break;
01205                 default:;
01206                         break;
01207                 }
01208                 
01209                 gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
01210 
01211                 if (!filename)
01212                 {
01213                         suggest_name += suggest_ext;
01214 
01215                         gtk_file_chooser_set_current_name
01216                                 (GTK_FILE_CHOOSER(picker),
01217                                  suggest_name.c_str());
01218                 }
01219                 else
01220                 {
01221                         gtk_file_chooser_set_current_name
01222                                 (GTK_FILE_CHOOSER(picker), filename);
01223                 }
01224 
01225                 gtk_widget_show_all(GTK_WIDGET(picker));
01226                 gtk_main();
01227 
01228                 rtn = (mStoreFilenames.fileVector.size() == 1);
01229         }
01230 
01231         gViewerWindow->mWindow->afterDialog();
01232 
01233         return rtn;
01234 }
01235 
01236 BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
01237 {
01238         BOOL rtn = FALSE;
01239 
01240         gViewerWindow->mWindow->beforeDialog();
01241 
01242         reset();
01243         GtkWindow* picker = buildFilePicker(false, false, "openfile");
01244 
01245         if (picker)
01246         {
01247                 std::string caption = "Load ";
01248                 std::string filtername = "";
01249                 switch (filter)
01250                 {
01251                 case FFLOAD_WAV:
01252                         filtername = add_wav_filter_to_gtkchooser(picker);
01253                         break;
01254                 case FFLOAD_ANIM:
01255                         filtername = add_bvh_filter_to_gtkchooser(picker);
01256                         break;
01257                 case FFLOAD_IMAGE:
01258                         filtername = add_imageload_filter_to_gtkchooser(picker);
01259                         break;
01260                 default:;
01261                         break;
01262                 }
01263 
01264                 caption += filtername;
01265                 
01266                 gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
01267 
01268                 gtk_widget_show_all(GTK_WIDGET(picker));
01269                 gtk_main();
01270 
01271                 rtn = (mStoreFilenames.fileVector.size() == 1);
01272         }
01273 
01274         gViewerWindow->mWindow->afterDialog();
01275 
01276         return rtn;
01277 }
01278 
01279 BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
01280 {
01281         BOOL rtn = FALSE;
01282 
01283         gViewerWindow->mWindow->beforeDialog();
01284 
01285         reset();
01286         GtkWindow* picker = buildFilePicker(false, false, "openfile");
01287 
01288         if (picker)
01289         {
01290                 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker),
01291                                                       TRUE);
01292 
01293                 gtk_window_set_title(GTK_WINDOW(picker), "Load Files");
01294 
01295                 gtk_widget_show_all(GTK_WIDGET(picker));
01296                 gtk_main();
01297                 rtn = !mStoreFilenames.fileVector.empty();
01298         }
01299 
01300         gViewerWindow->mWindow->afterDialog();
01301 
01302         return rtn;
01303 }
01304 
01305 const char* LLFilePicker::getFirstFile()
01306 {
01307         mNextFileIndex = 0;
01308         return getNextFile();
01309 }
01310 
01311 const char* LLFilePicker::getNextFile()
01312 {
01313         if (mStoreFilenames.fileVector.size() > mNextFileIndex)
01314                 return mStoreFilenames.fileVector[mNextFileIndex++].c_str();
01315         else
01316                 return NULL;
01317 }
01318 
01319 const char* LLFilePicker::getDirname()
01320 {
01321         // getDirname is badly named... it really means getBasename.
01322         S32 index = mNextFileIndex - 1; // want index before the 'next' cursor
01323         if (index >= 0 && index < (S32)mStoreFilenames.fileVector.size())
01324         {
01325                 // we do this using C strings so we don't have to
01326                 // convert a LLString/std::string character offset into a
01327                 // byte-offset for the return (which is a C string anyway).
01328                 const char* dirsep = gDirUtilp->getDirDelimiter().c_str();
01329                 const char* fullpath = mStoreFilenames.fileVector[index].c_str();
01330                 const char* finalpart = NULL;
01331                 const char* thispart = fullpath;
01332                 // (Hmm, is the strstr of dirsep UTF-8-correct?  Yes, reckon.)
01333                 // Walk through the string looking for the final dirsep, i.e. /
01334                 do
01335                 {
01336                         thispart = strstr(thispart, dirsep);
01337                         if (NULL != thispart)
01338                                 finalpart = thispart = &thispart[1];
01339                 }
01340                 while (NULL != thispart);
01341                 return finalpart;
01342         }
01343         else
01344                 return NULL;
01345 }
01346 
01347 void LLFilePicker::reset()
01348 {
01349         llinfos << "GTK LLFilePicker::reset()" << llendl;
01350         mNextFileIndex = 0;
01351         mStoreFilenames.win = NULL;
01352         mStoreFilenames.fileVector.clear();
01353 }
01354 
01355 # else // LL_GTK
01356 
01357 // Hacky stubs designed to facilitate fake getSaveFile and getOpenFile with
01358 // static results, when we don't have a real filepicker.
01359 
01360 static LLString hackyfilename;
01361 
01362 LLFilePicker::LLFilePicker() 
01363 {
01364         reset();
01365 }
01366 
01367 LLFilePicker::~LLFilePicker()
01368 {
01369 }
01370 
01371 BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename )
01372 {
01373         llinfos << "getSaveFile suggested filename is [" << filename
01374                 << "]" << llendl;
01375         if (filename && filename[0])
01376         {
01377                 hackyfilename.assign(gDirUtilp->getLindenUserDir());
01378                 hackyfilename += gDirUtilp->getDirDelimiter();
01379                 hackyfilename += filename;
01380                 return TRUE;
01381         }
01382         hackyfilename.clear();
01383         return FALSE;
01384 }
01385 
01386 BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
01387 {
01388         // HACK: Static filenames for 'open' until we implement filepicker
01389         hackyfilename.assign(gDirUtilp->getLindenUserDir());
01390         hackyfilename += gDirUtilp->getDirDelimiter();
01391         hackyfilename += "upload";
01392         switch (filter)
01393         {
01394         case FFLOAD_WAV: hackyfilename += ".wav"; break;
01395         case FFLOAD_IMAGE: hackyfilename += ".tga"; break;
01396         case FFLOAD_ANIM: hackyfilename += ".bvh"; break;
01397         default: break;
01398         }
01399         llinfos << "getOpenFile: Will try to open file: " << hackyfilename
01400                 << llendl;
01401         return TRUE;
01402 }
01403 
01404 BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
01405 {
01406         hackyfilename.clear();
01407         return FALSE;
01408 }
01409 
01410 const char* LLFilePicker::getFirstFile()
01411 {
01412         if (!hackyfilename.empty())
01413         {
01414                 return hackyfilename.c_str();
01415         }
01416         return NULL;
01417 }
01418 
01419 const char* LLFilePicker::getNextFile()
01420 {
01421         hackyfilename.clear();
01422         return NULL;
01423 }
01424 
01425 const char* LLFilePicker::getDirname()
01426 {
01427         return NULL;
01428 }
01429 
01430 void LLFilePicker::reset()
01431 {
01432 }
01433 #endif // LL_GTK
01434 
01435 #else // not implemented
01436 
01437 LLFilePicker::LLFilePicker() 
01438 {
01439         reset();
01440 }
01441 
01442 LLFilePicker::~LLFilePicker()
01443 {
01444 }
01445 
01446 BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename )
01447 {
01448         return FALSE;
01449 }
01450 
01451 BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
01452 {
01453         return FALSE;
01454 }
01455 
01456 BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
01457 {
01458         return FALSE;
01459 }
01460 
01461 const char* LLFilePicker::getFirstFile()
01462 {
01463         return NULL;
01464 }
01465 
01466 const char* LLFilePicker::getNextFile()
01467 {
01468         return NULL;
01469 }
01470 
01471 const char* LLFilePicker::getDirname()
01472 {
01473         return NULL;
01474 }
01475 
01476 void LLFilePicker::reset()
01477 {
01478 }
01479 
01480 #endif

Generated on Thu Jul 1 06:08:30 2010 for Second Life Viewer by  doxygen 1.4.7