1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxFileDialog  
   8 // Copyright:   (c) AUTHOR 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "filedlg.h" 
  19 #include "wx/dialog.h" 
  20 #include "wx/filedlg.h" 
  22 #include "wx/tokenzr.h" 
  25   #include "PLStringFuncs.h" 
  28 #if !USE_SHARED_LIBRARY 
  29 IMPLEMENT_CLASS(wxFileDialog
, wxDialog
) 
  34 #include "wx/mac/private.h" 
  36 #include <Navigation.h> 
  38 #include "MoreFiles.h" 
  39 #include "MoreFilesExtras.h" 
  41 extern bool gUseNavServices 
; 
  43 // the data we need to pass to our standard file hook routine 
  44 // includes a pointer to the dialog, a pointer to the standard 
  45 // file reply record (so we can inspect the current selection) 
  46 // and a copy of the "previous" file spec of the reply record 
  47 // so we can see if the selection has changed 
  49 const int kwxMacFileTypes 
= 10 ; 
  51 struct OpenUserDataRec 
{ 
  53   wxString      name 
[kwxMacFileTypes
] ; 
  54   wxString      extensions
[kwxMacFileTypes
] ; 
  55         OSType                          filtermactypes
[kwxMacFileTypes
] ; 
  58 typedef struct OpenUserDataRec
 
  59         OpenUserDataRec
, *OpenUserDataRecPtr
; 
  61 static pascal void      NavEventProc( 
  62                                                                 NavEventCallbackMessage         inSelector
, 
  64                                                                 NavCallBackUserData                     ioUserData
); 
  67                 static NavEventUPP      sStandardNavEventFilter 
= NewNavEventUPP(NavEventProc
); 
  69                 static NavEventUPP      sStandardNavEventFilter 
= NewNavEventProc(NavEventProc
); 
  74         NavEventCallbackMessage         inSelector
, 
  76         NavCallBackUserData     ioUserData      
) 
  78           OpenUserDataRec 
* data 
= ( OpenUserDataRec 
*) ioUserData 
; 
  79         if (inSelector 
== kNavCBEvent
) {         
  80                         // In Universal Headers 3.2, Apple changed the definition of 
  82                 #if UNIVERSAL_INTERFACES_VERSION >= 0x0320 // Universal Headers 3.2 
  83                         UModalAlerts::ProcessModalEvent(*(ioParams->eventData.eventDataParms.event)); 
  86                         UModalAlerts::ProcessModalEvent(*(ioParams->eventData.event)); 
  90          wxTheApp
->MacHandleOneEvent(ioParams
->eventData
.eventDataParms
.event
); 
  91         } else if ( inSelector 
== kNavCBPopupMenuSelect 
) 
  93           NavMenuItemSpec 
* menu 
= (NavMenuItemSpec 
*) ioParams
->eventData
.eventDataParms
.param 
; 
  94           data
->currentfilter 
= menu
->menuType 
; 
  98 const char * gfilters
[] = 
 107 OSType gfiltersmac
[] = 
 118 void MakeUserDataRec(OpenUserDataRec    
*myData 
, const wxString
& filter 
) 
 120   myData
->currentfilter 
= 0 ; 
 122         if ( filter 
&& filter
[0] ) 
 124           wxString 
filter2(filter
) ; 
 128     for( unsigned int i 
= 0; i 
< filter2
.Len(); i
++ ) 
 130        if( filter2
.GetChar(i
) == wxT('|') ) 
 133           myData
->name
[filterIndex
] = current 
; 
 136           myData
->extensions
[filterIndex
] = current
.MakeUpper() ; 
 144         current 
+= filter2
.GetChar(i
) ; 
 147 //    if ( filterIndex > 0 ) 
 149       wxASSERT_MSG( !isName 
, "incorrect format of format string" ) ; 
 150       myData
->extensions
[filterIndex
] = current
.MakeUpper() ; 
 154                 myData
->numfilters 
= filterIndex 
; 
 155                 for ( int i 
= 0 ; i 
< myData
->numfilters 
; i
++ ) 
 158                         for ( j 
= 0 ; gfilters
[j
] ; j
++ ) 
 160                                 if ( strcmp( myData
->extensions
[i
] , gfilters
[j
] ) == 0 ) 
 162                                         myData
->filtermactypes
[i
] = gfiltersmac
[j
] ; 
 166                         if( gfilters
[j
] == NULL 
) 
 168                                 myData
