]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/morefile/IterateDirectory.c
files of wxMac moved into carbon subdirs
[wxWidgets.git] / src / mac / carbon / morefile / IterateDirectory.c
diff --git a/src/mac/carbon/morefile/IterateDirectory.c b/src/mac/carbon/morefile/IterateDirectory.c
new file mode 100644 (file)
index 0000000..e748829
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+       File:           IterateDirectory.c
+
+       Contains:       File Manager directory iterator routines.
+
+       Version:        MoreFiles
+
+       Copyright:      © 1995-2001 by Jim Luther and Apple Computer, Inc., all rights reserved.
+
+       You may incorporate this sample code into your applications without
+       restriction, though the sample code has been provided "AS IS" and the
+       responsibility for its operation is 100% yours.  However, what you are
+       not permitted to do is to redistribute the source as "DSC Sample Code"
+       after having made changes. If you're going to re-distribute the source,
+       we require that you make it clear in the source that the code was
+       descended from Apple Sample Code, but that you've made changes.
+
+       File Ownership:
+
+               DRI:                            Apple Macintosh Developer Technical Support
+
+               Other Contact:          Apple Macintosh Developer Technical Support
+                                                       <http://developer.apple.com/bugreporter/>
+
+               Technology:                     DTS Sample Code
+
+       Writers:
+
+               (JL)    Jim Luther
+
+       Change History (most recent first):
+
+                <2>      2/7/01        JL              Added standard header. Updated names of includes.
+               <1>             12/06/99        JL              MoreFiles 1.5.
+*/
+
+#include <MacTypes.h>
+#include <MacErrors.h>
+#include <Files.h>
+
+#define        __COMPILINGMOREFILES
+
+#include "MoreFilesExtras.h"
+#include "IterateDirectory.h"
+
+/*
+**     Type definitions
+*/
+
+/* The IterateGlobals structure is used to minimize the amount of
+** stack space used when recursively calling IterateDirectoryLevel
+** and to hold global information that might be needed at any time.
+*/
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=mac68k
+#endif
+struct IterateGlobals
+{
+       IterateFilterProcPtr    iterateFilter;  /* pointer to IterateFilterProc */
+       CInfoPBRec                              cPB;                    /* the parameter block used for PBGetCatInfo calls */
+       Str63                                   itemName;               /* the name of the current item */
+       OSErr                                   result;                 /* temporary holder of results - saves 2 bytes of stack each level */
+       Boolean                                 quitFlag;               /* set to true if filter wants to kill interation */
+       unsigned short                  maxLevels;              /* Maximum levels to iterate through */
+       unsigned short                  currentLevel;   /* The current level IterateLevel is on */
+       void                                    *yourDataPtr;   /* A pointer to caller data the filter may need to access */
+};
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=reset
+#endif
+
+typedef struct IterateGlobals IterateGlobals;
+typedef IterateGlobals *IterateGlobalsPtr;
+
+/*****************************************************************************/
+
+/*     Static Prototype */
+
+static void    IterateDirectoryLevel(long dirID,
+                                                                         IterateGlobals *theGlobals);
+
+/*****************************************************************************/
+
+/*
+**     Functions
+*/
+
+static void    IterateDirectoryLevel(long dirID,
+                                                                         IterateGlobals *theGlobals)
+{
+       if ( (theGlobals->maxLevels == 0) ||                                            /* if maxLevels is zero, we aren't checking levels */
+                (theGlobals->currentLevel < theGlobals->maxLevels) )   /* if currentLevel < maxLevels, look at this level */
+       {
+               short index = 1;
+               
+               ++theGlobals->currentLevel;     /* go to next level */
+               
+               do
+               {       /* Isn't C great... What I'd give for a "WITH theGlobals DO" about now... */
+               
+                       /* Get next source item at the current directory level */
+                       
+                       theGlobals->cPB.dirInfo.ioFDirIndex = index;
+                       theGlobals->cPB.dirInfo.ioDrDirID = dirID;
+                       theGlobals->result = PBGetCatInfoSync((CInfoPBPtr)&theGlobals->cPB);            
+       
+                       if ( theGlobals->result == noErr )
+                       {
+                               /* Call the IterateFilterProc */
+                               CallIterateFilterProc(theGlobals->iterateFilter, &theGlobals->cPB, &theGlobals->quitFlag, theGlobals->yourDataPtr);
+                               
+                               /* Is it a directory? */
+                               if ( (theGlobals->cPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
+                               {
+                                       /* We have a directory */
+                                       if ( !theGlobals->quitFlag )
+                                       {
+                                               /* Dive again if the IterateFilterProc didn't say "quit" */
+                                               IterateDirectoryLevel(theGlobals->cPB.dirInfo.ioDrDirID, theGlobals);
+                                       }
+                               }
+                       }
+                       
+                       ++index; /* prepare to get next item */
+               } while ( (theGlobals->result == noErr) && (!theGlobals->quitFlag) ); /* time to fall back a level? */
+               
+               if ( (theGlobals->result == fnfErr) ||  /* fnfErr is OK - it only means we hit the end of this level */
+                        (theGlobals->result == afpAccessDenied) ) /* afpAccessDenied is OK, too - it only means we cannot see inside a directory */
+               {
+                       theGlobals->result = noErr;
+               }
+                       
+               --theGlobals->currentLevel;     /* return to previous level as we leave */
+       }
+}
+
+/*****************************************************************************/
+
+pascal OSErr   IterateDirectory(short vRefNum,
+                                                                long dirID,
+                                                                ConstStr255Param name,
+                                                                unsigned short maxLevels,
+                                                                IterateFilterProcPtr iterateFilter,
+                                                                void *yourDataPtr)
+{
+       IterateGlobals  theGlobals;
+       OSErr                   result;
+       long                    theDirID;
+       short                   theVRefNum;
+       Boolean                 isDirectory;
+       
+       /* Make sure there is a IterateFilter */
+       if ( iterateFilter != NULL )
+       {
+               /* Get the real directory ID and make sure it is a directory */
+               result = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory);
+               if ( result == noErr )
+               {
+                       if ( isDirectory == true )
+                       {
+                               /* Get the real vRefNum */
+                               result = DetermineVRefNum(name, vRefNum, &theVRefNum);
+                               if ( result == noErr )
+                               {
+                                       /* Set up the globals we need to access from the recursive routine. */
+                                       theGlobals.iterateFilter = iterateFilter;
+                                       theGlobals.cPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
+                                       theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum;
+                                       theGlobals.itemName[0] = 0;
+                                       theGlobals.result = noErr;
+                                       theGlobals.quitFlag = false;
+                                       theGlobals.maxLevels = maxLevels;
+                                       theGlobals.currentLevel = 0;    /* start at level 0 */
+                                       theGlobals.yourDataPtr = yourDataPtr;
+                               
+                                       /* Here we go into recursion land... */
+                                       IterateDirectoryLevel(theDirID, &theGlobals);
+                                       
+                                       result = theGlobals.result;     /* set the result */
+                               }
+                       }
+                       else
+                       {
+                               result = dirNFErr;      /* a file was passed instead of a directory */
+                       }
+               }
+       }
+       else
+       {
+               result = paramErr;      /* iterateFilter was NULL */
+       }
+       
+       return ( result );
+}
+
+/*****************************************************************************/
+
+pascal OSErr   FSpIterateDirectory(const FSSpec *spec,
+                                                                       unsigned short maxLevels,
+                                                                       IterateFilterProcPtr iterateFilter,
+                                                                       void *yourDataPtr)
+{
+       return ( IterateDirectory(spec->vRefNum, spec->parID, spec->name,
+                                               maxLevels, iterateFilter, yourDataPtr) );
+}
+
+/*****************************************************************************/