]> git.saurik.com Git - wxWidgets.git/blob - src/mac/morefile/IterateD.cpp
#include textfile.h out of the WX_PRECOMP section (bcc)
[wxWidgets.git] / src / mac / morefile / IterateD.cpp
1 /*
2 ** IterateDirectory: File Manager directory iterator routines.
3 **
4 ** by Jim Luther
5 **
6 ** File: IterateDirectory.c
7 **
8 ** Copyright © 1995-1998 Jim Luther and Apple Computer, Inc.
9 ** All rights reserved.
10 **
11 ** You may incorporate this sample code into your applications without
12 ** restriction, though the sample code has been provided "AS IS" and the
13 ** responsibility for its operation is 100% yours.
14 **
15 ** IterateDirectory is designed to drop into the MoreFiles sample code
16 ** library I wrote while in Apple Developer Technical Support
17 */
18
19 #include <Types.h>
20 #include <Errors.h>
21 #include <Files.h>
22
23 #define __COMPILINGMOREFILES
24
25 #include "MoreExtr.h"
26 #include "IterateD.h"
27
28 /*
29 ** Type definitions
30 */
31
32 /* The IterateGlobals structure is used to minimize the amount of
33 ** stack space used when recursively calling IterateDirectoryLevel
34 ** and to hold global information that might be needed at any time.
35 */
36 #if PRAGMA_ALIGN_SUPPORTED
37 #pragma options align=mac68k
38 #endif
39 struct IterateGlobals
40 {
41 IterateFilterProcPtr iterateFilter; /* pointer to IterateFilterProc */
42 CInfoPBRec cPB; /* the parameter block used for PBGetCatInfo calls */
43 Str63 itemName; /* the name of the current item */
44 OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */
45 Boolean quitFlag; /* set to true if filter wants to kill interation */
46 unsigned short maxLevels; /* Maximum levels to iterate through */
47 unsigned short currentLevel; /* The current level IterateLevel is on */
48 void *yourDataPtr; /* A pointer to caller data the filter may need to access */
49 };
50 #if PRAGMA_ALIGN_SUPPORTED
51 #pragma options align=reset
52 #endif
53
54 typedef struct IterateGlobals IterateGlobals;
55 typedef IterateGlobals *IterateGlobalsPtr;
56
57 /*****************************************************************************/
58
59 /* Static Prototype */
60
61 static void IterateDirectoryLevel(long dirID,
62 IterateGlobals *theGlobals);
63
64 /*****************************************************************************/
65
66 /*
67 ** Functions
68 */
69
70 static void IterateDirectoryLevel(long dirID,
71 IterateGlobals *theGlobals)
72 {
73 if ( (theGlobals->maxLevels == 0) || /* if maxLevels is zero, we aren't checking levels */
74 (theGlobals->currentLevel < theGlobals->maxLevels) ) /* if currentLevel < maxLevels, look at this level */
75 {
76 short index = 1;
77
78 ++theGlobals->currentLevel; /* go to next level */
79
80 do
81 { /* Isn't C great... What I'd give for a "WITH theGlobals DO" about now... */
82
83 /* Get next source item at the current directory level */
84
85 theGlobals->cPB.dirInfo.ioFDirIndex = index;
86 theGlobals->cPB.dirInfo.ioDrDirID = dirID;
87 theGlobals->result = PBGetCatInfoSync((CInfoPBPtr)&theGlobals->cPB);
88
89 if ( theGlobals->result == noErr )
90 {
91 /* Call the IterateFilterProc */
92 CallIterateFilterProc(theGlobals->iterateFilter, &theGlobals->cPB, &theGlobals->quitFlag, theGlobals->yourDataPtr);
93
94 /* Is it a directory? */
95 if ( (theGlobals->cPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
96 {
97 /* We have a directory */
98 if ( !theGlobals->quitFlag )
99 {
100 /* Dive again if the IterateFilterProc didn't say "quit" */
101 IterateDirectoryLevel(theGlobals->cPB.dirInfo.ioDrDirID, theGlobals);
102 }
103 }
104 }
105
106 ++index; /* prepare to get next item */
107 } while ( (theGlobals->result == noErr) && (!theGlobals->quitFlag) ); /* time to fall back a level? */
108
109 if ( (theGlobals->result == fnfErr) || /* fnfErr is OK - it only means we hit the end of this level */
110 (theGlobals->result == afpAccessDenied) ) /* afpAccessDenied is OK, too - it only means we cannot see inside a directory */
111 {
112 theGlobals->result = noErr;
113 }
114
115 --theGlobals->currentLevel; /* return to previous level as we leave */
116 }
117 }
118
119 /*****************************************************************************/
120
121 pascal OSErr IterateDirectory(short vRefNum,
122 long dirID,
123 ConstStr255Param name,
124 unsigned short maxLevels,
125 IterateFilterProcPtr iterateFilter,
126 void *yourDataPtr)
127 {
128 IterateGlobals theGlobals;
129 OSErr result;
130 long theDirID;
131 short theVRefNum;
132 Boolean isDirectory;
133
134 /* Make sure there is a IterateFilter */
135 if ( iterateFilter != NULL )
136 {
137 /* Get the real directory ID and make sure it is a directory */
138 result = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory);
139 if ( result == noErr )
140 {
141 if ( isDirectory == true )
142 {
143 /* Get the real vRefNum */
144 result = DetermineVRefNum(name, vRefNum, &theVRefNum);
145 if ( result == noErr )
146 {
147 /* Set up the globals we need to access from the recursive routine. */
148 theGlobals.iterateFilter = iterateFilter;
149 theGlobals.cPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
150 theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum;
151 theGlobals.itemName[0] = 0;
152 theGlobals.result = noErr;
153 theGlobals.quitFlag = false;
154 theGlobals.maxLevels = maxLevels;
155 theGlobals.currentLevel = 0; /* start at level 0 */
156 theGlobals.yourDataPtr = yourDataPtr;
157
158 /* Here we go into recursion land... */
159 IterateDirectoryLevel(theDirID, &theGlobals);
160
161 result = theGlobals.result; /* set the result */
162 }
163 }
164 else
165 {
166 result = dirNFErr; /* a file was passed instead of a directory */
167 }
168 }
169 }
170 else
171 {
172 result = paramErr; /* iterateFilter was NULL */
173 }
174
175 return ( result );
176 }
177
178 /*****************************************************************************/
179
180 pascal OSErr FSpIterateDirectory(const FSSpec *spec,
181 unsigned short maxLevels,
182 IterateFilterProcPtr iterateFilter,
183 void *yourDataPtr)
184 {
185 return ( IterateDirectory(spec->vRefNum, spec->parID, spec->name,
186 maxLevels, iterateFilter, yourDataPtr) );
187 }
188
189 /*****************************************************************************/