1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxFileDialog  
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   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> 
  39 #  include "MoreFilesX.h" 
  41 #  include "MoreFiles.h" 
  42 #  include "MoreFilesExtras.h" 
  45 extern bool gUseNavServices 
; 
  47 // the data we need to pass to our standard file hook routine 
  48 // includes a pointer to the dialog, a pointer to the standard 
  49 // file reply record (so we can inspect the current selection) 
  50 // and a copy of the "previous" file spec of the reply record 
  51 // so we can see if the selection has changed 
  53 struct OpenUserDataRec 
{ 
  57   wxArrayString      extensions 
; 
  58   wxArrayLong        filtermactypes 
; 
  59   NavMenuItemSpecArrayHandle menuitems 
; 
  62 typedef struct OpenUserDataRec
 
  63     OpenUserDataRec
, *OpenUserDataRecPtr
; 
  65 static pascal void    NavEventProc( 
  66                                 NavEventCallbackMessage        inSelector
, 
  68                                 NavCallBackUserData            ioUserData
); 
  71         static NavEventUPP    sStandardNavEventFilter 
= NewNavEventUPP(NavEventProc
); 
  73         static NavEventUPP    sStandardNavEventFilter 
= NewNavEventProc(NavEventProc
); 
  78     NavEventCallbackMessage        inSelector
, 
  80     NavCallBackUserData    ioUserData    
) 
  82     OpenUserDataRec 
