May 94 Tips
Volume Number: | | 10
|
Issue Number: | | 5
|
Column Tag: | | Tips & Tidbits
|
Related Info: Font Manager Window Mgr
Tips & Tidbits
By Scott T Boyd, Editor
Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.
Tip Of The Month
Counting items in a directory
Heres a piece of code which counts the number of items in a directory. Its particularly useful if you are going to do something to every file in a directory (and its subdirectories) and want to show a progress bar. It counts both invisible and visible items, so if you dont want invisibles counted, youll need to modify it. The CountGlobals structure is used to minimize the amount of stack space used when recursively calling GetLevelCount and to hold global information that might be needed at any time.
- Jim Luther, Cupertino, CA
/* 1 */
struct CountGlobals
{
OSErr result; // temp holder of results - saves 2 bytes of stack at
each level
Str63 itemName;// the name of the current item
CInfoPBRec myCPB; // the parameter block used for PBGetCatInfo calls
unsigned long files;// the number of files in the directory structure
unsigned long directories; // the number of directories in the directory
structure
};
typedef struct CountGlobals CountGlobals;
typedef CountGlobals *CountGlobalsPtr;
// static prototypes
static void GetLevelCount(long currentDirID,
CountGlobalsPtr theGlobals);
void CountDirectoryItems(short srcVRefNum, long srcDirID,
unsigned long *files, unsigned long *directories);
static void GetLevelCount(long currentDirID,
CountGlobalsPtr theGlobals)
{
short index = 1;
do {
theGlobals->myCPB.dirInfo.ioFDirIndex = index;
// we need to do this every time through; GetCatInfo returns ioFlNum
in this field
theGlobals->myCPB.dirInfo.ioDrDirID = currentDirID;
theGlobals->result =
PBGetCatInfoSync((CInfoPBPtr)&theGlobals->myCPB);
if (theGlobals->result == noErr)
{
if ((theGlobals->myCPB.dirInfo.ioFlAttrib & ioDirMask) != 0)
{
// we have a directory
++(theGlobals->directories);
GetLevelCount( theGlobals->myCPB.dirInfo.ioDrDirID,
theGlobals); // recurse
theGlobals->result = noErr;// clear error return on way back
}
else
{
// we have a file
++(theGlobals->files);
}
}
++index;
} while (theGlobals->result == noErr);
}
void CountDirectoryItems(short srcVRefNum,
long srcDirID,
unsigned long *files,
unsigned long *directories)
{
CountGlobals theGlobals;
theGlobals.myCPB.dirInfo.ioNamePtr = theGlobals.itemName;
theGlobals.myCPB.dirInfo.ioVRefNum = srcVRefNum;
theGlobals.files = 0;
theGlobals.directories = 0;
GetLevelCount(srcDirID, &theGlobals);
*files = theGlobals.files;
*directories = theGlobals.directories;
}
Spread the word about things you know that others could benefit from knowing! Send
us your tips and tidbits, especially programming-related tips. Were also looking for user tips particularly useful to programmers .
MacTech Magazine will pay $25 for every tip used, and $50 for the Tip of the Month. You can take your award in orders or subscriptions if you prefer.
To submit a tip, send it in by e-mail. (Please make sure your code compiles). See page two for our addresses.
Popup Menus Pop Up Again
In the February issue, Laurent Haas suggested a method of forcing pop-up menus to appear in a certain font and size. His method involved forcing the system to use a new system font. I used to use this method as well, since it was the method suggested in an Apple DTS Q&A stack. Unfortunately, it has two drawbacks:
(1) It is very slow because the system has to rebuild the cached font info every time the font manager sees that LastSPExtra (the global variable at 0x0B4C) is -1. (That is why the -1 is being stuffed in there in the first place - otherwise the other changes are ignored because of the caching).
(2) It doesnt work - no kidding... if it works consistently on a particular machine, you are very lucky. Much of the time it simply does not have the desired effect - usually the font will change, but the size won't.
The method I use now is to patch _TextFont and _TextSize immediately before calling PopupMenuSelect and then unpatch them immediately afterwards (to minimize interference with anything else that uses these traps). My patches call the original routine but with a substituted argument for the font number or size. This works consistently and has no speed penalty to speak of. After unpatching, I also need to restore the font and size of the window manager port, since the menu defproc has explicitly set them by calling TextFont(0) and TextSize(0). Because of the patches, the WMgrPort now has a font and size different from the system font and size. I set the current port to the WMgrPort and do a TextFont and a TextSize to set them back to 0. On a colour Mac, this must also be done for the Colour Window manager port as well.
This method doesnt use any low memory globals, so is less likely to break. It does, however, require tweaking the window manager port(s), which could possibly break but I doubt it.
- Rowan Daniell, Software Engineer, Cowie Associates Ltd
Moving Targets In Mpw
With the advent of the Universal C interfaces it is a pain switching back and forth between the CIncludes and PPCCIncludes folders. Adding the following three lines to your UserStartUp-<yourname> script will make life easier:
/* 2 */
AddMenu Tools 'Use Universal CIncludes'
'SET CIncludes "{MPW}Interfaces:PPCCIncludes:"'
AddMenu Tools 'Use Standard CIncludes'
'SET CIncludes "{MPW}Interfaces:CIncludes:"'
AddMenu Tools (- ''
Any menu can be specified, but I chose to add these commands to the top of my Tools menu (which is also why I added a dividing line beneath the two items). Selecting an item causes the shell variable {CIncludes} to be set to the appropriate path. This can make life much easier when jumping between older projects and new, PowerPC-savvy projects.
- Bryan Pietrzak, Softdisk Publishing