->filtermactypes
[i
] = '****' ; 
 174                 myData
->numfilters 
= 0 ; 
 179 static Boolean 
CheckFile( ConstStr255Param name 
, OSType type 
, OpenUserDataRecPtr data
) 
 184     p2cstrcpy((char *)filename
, name
) ; 
 186     PLstrcpy( filename 
, name 
) ; 
 189     wxString 
file(filename
) ; 
 192     if ( data
->numfilters 
> 0 ) 
 194         //for ( int i = 0 ; i < data->numfilters ; ++i ) 
 195             int i 
= data
->currentfilter 
; 
 196             if ( data
->extensions
[i
].Right(2) == ".*" ) 
 200               if ( type 
== data
->filtermactypes
[i
] ) 
 203               wxStringTokenizer 
tokenizer( data
->extensions
[i
] , ";" ) ; 
 204               while( tokenizer
.HasMoreTokens() ) 
 206                 wxString extension 
= tokenizer
.GetNextToken() ; 
 207               if ( extension
.GetChar(0) == '*' ) 
 208                       extension 
= extension
.Mid(1) ; 
 210               if ( file
.Len() >= extension
.Len() && extension 
== file
.Right(extension
.Len() ) ) 
 220 static pascal Boolean 
CrossPlatformFileFilter(CInfoPBPtr myCInfoPBPtr
, void *dataPtr
) 
 222         OpenUserDataRecPtr data 
= (OpenUserDataRecPtr
) dataPtr 
; 
 223         // return true if this item is invisible or a file 
 228         visibleFlag 
= ! (myCInfoPBPtr
->hFileInfo
.ioFlFndrInfo
.fdFlags 
& kIsInvisible
); 
 229         folderFlag 
= (myCInfoPBPtr
->hFileInfo
.ioFlAttrib 
& 0x10); 
 231         // because the semantics of the filter proc are "true means don't show 
 232         // it" we need to invert the result that we return 
 239                 return !CheckFile( myCInfoPBPtr
->hFileInfo
.ioNamePtr 
, myCInfoPBPtr
->hFileInfo
.ioFlFndrInfo
.fdType 
, data 
) ; 
 248 wxString 
wxFileSelector(const char *title
, 
 249                      const char *defaultDir
, const char *defaultFileName
, 
 250                      const char *defaultExtension
, const char *filter
, int flags
, 
 251                      wxWindow 
*parent
, int x
, int y
) 
 253     // If there's a default extension specified but no filter, we create a suitable 
 256     wxString 
filter2(""); 
 257     if ( defaultExtension 
&& !filter 
) 
 258         filter2 
= wxString("*.") + wxString(defaultExtension
) ; 
 262     wxString defaultDirString
; 
 264         defaultDirString 
= defaultDir
; 
 266         defaultDirString 
= ""; 
 268     wxString defaultFilenameString
; 
 270         defaultFilenameString 
= defaultFileName
; 
 272         defaultFilenameString 
= ""; 
 274     wxFileDialog 
fileDialog(parent
, title
, defaultDirString
, defaultFilenameString
, filter2
, flags
, wxPoint(x
, y
)); 
 276     if ( fileDialog
.ShowModal() == wxID_OK 
) 
 278         strcpy(wxBuffer
, (const char *)fileDialog
.GetPath()); 
 282         return wxGetEmptyString(); 
 285 WXDLLEXPORT wxString 