* data 
= ( OpenUserDataRec 
*) ioUserData 
; 
  83     if (inSelector 
== kNavCBEvent
) {     
  85          wxTheApp
->MacHandleOneEvent(ioParams
->eventData
.eventDataParms
.event
); 
  88     else if ( inSelector 
== kNavCBStart 
) 
  90         if ( data
->menuitems 
) 
  91             NavCustomControl(ioParams
->context
, kNavCtlSelectCustomType
, &(*data
->menuitems
)[data
->currentfilter
]); 
  93     else if ( inSelector 
== kNavCBPopupMenuSelect 
) 
  95         NavMenuItemSpec 
* menu 
= (NavMenuItemSpec 
*) ioParams
->eventData
.eventDataParms
.param 
; 
  96         if ( menu
->menuCreator 
== 'WXNG' ) 
  98             data
->currentfilter 
= menu
->menuType 
; 
 101                 int i 
= menu
->menuType 
; 
 102                 wxString extension 
=  data
->extensions
[i
].AfterLast('.') ; 
 103                 extension
.MakeLower() ; 
 105                 // get the current filename 
 106                 NavCustomControl(ioParams
->context
, kNavCtlGetEditFileName
, &filename
); 
 107                 wxString sfilename 
= wxMacMakeStringFromPascal( filename 
) ; 
 108                 int pos 
= sfilename
.Find('.',TRUE
) ; 
 109                 if ( pos 
!= wxNOT_FOUND 
) 
 111                     sfilename 
= sfilename
.Left(pos
+1)+extension 
; 
 112                     wxMacStringToPascal( sfilename 
, filename 
) ; 
 113                     NavCustomControl(ioParams
->context
, kNavCtlSetEditFileName
, &filename
); 
 120 const wxChar 
* gfilters
[] = 
 129 OSType gfiltersmac
[] = 
 140 void MakeUserDataRec(OpenUserDataRec    
*myData 
, const wxString
& filter 
) 
 142     myData
->menuitems 
= NULL 
; 
 143     myData
->currentfilter 
= 0 ; 
 144     myData
->saveMode 
= FALSE 
; 
 146     if ( filter 
&& filter
[0] ) 
 148         wxString 
filter2(filter
) ; 
 152         for( unsigned int i 
= 0; i 
< filter2
.Len() ; i
++ ) 
 154             if( filter2
.GetChar(i
) == wxT('|') ) 
 157                     myData
->name
.Add( current 
) ; 
 160                     myData
->extensions
.Add( current
.MakeUpper() ) ; 
 164                 current 
= wxEmptyString 
; 
 168                 current 
+= filter2
.GetChar(i
) ; 
 171         // we allow for compatibility reason to have a single filter expression (like *.*) without 
 172         // an explanatory text, in that case the first part is name and extension at the same time 
 174         wxASSERT_MSG( filterIndex 
== 0 || !isName 
, wxT("incorrect format of format string") ) ; 
 175         if ( current
.IsEmpty() ) 
 176             myData
->extensions
.Add( myData
->name
[filterIndex
] ) ; 
 178             myData
->extensions
.Add( current
.MakeUpper() ) ; 
 179         if ( filterIndex 
== 0 || isName 
) 
 180             myData
->name
.Add( current
.MakeUpper() ) ; 
 185         const size_t extCount 
= myData
->extensions
.GetCount(); 
 186         for ( size_t i 
= 0 ; i 
< extCount
; i
++ ) 
 189             for ( j 
= 0 ; gfilters
[j
] ; j
++ ) 
 191                 if ( myData
->extensions
[i
] == gfilters
[j
]  ) 
 193                     myData
->filtermactypes
.Add( gfiltersmac
[j
] ) ; 
 197             if( gfilters
[j
] == NULL 
) 
 199                 myData
->filtermactypes
.Add( '****' ) ; 
 205 static Boolean 
CheckFile( ConstStr255Param name 
, OSType type 
, OpenUserDataRecPtr data
) 
 211     p2cstrcpy((char *)filename, name) ; 
 213     PLstrcpy( filename , name ) ; 
 216     wxString file(filename) ; 
 218         wxString file 
= wxMacMakeStringFromPascal( name 
) ; 
 221     if ( data
->extensions
.GetCount() > 0 ) 
 223         //for ( int i = 0 ; i < data->numfilters ; ++i ) 
 224         int i 
= data
->currentfilter 
; 
 225         if ( data
->extensions
[i
].Right(2) == wxT(".*") ) 
 229             if ( type 
== (OSType
)data
->filtermactypes
[i
] ) 
 232             wxStringTokenizer 
tokenizer( data
->extensions
[i
] , wxT(";") ) ; 
 233             while( tokenizer
.HasMoreTokens() ) 
 235                 wxString extension 
= tokenizer
.GetNextToken() ; 
 236                 if ( extension
.GetChar(0) == '*' ) 
 237                     extension 
= extension
.Mid(1) ; 
 239                 if ( file
.Len() >= extension
.Len() && extension 
== file
.Right(extension
.Len() ) ) 
 249 static pascal Boolean 
CrossPlatformFileFilter(CInfoPBPtr myCInfoPBPtr
, void *dataPtr
) 
 251     OpenUserDataRecPtr data 
= (OpenUserDataRecPtr
) dataPtr 
; 
 252     // return true if this item is invisible or a file 
 257     visibleFlag 
= ! (myCInfoPBPtr
->hFileInfo
.ioFlFndrInfo
.fdFlags 
& kIsInvisible
); 
 258     folderFlag 
= (myCInfoPBPtr
->hFileInfo
.ioFlAttrib 
& 0x10); 
 260     // because the semantics of the filter proc are "true means don't show 
 261     // it" we need to invert the result that we return 
 268         return !CheckFile( myCInfoPBPtr
->hFileInfo
.ioNamePtr 
, myCInfoPBPtr
->hFileInfo
.ioFlFndrInfo
.fdType 
, data 
) ; 
 277 wxString 
wxFileSelector(const wxChar 
*title
, 
 278                      const wxChar 
*defaultDir
, const wxChar 
*defaultFileName
, 
 279                      const wxChar 
*defaultExtension
, const wxChar 
*filter
, int flags
, 
 280                      wxWindow 
*parent
, int x
, int y
) 
 282     // If there's a default extension specified but no filter, we create a suitable 
 286     if ( defaultExtension 
&& !filter 
) 
 287         filter2 
= wxString(wxT("*.")) + wxString(defaultExtension
) ; 
 291     wxString defaultDirString
; 
 293         defaultDirString 
= defaultDir
; 
 295         defaultDirString 
= wxEmptyString 
; 
 297     wxString defaultFilenameString
; 
 299         defaultFilenameString 
= defaultFileName
; 
 301         defaultFilenameString 
= wxEmptyString
; 
 303     wxFileDialog 
fileDialog(parent
, title
, defaultDirString
, defaultFilenameString
, filter2
, flags
, wxPoint(x
, y
)); 
 305     if ( fileDialog
.ShowModal() == wxID_OK 
) 
 307         return fileDialog
.GetPath(); 
 310         return wxGetEmptyString(); 
 313 WXDLLEXPORT wxString 
wxFileSelectorEx(const wxChar 
*title
, 
 314                        const wxChar 
*defaultDir
, 
 315                        const wxChar 
*defaultFileName
, 
 316                        int* defaultFilterIndex
, 
 317                        const wxChar 
*filter
, 
 324     wxFileDialog 
fileDialog(parent
, title 
? title 
: wxT(""), defaultDir 
? defaultDir 
: wxT(""), 
 325         defaultFileName 
? defaultFileName 
: wxT(""), filter 
? filter 
: wxT(""), flags
, wxPoint(x
, y
)); 
 327     if ( fileDialog
.ShowModal() == wxID_OK 
) 
 329         *defaultFilterIndex 
= fileDialog
.GetFilterIndex(); 
 330         return fileDialog
.GetPath(); 
 333         return wxGetEmptyString(); 
 336 wxFileDialog::wxFileDialog(wxWindow 
*parent
, const wxString
& message
, 
 337         const wxString
& defaultDir
, const wxString
& defaultFileName
, const wxString
& wildCard
, 
 338         long style
, const wxPoint
& pos
) 
 340     wxASSERT_MSG( NavServicesAvailable() , wxT("Navigation Services are not running") ) ; 
 342     m_dialogStyle 
= style
; 
 345     m_fileName 
= defaultFileName
; 
 347     m_wildCard 
= wildCard
; 
 351 pascal Boolean 
CrossPlatformFilterCallback ( 
 355     NavFilterModes filterMode
 
 359     OpenUserDataRecPtr data 
= (OpenUserDataRecPtr
) callBackUD 
; 
 361     if (filterMode 
== kNavFilteringBrowserList
) 
 363         NavFileOrFolderInfo
* theInfo 
= (NavFileOrFolderInfo
*) info 
; 
 364         if (theItem
->descriptorType 
== typeFSS 
&& !theInfo
->isFolder
) 
 367             memcpy( &spec 
, *theItem
->dataHandle 
, sizeof(FSSpec
) ) ; 
 368             display 
= CheckFile( spec
.name 
, theInfo
->fileAndFolder
.fileInfo
.finderInfo
.fdType 
, data 
) ; 
 375 int wxFileDialog::ShowModal() 
 377     NavDialogOptions           mNavOptions
; 
 378     NavObjectFilterUPP           mNavFilterUPP 
= NULL
; 
 379     NavPreviewUPP           mNavPreviewUPP 
= NULL 
; 
 380     NavReplyRecord           mNavReply
; 
 381     AEDesc               mDefaultLocation 
; 
 382     bool               mSelectDefault 
= false ; 
 386     ::NavGetDefaultDialogOptions(&mNavOptions
); 
 389     mNavPreviewUPP    
= nil
; 
 390     mSelectDefault    
= false; 
 391     mNavReply
.validRecord              
= false; 
 392     mNavReply
.replacing                   
= false; 
 393     mNavReply
.isStationery             
= false; 
 394     mNavReply
.translationNeeded           
= false; 
 395     mNavReply
.selection
.descriptorType 
= typeNull
; 
 396     mNavReply
.selection
.dataHandle     
= nil
; 
 397     mNavReply
.keyScript                   
= smSystemScript
; 
 398     mNavReply
.fileTranslation          
= nil
; 
 400     // Set default location, the location 
 401     //   that's displayed when the dialog 
 405     wxMacFilename2FSSpec( m_dir 
, &location 
) ; 
 408     mDefaultLocation
.descriptorType 
= typeNull
; 
 409     mDefaultLocation
.dataHandle     
= nil
; 
 411     err 
= ::AECreateDesc(typeFSS
, &location
, sizeof(FSSpec
), &mDefaultLocation 
); 
 413     if ( mDefaultLocation
.dataHandle 
) { 
 415         if (mSelectDefault
) { 
 416             mNavOptions
.dialogOptionFlags 
|= kNavSelectDefaultLocation
; 
 418             mNavOptions
.dialogOptionFlags 
&= ~kNavSelectDefaultLocation
; 
 421     wxMacStringToPascal( m_message 
, (StringPtr
)mNavOptions
.message 
) ; 
 422     wxMacStringToPascal( m_fileName 
, (StringPtr
)mNavOptions
.savedFileName 
) ; 
 426     m_path 
= wxEmptyString 
; 
 427     m_fileName 
= wxEmptyString 
; 
 431     OpenUserDataRec            myData
; 
 432     MakeUserDataRec( &myData 
, m_wildCard 
) ; 
 433     myData
.currentfilter 
= m_filterIndex 
; 
 434     if ( myData
.extensions
.GetCount() > 0 ) 
 436         mNavOptions
.popupExtension 
= (NavMenuItemSpecArrayHandle
) NewHandle( sizeof( NavMenuItemSpec 
) * myData
.extensions
.GetCount() ) ; 
 437         myData
.menuitems 
= mNavOptions
.popupExtension 
; 
 438         for ( size_t i 
= 0 ; i 
< myData
.extensions
.GetCount() ; ++i 
)  
 440             (*mNavOptions
.popupExtension
)[i
].version     
= kNavMenuItemSpecVersion 
; 
 441             (*mNavOptions
.popupExtension
)[i
].menuCreator 
= 'WXNG' ; 
 442             (*mNavOptions
.popupExtension
)[i
].menuType    
= i 
; 
 443             wxMacStringToPascal( myData
.name
[i
] , (StringPtr
)(*mNavOptions
.popupExtension
)[i
].menuItemName 
) ; 
 446     if ( m_dialogStyle 
& wxSAVE 
) 
 448         myData
.saveMode 
= true ; 
 450         mNavOptions
.dialogOptionFlags 
|= kNavDontAutoTranslate 
; 
 451         mNavOptions
.dialogOptionFlags 
|= kNavDontAddTranslateItems 
; 
 457                            sStandardNavEventFilter 
, 
 459                            kNavGenericSignature
, 
 460                            &myData
);                    // User Data 
 461         m_filterIndex 
= myData
.currentfilter 
; 
 465         myData
.saveMode 
= false ; 
 467         mNavFilterUPP 
= NewNavObjectFilterUPP( CrossPlatformFilterCallback 
) ; 
 468         if ( m_dialogStyle 
& wxMULTIPLE 
) 
 469             mNavOptions
.dialogOptionFlags 
|= kNavAllowMultipleFiles 
; 
 471             mNavOptions
.dialogOptionFlags 
&= ~kNavAllowMultipleFiles 
; 
 477                            sStandardNavEventFilter 
, 
 482         m_filterIndex 
= myData
.currentfilter 
; 
 485     DisposeNavObjectFilterUPP(mNavFilterUPP
); 
 486     if ( mDefaultLocation
.dataHandle 
!= nil 
) 
 488         ::AEDisposeDesc(&mDefaultLocation
); 
 491     if ( (err 
!= noErr
) && (err 
!= userCanceledErr
) ) { 
 495     if (mNavReply
.validRecord
) { 
 502         ::AECountItems( &mNavReply
.selection 
, &count 
) ; 
 503         for ( long i 
= 1 ; i 
<= count 
; ++i 
) 
 505             OSErr err 
= ::AEGetNthDesc( &mNavReply
.selection 
, i 
, typeFSS
, &keyWord 
, &specDesc
); 
 506             if ( err 
!= noErr 
) { 
 510             outFileSpec 
= **(FSSpec
**) specDesc
.dataHandle
; 
 511             if (specDesc
.dataHandle 
!= nil
) { 
 512                 ::AEDisposeDesc(&specDesc
); 
 514             m_path 
= wxMacFSSpec2MacFilename( &outFileSpec 
) ; 
 515             m_paths
.Add( m_path 
) ; 
 516             m_fileName 
= wxFileNameFromPath(m_path
); 
 517             m_fileNames
.Add(m_fileName
); 
 519         // set these to the first hit 
 520         m_path 
= m_paths
[ 0 ] ; 
 521         m_fileName 
= wxFileNameFromPath(m_path
); 
 522         m_dir 
= wxPathOnly(m_path
); 
 523         NavDisposeReply( &mNavReply 
) ; 
 529 // Generic file load/save dialog 
 531 wxDefaultFileSelector(bool load
, const wxChar 
*what
, const wxChar 
*extension
, const wxChar 
*default_name
, wxWindow 
*parent
) 
 537         str 
= wxT("Load %s file"); 
 539         str 
= wxT("Save %s file"); 
 540     prompt
.Printf( wxGetTranslation(str
), what
); 
 542     const wxChar 
*ext 
= extension
; 
 543     if (*ext 
== wxT('.')) 
 547     wild
.Printf(wxT("*.%s"), ext
); 
 549     return wxFileSelector (prompt
, NULL
, default_name
, ext
, wild
, 0, parent
); 
 552 // Generic file load dialog 
 554 wxLoadFileSelector(const wxChar 
*what
, const wxChar 
*extension
, const wxChar 
*default_name
, wxWindow 
*parent
) 
 556     return wxDefaultFileSelector(TRUE
, what
, extension
, default_name
, parent
); 
 560 // Generic file save dialog 
 562 wxSaveFileSelector(const wxChar 
*what
, const wxChar 
*extension
, const wxChar 
*default_name
, wxWindow 
*parent
) 
 564     return wxDefaultFileSelector(FALSE
, what
, extension
, default_name
, parent
);