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

Generated on Fri May 16 08:33:21 2008 for SecondLife by  doxygen 1.5.5