X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5fde6fcc9b551340a194ae4c726db5ab64b5c594..1419ea47dd1a8e8e11ad254026141a8777038c41:/src/mac/carbon/dirdlg.cpp?ds=sidebyside

diff --git a/src/mac/carbon/dirdlg.cpp b/src/mac/carbon/dirdlg.cpp
index 89b3892451..079663908a 100644
--- a/src/mac/carbon/dirdlg.cpp
+++ b/src/mac/carbon/dirdlg.cpp
@@ -20,7 +20,9 @@
 
 #include "wx/cmndata.h"
 
-#if defined(__UNIX__)
+#include "wx/mac/private.h"
+
+#ifdef __DARWIN__
   #include <Carbon/Carbon.h>
 #else
   #include <Navigation.h>
@@ -30,423 +32,11 @@
 IMPLEMENT_CLASS(wxDirDialog, wxDialog)
 #endif
 
-bool gUseNavServices = NavServicesAvailable() ;
-
-// the data we need to pass to our standard file hook routine
-// includes a pointer to the dialog, a pointer to the standard
-// file reply record (so we can inspect the current selection)
-// and a copy of the "previous" file spec of the reply record
-// so we can see if the selection has changed
-
-#if !TARGET_CARBON
-
-struct UserDataRec {
-	StandardFileReply	*sfrPtr;
-	FSSpec				oldSelectionFSSpec;
-	DialogPtr			theDlgPtr;
-};
-typedef struct UserDataRec
-	UserDataRec, *UserDataRecPtr;
-
-enum {
-	kSelectItem = 10, 			// select button item number
-	kSFGetFolderDlgID = 250,	// dialog resource number
-	kStrListID = 250,			// our strings
-	kSelectStrNum = 1,			// word 'Select: ' for button
-	kDesktopStrNum = 2,			// word 'Desktop' for button
-	kSelectNoQuoteStrNum = 3,	// word 'Select: ' for button
-	
-	kUseQuotes = true,			// parameter for SetButtonName
-	kDontUseQuotes = false
-};
-
-
-static void GetLabelString(StringPtr theStr, short stringNum)
-{
-	GetIndString(theStr, kStrListID, stringNum);
-}
-
-static void CopyPStr(StringPtr src, StringPtr dest)
-{
-	BlockMoveData(src, dest, 1 + src[0]);
-}
-
-static char GetSelectKey(void)
-{
-	// this is the key used to trigger the select button
-	
-	// NOT INTERNATIONAL SAVVY; should at least grab it from resources
-	
-	return 's';
-}
-
-
-// SetButtonName sets the name of the Select button in the dialog
-//
-// To do this, we need to call the Script Manager to truncate the
-// label in the middle to fit the button and to merge the button
-// name with the word Select (possibly followed by quotes).  Using
-// the Script Manager avoids all sorts of problems internationally.
-//
-// buttonName is the name to appear following the word Select
-// quoteFlag should be true if the name is to appear in quotes
-
-static void SetButtonName(DialogPtr theDlgPtr, short buttonID, StringPtr buttonName,
-					Boolean quoteFlag)
-{
-	short 	buttonType;
-	Handle	buttonHandle;
-	Rect	buttonRect;
-	short	textWidth;
-	Handle	labelHandle;
-	Handle	nameHandle;
-	Str15	keyStr;
-	Str255	labelStr;
-	OSErr	err;
-	
-	nameHandle = nil;
-	labelHandle = nil;
-	
-	// get the details of the button from the dialog
-	
-	GetDialogItem(theDlgPtr, buttonID, &buttonType, &buttonHandle, &buttonRect);
-	
-	// get the string for the select button label, "Select ^0" or "Select Ò^0Ó"
-	
-	GetLabelString(labelStr, (quoteFlag == kUseQuotes) ? kSelectStrNum : kSelectNoQuoteStrNum);
-	
-	// make string handles containing the select button label and the
-	// file name to be stuffed into the button
-	
-	err = PtrToHand(&labelStr[1], &labelHandle, labelStr[0]);
-	if (err != noErr) goto Bail;
-	
-	// cut out the middle of the file name to fit the button
-	//
-	// we'll temporarily use labelStr here to hold the modified button name
-	// since we don't own the buttonName string storage space
-	
-	textWidth = (buttonRect.right - buttonRect.left) - StringWidth(labelStr);
-
-	CopyPStr(buttonName, labelStr);
-	(void) TruncString(textWidth, labelStr, smTruncMiddle);
-	
-	err = PtrToHand(&labelStr[1], &nameHandle, labelStr[0]);
-	if (err != noErr) goto Bail;
-	
-	// replace the ^0 in the Select string with the file name
-	
-	CopyPStr("\p^0", keyStr);
-	
-	(void) ReplaceText(labelHandle, nameHandle, keyStr);
-	
-	labelStr[0] = (unsigned char) GetHandleSize(labelHandle);
-	BlockMoveData(*labelHandle, &labelStr[1], labelStr[0]);
-	
-	// now set the control title, and re-validate the area
-	// above the control to avoid a needless redraw
-	
-	SetControlTitle((ControlHandle) buttonHandle, labelStr);
-	
-	ValidRect(&buttonRect);
-
-Bail:
-	if (nameHandle)		DisposeHandle(nameHandle);
-	if (labelHandle)	DisposeHandle(labelHandle);
-	
-}
-
-// FlashButton briefly highlights the dialog button 
-// as feedback for key equivalents
-
-static void FlashButton(DialogPtr theDlgPtr, short buttonID)
-{
-	short	buttonType;
-	Handle	buttonHandle;
-	Rect	buttonRect;
-	unsigned long	finalTicks;
-	
-	GetDialogItem(theDlgPtr, buttonID, &buttonType, &buttonHandle, &buttonRect);
-	HiliteControl((ControlHandle) buttonHandle, kControlButtonPart);
-	Delay(10, &finalTicks);
-	HiliteControl((ControlHandle) buttonHandle, 0);
-}
-
-static Boolean SameFSSpec(FSSpecPtr spec1, FSSpecPtr spec2)
-{
-	return (spec1->vRefNum == spec2->vRefNum
-			&& spec1->parID == spec2->parID
-			&& EqualString(spec1->name, spec2->name, false, false));
-}
-// MyModalDialogFilter maps a key to the Select button, and handles
-// flashing of the button when the key is hit
-
-static pascal Boolean SFGetFolderModalDialogFilter(DialogPtr theDlgPtr, EventRecord *eventRec,
-											short *item, void *dataPtr)
-{
-#pragma unused (dataPtr)
-
-	// make certain the proper dialog is showing, 'cause standard file
-	// can nest dialogs but calls the same filter for each
-	
-	if (((WindowPeek) theDlgPtr)->refCon == sfMainDialogRefCon)
-	{
-		// check if the select button was hit
-		
-		if ((eventRec->what == keyDown)
-			&& (eventRec->modifiers & cmdKey) 
-			&& ((eventRec->message & charCodeMask) == GetSelectKey()))
-		{
-			*item = kSelectItem;
-			FlashButton(theDlgPtr, kSelectItem);
-			return true;
-		}
-	}
-		
-	return false;
-}
-
-
-// MyDlgHook is a hook routine that maps the select button to Open
-// and sets the Select button name
-
-static pascal short SFGetFolderDialogHook(short item, DialogPtr theDlgPtr, void *dataPtr)
-{
-	UserDataRecPtr	theUserDataRecPtr;
-	long			desktopDirID;
-	short			desktopVRefNum;
-	FSSpec			tempSpec;
-	Str63			desktopName;
-	OSErr			err;
-	
-	// be sure Std File is really showing us the intended dialog,
-	// not a nested modal dialog
-	
-	if (((WindowPeek) theDlgPtr)->refCon != sfMainDialogRefCon)
-	{
-		return item;
-	}
-	
-	theUserDataRecPtr = (UserDataRecPtr) dataPtr;
-	
-	// map the Select button to Open
-	
-	if (item == kSelectItem)
-	{
-		item = sfItemOpenButton;
-	}
-	
-	// find the desktop folder
-	
-	err = FindFolder(theUserDataRecPtr->sfrPtr->sfFile.vRefNum,
-					kDesktopFolderType, kDontCreateFolder,
-					&desktopVRefNum, &desktopDirID);
-	
-	if (err != noErr)
-	{
-		// for errors, get value that won't match any real vRefNum/dirID
-		desktopVRefNum = 0;
-		desktopDirID = 0;
-	}
-	
-	// change the Select button label if the selection has changed or
-	// if this is the first call to the hook
-	
-	if (item == sfHookFirstCall
-		|| item == sfHookChangeSelection
-		|| item == sfHookRebuildList
-		|| ! SameFSSpec(&theUserDataRecPtr->sfrPtr->sfFile,
-					&theUserDataRecPtr->oldSelectionFSSpec))
-	{
-		// be sure there is a file name selected
-		
-		if (theUserDataRecPtr->sfrPtr->sfFile.name[0] != '\0')
-		{
-			SetButtonName(theDlgPtr, kSelectItem, 
-							theUserDataRecPtr->sfrPtr->sfFile.name, 
-							kUseQuotes);	// true -> use quotes
-		}
-		else
-		{
-			// is the desktop selected?
-			
-			if (theUserDataRecPtr->sfrPtr->sfFile.vRefNum == desktopVRefNum
-				&& theUserDataRecPtr->sfrPtr->sfFile.parID == desktopDirID)
-			{
-				// set button to "Select Desktop"
-				
-				GetLabelString(desktopName, kDesktopStrNum);
-				SetButtonName(theDlgPtr, kSelectItem, 
-								desktopName, kDontUseQuotes);	// false -> no quotes
-			}
-			else
-			{
-				// get parent directory's name for the Select button
-				//
-				// passing an empty name string to FSMakeFSSpec gets the
-				// name of the folder specified by the parID parameter
-				
-				(void) FSMakeFSSpec(theUserDataRecPtr->sfrPtr->sfFile.vRefNum,
-					theUserDataRecPtr->sfrPtr->sfFile.parID, "\p",
-					&tempSpec);
-				SetButtonName(theDlgPtr, kSelectItem, 
-							tempSpec.name, kUseQuotes); // true -> use quotes
-			}
-		}
-	}
-	
-	// save the current selection as the old selection for comparison next time
-	//
-	// it's not valid on the first call, though, or if we don't have a 
-	// name available from standard file
-	
-	if (item != sfHookFirstCall || theUserDataRecPtr->sfrPtr->sfFile.name[0] != '\0')
-	{
-		theUserDataRecPtr->oldSelectionFSSpec = theUserDataRecPtr->sfrPtr->sfFile;
-	}
-	else
-	{
-		// on first call, empty string won't set the button correctly, 
-		// so invalidate oldSelection
-		
-		theUserDataRecPtr->oldSelectionFSSpec.vRefNum = 999;
-		theUserDataRecPtr->oldSelectionFSSpec.parID = 0;
-	}
-	
-	return item;
-}
-
-void StandardGetFolder( ConstStr255Param message , ConstStr255Param path , FileFilterYDUPP fileFilter, StandardFileReply *theSFR)
-{
-	Point 				thePt;
-	SFTypeList			mySFTypeList;
-	UserDataRec			myData;
-	FSSpec				tempSpec;
-	Boolean				folderFlag;
-	Boolean				wasAliasedFlag;
-	DlgHookYDUPP		dlgHookUPP;
-	ModalFilterYDUPP	myModalFilterUPP;
-	OSErr				err;
-	
-	
-	// presumably we're running System 7 or later so CustomGetFile is
-	// available
-	
-	// set initial contents of Select button to a space
-	
-	memcpy(theSFR->sfFile.name, "\p ", 2);
-	
-	// point the user data parameter at the reply record so we can get to it later
-	
-	myData.sfrPtr = theSFR;
-	
-	// display the dialog
-	
-	#if !TARGET_CARBON
-	
-	dlgHookUPP = NewDlgHookYDProc(SFGetFolderDialogHook);
-	myModalFilterUPP = NewModalFilterYDProc(SFGetFolderModalDialogFilter);
-	
-	thePt.h = thePt.v = -1;	// center dialog
-	
-	ParamText( message , NULL , NULL , NULL ) ;
-	
-	CustomGetFile(	fileFilter, 
-					-1,					// show all types
-					mySFTypeList,
-					theSFR,
-					kSFGetFolderDlgID,
-					thePt,				// top left point
-					dlgHookUPP,
-					myModalFilterUPP,
-					nil,				// activate list
-					nil,				// activate proc
-					&myData);
-					
-	DisposeRoutineDescriptor(dlgHookUPP);
-	DisposeRoutineDescriptor(myModalFilterUPP);
-	#else
-	#endif
-	
-	// if cancel wasn't pressed and no fatal error occurred...
-	
-	if (theSFR->sfGood)
-	{
-		// if no name is in the reply record file spec,
-		// use the file spec of the parent folder
-		
-		if (theSFR->sfFile.name[0] == '\0')
-		{
-			err = FSMakeFSSpec(theSFR->sfFile.vRefNum, theSFR->sfFile.parID,
-								"\p", &tempSpec);
-			if (err == noErr)
-			{
-				theSFR->sfFile = tempSpec;
-			}
-			else
-			{
-				// no name to return, forget it
-				
-				theSFR->sfGood = false;
-			}
-		}
-		
-		// if there is now a name in the file spec, check if it's
-		// for a folder or a volume
-		
-		if (theSFR->sfFile.name[0] != '\0')
-		{
-			// the parID of the root of a disk is always fsRtParID == 1
-			
-			if (theSFR->sfFile.parID == fsRtParID)
-			{
-				theSFR->sfIsVolume = true;
-				theSFR->sfIsFolder = false;	// it would be reasonable for this to be true, too
-			}
-			
-			// we have a valid FSSpec, now let's make sure it's not for an alias file
-			
-			err = ResolveAliasFile(&theSFR->sfFile, true, &folderFlag, &wasAliasedFlag);
-			if (err != noErr)
-			{
-				theSFR->sfGood = false;
-			}
-			
-			// did the alias resolve to a folder?
-			
-			if (folderFlag  && ! theSFR->sfIsVolume)
-			{
-				theSFR->sfIsFolder = true;
-			}
-		}
-	}
-}
-
-static pascal Boolean OnlyVisibleFoldersCustomFileFilter(CInfoPBPtr myCInfoPBPtr, void *dataPtr)
-{
-#pragma unused (dataPtr)
-
-	// return true if this item is invisible or a file
-
-	Boolean visibleFlag;
-	Boolean folderFlag;
-	
-	visibleFlag = ! (myCInfoPBPtr->hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible);
-	folderFlag = (myCInfoPBPtr->hFileInfo.ioFlAttrib & 0x10);
-	
-	// because the semantics of the filter proc are "true means don't show
-	// it" we need to invert the result that we return
-	
-	return !(visibleFlag && folderFlag);
-}
-
-#endif
-
-
 wxDirDialog::wxDirDialog(wxWindow *parent, const wxString& message,
         const wxString& defaultPath,
         long style, const wxPoint& pos)
 {
+	wxASSERT_MSG( NavServicesAvailable() , "Navigation Services are not running" ) ;
     m_message = message;
     m_dialogStyle = style;
     m_parent = parent;
@@ -455,145 +45,98 @@ wxDirDialog::wxDirDialog(wxWindow *parent, const wxString& message,
 
 int wxDirDialog::ShowModal()
 {
-	#if !TARGET_CARBON
-	if ( !gUseNavServices )
-	{
-		Str255				prompt ;
-		Str255				path ;
-
-#if TARGET_CARBON
-		c2pstrcpy((StringPtr)prompt, m_message) ;
-#else
-		strcpy((char *)prompt, m_message) ;
-		c2pstr((char *)prompt ) ;
-#endif
-#if TARGET_CARBON
-		c2pstrcpy((StringPtr)path, m_path ) ;
-#else
-		strcpy((char *)path, m_path ) ;
-		c2pstr((char *)path ) ;
-#endif
-
-		StandardFileReply	reply ;
-		FileFilterYDUPP 	invisiblesExcludedCustomFilterUPP = 0 ;
-		invisiblesExcludedCustomFilterUPP = 
-			NewFileFilterYDProc(OnlyVisibleFoldersCustomFileFilter);
-
-
-		StandardGetFolder( prompt , path , invisiblesExcludedCustomFilterUPP, &reply);
+	NavDialogOptions		mNavOptions;
+	NavObjectFilterUPP		mNavFilterUPP = NULL;
+	NavPreviewUPP			mNavPreviewUPP = NULL ;
+	NavReplyRecord			mNavReply;
+	AEDesc*					mDefaultLocation = NULL ;
+	bool					mSelectDefault = false ;
+	
+	::NavGetDefaultDialogOptions(&mNavOptions);
+
+	mNavFilterUPP	= nil;
+	mNavPreviewUPP	= nil;
+	mSelectDefault	= false;
+	mNavReply.validRecord				= false;
+	mNavReply.replacing					= false;
+	mNavReply.isStationery				= false;
+	mNavReply.translationNeeded			= false;
+	mNavReply.selection.descriptorType = typeNull;
+	mNavReply.selection.dataHandle		= nil;
+	mNavReply.keyScript					= smSystemScript;
+	mNavReply.fileTranslation			= nil;
+	
+	// Set default location, the location
+	//   that's displayed when the dialog
+	//   first appears
+	
+	if ( mDefaultLocation ) {
+		
+		if (mSelectDefault) {
+			mNavOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
+		} else {
+			mNavOptions.dialogOptionFlags &= ~kNavSelectDefaultLocation;
+		}
+	}
 	
+	OSErr err = ::NavChooseFolder(
+						mDefaultLocation,
+						&mNavReply,
+						&mNavOptions,
+						NULL,
+						mNavFilterUPP,
+						0L);							// User Data
+	
+	if ( (err != noErr) && (err != userCanceledErr) ) {
+		m_path = "" ;
+		return wxID_CANCEL ;
+	}
 
-		DisposeRoutineDescriptor(invisiblesExcludedCustomFilterUPP);
-
-		if ( reply.sfGood == false )
-		{
+	if (mNavReply.validRecord) {		// User chose a folder
+	
+		FSSpec	folderInfo;
+		FSSpec  outFileSpec ;
+		AEDesc specDesc ;
+		
+		OSErr err = ::AECoerceDesc( &mNavReply.selection , typeFSS, &specDesc);
+		if ( err != noErr ) {
 			m_path = "" ;
 			return wxID_CANCEL ;
+		}			
+		folderInfo = **(FSSpec**) specDesc.dataHandle;
+		if (specDesc.dataHandle != nil) {
+			::AEDisposeDesc(&specDesc);
 		}
-		else
-		{
-			m_path = wxMacFSSpec2UnixFilename( &reply.sfFile ) ;
-			return wxID_OK ;
-		}
-		return wxID_CANCEL;
-	}
-	else
-	#endif
-	{
-		NavDialogOptions		mNavOptions;
-		NavObjectFilterUPP		mNavFilterUPP = NULL;
-		NavPreviewUPP			mNavPreviewUPP = NULL ;
-		NavReplyRecord			mNavReply;
-		AEDesc*					mDefaultLocation = NULL ;
-		bool					mSelectDefault = false ;
-		
-		::NavGetDefaultDialogOptions(&mNavOptions);
-	
-		mNavFilterUPP	= nil;
-		mNavPreviewUPP	= nil;
-		mSelectDefault	= false;
-		mNavReply.validRecord				= false;
-		mNavReply.replacing					= false;
-		mNavReply.isStationery				= false;
-		mNavReply.translationNeeded			= false;
-		mNavReply.selection.descriptorType = typeNull;
-		mNavReply.selection.dataHandle		= nil;
-		mNavReply.keyScript					= smSystemScript;
-		mNavReply.fileTranslation			= nil;
-		
-		// Set default location, the location
-		//   that's displayed when the dialog
-		//   first appears
+
+//			mNavReply.GetFileSpec(folderInfo);
 		
-		if ( mDefaultLocation ) {
-			
-			if (mSelectDefault) {
-				mNavOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
-			} else {
-				mNavOptions.dialogOptionFlags &= ~kNavSelectDefaultLocation;
-			}
-		}
+			// The FSSpec from NavChooseFolder is NOT the file spec
+			// for the folder. The parID field is actually the DirID
+			// of the folder itself, not the folder's parent, and
+			// the name field is empty. We must call PBGetCatInfo
+			// to get the parent DirID and folder name
 		
-		OSErr err = ::NavChooseFolder(
-							mDefaultLocation,
-							&mNavReply,
-							&mNavOptions,
-							NULL,
-							mNavFilterUPP,
-							0L);							// User Data
+		Str255		name;
+		CInfoPBRec	thePB;			// Directory Info Parameter Block
+		thePB.dirInfo.ioCompletion	= nil;
+		thePB.dirInfo.ioVRefNum		= folderInfo.vRefNum;	// Volume is right
+		thePB.dirInfo.ioDrDirID		= folderInfo.parID;		// Folder's DirID
+		thePB.dirInfo.ioNamePtr		= name;
+		thePB.dirInfo.ioFDirIndex	= -1;	// Lookup using Volume and DirID
 		
-		if ( (err != noErr) && (err != userCanceledErr) ) {
+		err = ::PBGetCatInfoSync(&thePB);
+		if ( err != noErr ) {
 			m_path = "" ;
 			return wxID_CANCEL ;
-		}
-
-		if (mNavReply.validRecord) {		// User chose a folder
-		
-			FSSpec	folderInfo;
-			FSSpec  outFileSpec ;
-			AEDesc specDesc ;
-			
-			OSErr err = ::AECoerceDesc( &mNavReply.selection , typeFSS, &specDesc);
-			if ( err != noErr ) {
-				m_path = "" ;
-				return wxID_CANCEL ;
-			}			
-			folderInfo = **(FSSpec**) specDesc.dataHandle;
-			if (specDesc.dataHandle != nil) {
-				::AEDisposeDesc(&specDesc);
-			}
-
-//			mNavReply.GetFileSpec(folderInfo);
-			
-				// The FSSpec from NavChooseFolder is NOT the file spec
-				// for the folder. The parID field is actually the DirID
-				// of the folder itself, not the folder's parent, and
-				// the name field is empty. We must call PBGetCatInfo
-				// to get the parent DirID and folder name
-			
-			Str255		name;
-			CInfoPBRec	thePB;			// Directory Info Parameter Block
-			thePB.dirInfo.ioCompletion	= nil;
-			thePB.dirInfo.ioVRefNum		= folderInfo.vRefNum;	// Volume is right
-			thePB.dirInfo.ioDrDirID		= folderInfo.parID;		// Folder's DirID
-			thePB.dirInfo.ioNamePtr		= name;
-			thePB.dirInfo.ioFDirIndex	= -1;	// Lookup using Volume and DirID
-			
-			err = ::PBGetCatInfoSync(&thePB);
-			if ( err != noErr ) {
-				m_path = "" ;
-				return wxID_CANCEL ;
-			}			
-												// Create cannonical FSSpec
-			::FSMakeFSSpec(thePB.dirInfo.ioVRefNum, thePB.dirInfo.ioDrParID,
-						   name, &outFileSpec);
-							
-			// outFolderDirID = thePB.dirInfo.ioDrDirID;
-			m_path = wxMacFSSpec2UnixFilename( &outFileSpec ) ;
-			return wxID_OK ;
-		}
-		return wxID_CANCEL;
-
+		}			
+											// Create cannonical FSSpec
+		::FSMakeFSSpec(thePB.dirInfo.ioVRefNum, thePB.dirInfo.ioDrParID,
+					   name, &outFileSpec);
+						
+		// outFolderDirID = thePB.dirInfo.ioDrDirID;
+		m_path = wxMacFSSpec2MacFilename( &outFileSpec ) ;
+		return wxID_OK ;
 	}
+	return wxID_CANCEL;
 }