wxFileSelectorEx(const char *title
, 
 286                        const char *defaultDir
, 
 287                        const char *defaultFileName
, 
 288                        int* defaultFilterIndex
, 
 296     wxFileDialog 
fileDialog(parent
, title 
? title 
: "", defaultDir 
? defaultDir 
: "", 
 297         defaultFileName 
? defaultFileName 
: "", filter 
? filter 
: "", flags
, wxPoint(x
, y
)); 
 299     if ( fileDialog
.ShowModal() == wxID_OK 
) 
 301         *defaultFilterIndex 
= fileDialog
.GetFilterIndex(); 
 302         strcpy(wxBuffer
, (const char *)fileDialog
.GetPath()); 
 306         return wxGetEmptyString(); 
 309 wxFileDialog::wxFileDialog(wxWindow 
*parent
, const wxString
& message
, 
 310         const wxString
& defaultDir
, const wxString
& defaultFileName
, const wxString
& wildCard
, 
 311         long style
, const wxPoint
& pos
) 
 313           wxASSERT_MSG( NavServicesAvailable() , "Navigation Services are not running" ) ; 
 315     m_dialogStyle 
= style
; 
 318     m_fileName 
= defaultFileName
; 
 320     m_wildCard 
= wildCard
; 
 325 pascal Boolean 
CrossPlatformFilterCallback ( 
 329     NavFilterModes filterMode
 
 333         OpenUserDataRecPtr data 
= (OpenUserDataRecPtr
) callBackUD 
; 
 335         if (filterMode 
== kNavFilteringBrowserList
) 
 337           NavFileOrFolderInfo
* theInfo 
= (NavFileOrFolderInfo
*) info 
; 
 338                 if (theItem
->descriptorType 
== typeFSS 
&& !theInfo
->isFolder
) 
 341                   memcpy( &spec 
, *theItem
->dataHandle 
, sizeof(FSSpec
) ) ; 
 342                   display 
= CheckFile( spec
.name 
, theInfo
->fileAndFolder
.fileInfo
.finderInfo
.fdType 
, data 
) ; 
 349 int wxFileDialog::ShowModal() 
 351                 NavDialogOptions                mNavOptions
; 
 352                 NavObjectFilterUPP              mNavFilterUPP 
= NULL
; 
 353                 NavPreviewUPP                   mNavPreviewUPP 
= NULL 
; 
 354                 NavReplyRecord                  mNavReply
; 
 355                 AEDesc                                  mDefaultLocation 
; 
 356                 bool                                    mSelectDefault 
= false ; 
 358                 ::NavGetDefaultDialogOptions(&mNavOptions
); 
 361                 mNavPreviewUPP  
= nil
; 
 362                 mSelectDefault  
= false; 
 363                 mNavReply
.validRecord                           
= false; 
 364                 mNavReply
.replacing                                     
= false; 
 365                 mNavReply
.isStationery                          
= false; 
 366                 mNavReply
.translationNeeded                     
= false; 
 367                 mNavReply
.selection
.descriptorType 
= typeNull
; 
 368                 mNavReply
.selection
.dataHandle          
= nil
; 
 369                 mNavReply
.keyScript                                     
= smSystemScript
; 
 370                 mNavReply
.fileTranslation                       
= nil
; 
 372                 // Set default location, the location 
 373                 //   that's displayed when the dialog 
 377                 wxMacFilename2FSSpec( m_dir 
, &location 
) ; 
 380                 mDefaultLocation
.descriptorType 
= typeNull
; 
 381                 mDefaultLocation
.dataHandle     
= nil
; 
 383                 err 
= ::AECreateDesc(typeFSS
, &location
, sizeof(FSSpec
), &mDefaultLocation 
); 
 385                 if ( mDefaultLocation
.dataHandle 
) { 
 387                         if (mSelectDefault
) { 
 388                                 mNavOptions
.dialogOptionFlags 
|= kNavSelectDefaultLocation
; 
 390                                 mNavOptions
.dialogOptionFlags 
&= ~kNavSelectDefaultLocation
; 
 395                 c2pstrcpy((StringPtr
)mNavOptions
.message
, m_message
) ; 
 397                 strcpy((char *)mNavOptions
.message
, m_message
) ; 
 398                 c2pstr((char *)mNavOptions
.message 
) ; 
 401                 c2pstrcpy((StringPtr
)mNavOptions
.savedFileName
, m_fileName
) ; 
 403                 strcpy((char *)mNavOptions
.savedFileName
, m_fileName
) ; 
 404                 c2pstr((char *)mNavOptions
.savedFileName 
) ; 
 407                 if ( m_dialogStyle 
& wxSAVE 
) 
 410                         mNavOptions
.dialogOptionFlags 
|= kNavNoTypePopup 
; 
 411                         mNavOptions
.dialogOptionFlags 
|= kNavDontAutoTranslate 
; 
 412                         mNavOptions
.dialogOptionFlags 
|= kNavDontAddTranslateItems 
; 
 418                                                 sStandardNavEventFilter 
, 
 425                 OpenUserDataRec                 myData
; 
 426                 MakeUserDataRec( &myData 
, m_wildCard 
) ; 
 427                 NavTypeListHandle typelist 
= NULL 
; 
 429                 if ( myData
.numfilters 
> 0 ) 
 431                   mNavOptions
.popupExtension 
= (NavMenuItemSpecArrayHandle
) NewHandle( sizeof( NavMenuItemSpec 
) * myData
.numfilters 
) ; 
 432                   for ( int i 
= 0 ; i 
< myData
.numfilters 
; ++i 
) { 
 433                     (*mNavOptions
.popupExtension
)[i
].version 
= kNavMenuItemSpecVersion 
; 
 434                     (*mNavOptions
.popupExtension
)[i
].menuCreator 
= 'WXNG' ; 
 435                     (*mNavOptions
.popupExtension
)[i
].menuType 
= i 
; 
 437                         c2pstrcpy((StringPtr
)(*mNavOptions
.popupExtension
)[i
].menuItemName
, myData
.name
[i
]) ; 
 439                         strcpy((char *)(*mNavOptions
.popupExtension
)[i
].menuItemName
, myData
.name
[i
]) ; 
 440                         c2pstr((char *)(*mNavOptions
.popupExtension
)[i
].menuItemName 
) ; 
 445       mNavFilterUPP 
= NewNavObjectFilterUPP( CrossPlatformFilterCallback 
) ; 
 446                         if ( m_dialogStyle 
& wxMULTIPLE 
) 
 447                                 mNavOptions
.dialogOptionFlags 
|= kNavAllowMultipleFiles 
; 
 449                                 mNavOptions
.dialogOptionFlags 
&= ~kNavAllowMultipleFiles 
; 
 455                                                 sStandardNavEventFilter 
, 
 458                                                 typelist 
/*inFileTypes.TypeListHandle() */, 
 459                                                 &myData
);                                                       // User Data 
 461                           DisposeHandle( (Handle
) typelist 
) ; 
 464                 DisposeNavObjectFilterUPP(mNavFilterUPP
); 
 465                 if ( mDefaultLocation
.dataHandle 
!= nil 
) 
 467                         ::AEDisposeDesc(&mDefaultLocation
); 
 470                 if ( (err 
!= noErr
) && (err 
!= userCanceledErr
) ) { 
 475                 if (mNavReply
.validRecord
) { 
 482                         ::AECountItems( &mNavReply
.selection 
, &count 
) ; 
 483                         for ( long i 
= 1 ; i 
<= count 
; ++i 
) 
 485                                 OSErr err 
= ::AEGetNthDesc( &mNavReply
.selection 
, i 
, typeFSS
, &keyWord 
, &specDesc
); 
 486                                 if ( err 
!= noErr 
) { 
 490                                 outFileSpec 
= **(FSSpec
**) specDesc
.dataHandle
; 
 491                                 if (specDesc
.dataHandle 
!= nil
) { 
 492                                         ::AEDisposeDesc(&specDesc
); 
 496                                 // outFolderDirID = thePB.dirInfo.ioDrDirID; 
 497                                 m_path 
= wxMacFSSpec2MacFilename( &outFileSpec 
) ; 
 498                                 m_paths
.Add( m_path 
) ; 
 499                     m_fileNames
.Add(m_fileName
); 
 501                  // set these to the first hit 
 502                  m_path 
= m_paths
[ 0 ] ; 
 503                  m_fileName 
= wxFileNameFromPath(m_path
); 
 504                  m_dir 
= wxPathOnly(m_path
); 
 505        NavDisposeReply( &mNavReply 
) ; 
 511 // Generic file load/save dialog 
 513 wxDefaultFileSelector(bool load
, const char *what
, const char *extension
, const char *default_name
, wxWindow 
*parent
) 
 515   char *ext 
= (char *)extension
; 
 520     str 
= "Load %s file"; 
 522     str 
= "Save %s file"; 
 523   sprintf(prompt
, wxGetTranslation(str
), what
); 
 525   if (*ext 
== '.') ext
++; 
 527   sprintf(wild
, "*.%s", ext
); 
 529   return wxFileSelector (prompt
, NULL
, default_name
, ext
, wild
, 0, parent
); 
 532 // Generic file load dialog 
 534 wxLoadFileSelector(const char *what
, const char *extension
, const char *default_name
, wxWindow 
*parent
) 
 536   return wxDefaultFileSelector(TRUE
, what
, extension
, default_name
, parent
); 
 540 // Generic file save dialog 
 542 wxSaveFileSelector(const char *what
, const char *extension
, const char *default_name
, wxWindow 
*parent
) 
 544   return wxDefaultFileSelector(FALSE
, what
, extension
, default_name
, parent
);