Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
GetIconSuiteFromFinder.c
/* |
File: FinderDragPro.c |
Description: Sample file illustrating drag and drop techniques for use |
with file system objects. This file illustrates how applications |
can use drag and drop commands in a way compatible with current |
and past versions of the Finder. |
Author: Pete Gontier |
Copyright: Copyright: © 1999 by Apple Computer, Inc. |
all rights reserved. |
Disclaimer: 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. |
Change History (most recent first): |
06/09/95 NG last touched |
08/23/96 PG stolen from Nitin's old FinderDrag project |
04/21/97 PG pascal programs can be written in any language |
*/ |
#ifndef __ICONS__ |
# include <Icons.h> |
#endif |
#ifndef __ALIASES__ |
# include <Aliases.h> |
#endif |
#ifndef __AEREGISTRY__ |
# include <AERegistry.h> |
#endif |
#ifndef __GESTALT__ |
# include <Gestalt.h> |
#endif |
#ifndef __AEPACKOBJECT__ |
# include <AEPackObject.h> |
#endif |
#ifndef __AEOBJECTS__ |
# include <AEObjects.h> |
#endif |
#ifndef __ERRORS__ |
# include <Errors.h> |
#endif |
#ifndef __TEXTUTILS__ |
# include <TextUtils.h> |
#endif |
#ifndef __PROCESSES__ |
# include <Processes.h> |
#endif |
#include "GetIconSuiteFromFinder.h" |
#define require(x,y) do { if (!(x)) goto y; } while (0) |
AEDesc pFinderTarget; |
//---------------------------------------------------------------------------- |
// FinderIsRunning |
// |
// Walk the Process Mgr list to check if the Finder is running |
//---------------------------------------------------------------------------- |
static Boolean FinderIsRunning (void) |
{ |
OSErr err; |
ProcessInfoRec pInfo; |
ProcessSerialNumber psn; |
Boolean foundIt; |
foundIt = false; |
psn.highLongOfPSN = 0; psn.lowLongOfPSN = kNoProcess; |
while ((foundIt == false) && (GetNextProcess(&psn) == noErr)) { |
pInfo.processName = NULL; |
pInfo.processAppSpec = NULL; |
pInfo.processInfoLength = sizeof(ProcessInfoRec); |
err = GetProcessInformation(&psn, &pInfo); |
if ((err == noErr) |
&& (pInfo.processSignature == 'MACS') |
&& (pInfo.processType == 'FNDR')) |
foundIt = true; |
} |
return foundIt; |
} |
//---------------------------------------------------------------------------- |
// HaveScriptableFinder |
// |
// We have it if the Gestalt bit is set and the Finder is running |
//---------------------------------------------------------------------------- |
static Boolean HaveScriptableFinder(void) |
{ |
long response; |
Boolean haveScriptableFinder; |
OSErr err; |
haveScriptableFinder = false; |
err = Gestalt(gestaltFinderAttr, &response); |
require(err == noErr, Gestalt); |
if ((response & (1 << gestaltOSLCompliantFinder)) && (FinderIsRunning())) |
haveScriptableFinder = true; |
Gestalt: |
return haveScriptableFinder; |
} |
//---------------------------------------------------------------------------- |
// SendAppleEvent |
//---------------------------------------------------------------------------- |
static OSErr SendAppleEvent(AppleEvent *ae, AppleEvent *reply, AESendMode sendMode) |
{ |
AppleEvent throwAwayReply; |
OSErr err; |
if (reply == NULL) { |
err = AESend(ae, &throwAwayReply, sendMode, |
kAENormalPriority, kAEDefaultTimeout, NULL, NULL); |
if (err == noErr) |
AEDisposeDesc(&throwAwayReply); |
} |
else |
err = AESend(ae, reply, sendMode, |
kAENormalPriority, kAEDefaultTimeout, NULL, NULL); |
return err; |
} |
//---------------------------------------------------------------------------- |
// MakeAppleEvent |
//---------------------------------------------------------------------------- |
static pascal OSErr MakeAppleEvent |
(AEEventClass aeClass, AEEventID aeID, AEDesc *target, AppleEvent *ae) |
{ |
OSErr err = noErr; |
if (target->dataHandle == nil) |
{ |
DescType finderSig = 'MACS'; |
err = AECreateDesc(typeApplSignature, (Ptr) &finderSig, |
sizeof(DescType), target); |
} |
if (!err) |
err = AECreateAppleEvent(aeClass, aeID, target, |
kAutoGenerateReturnID, kAnyTransactionID, ae); |
return err; |
} |
//---------------------------------------------------------------------------- |
// MakeSpecifierForSelection |
//---------------------------------------------------------------------------- |
static OSErr MakeSpecifierForSelection(AEDesc *selectionSpecifier) |
{ |
OSErr err; |
DescType descData; |
AEDesc keyData, nullDescriptor; |
nullDescriptor.descriptorType = typeNull; |
nullDescriptor.dataHandle = NULL; |
// |
// Make a descriptor whose type is 'typeType' and whose |
// contents are 'pSelection' (defined in FinderRegistry.h). |
// This descriptor specifies the property of the null container |
// that we are interested in--in this case, the selection. |
// |
descData = pSelection; |
err = AECreateDesc(typeType, (Ptr) &descData, sizeof(DescType), &keyData); |
require(err == noErr, AECreateDesc); |
err = CreateObjSpecifier(cProperty, &nullDescriptor, formPropertyID, |
&keyData, true, selectionSpecifier); |
AECreateDesc: |
return err; |
} |
//---------------------------------------------------------------------------- |
// MakeSpecifierForFile |
//---------------------------------------------------------------------------- |
static pascal OSErr MakeSpecifierForFile(FSSpecPtr hfsObj, AEDesc *fileSpecifier) |
{ |
OSErr err; |
AEDesc nullDesc, hfsData; |
AliasHandle fileAlias; |
// |
// Create the file descriptor with the FSSpec passed in. |
// |
err = NewAlias(NULL, hfsObj, &fileAlias); |
require(err == noErr, NewAlias); |
HLock((Handle) fileAlias); |
err = AECreateDesc(typeAlias, (Ptr) *fileAlias, |
GetHandleSize((Handle) fileAlias), &hfsData); |
HUnlock((Handle) fileAlias); |
DisposeHandle((Handle) fileAlias); |
require(err == noErr, AECreateDesc); |
// |
// Make the object specifier with a null container |
// (i.e., "file of <null>", or just "file") |
// |
nullDesc.descriptorType = typeNull; |
nullDesc.dataHandle = NULL; |
err = CreateObjSpecifier(typeWildCard, &nullDesc, |
formAlias, &hfsData, false, fileSpecifier); |
AECreateDesc: |
NewAlias: |
return err; |
} |
//---------------------------------------------------------------------------- |
// MakePropertySpecifierForSpecifier |
//---------------------------------------------------------------------------- |
static pascal OSErr MakePropertySpecifierForSpecifier |
(DescType property, AEDesc *ofSpecifier, AEDesc *propertySpecifier) |
{ |
OSErr err; |
AEDesc keyData; |
// |
// Create a 'type' AEDesc with the desired property |
// |
err = AECreateDesc(typeType, (Ptr) &property, sizeof(DescType), &keyData); |
require(err == noErr, AECreateDesc); |
// |
// With it create a property specifier for the object specifier |
// passed to us. |
// |
err = CreateObjSpecifier(cProperty, ofSpecifier, |
formPropertyID, &keyData, false, propertySpecifier); |
(void) AEDisposeDesc(&keyData); |
AECreateDesc: |
return err; |
} |
//---------------------------------------------------------------------------- |
// GetSizeFromIconType |
//---------------------------------------------------------------------------- |
static pascal Size GetSizeFromIconType (DescType iconType) |
{ |
Size size = -1; |
switch (iconType) { |
case large8BitData: |
size = kLarge8BitIconSize; |
break; |
case large4BitData: |
size = kLarge4BitIconSize; |
break; |
case large1BitMask: |
size = kLargeIconSize; |
break; |
case small8BitData: |
size = kSmall8BitIconSize; |
break; |
case small4BitData: |
size = kSmall4BitIconSize; |
break; |
case small1BitMask: |
size = kSmallIconSize; |
break; |
} |
return size; |
} |
//---------------------------------------------------------------------------- |
// BuildIconSuiteFromAEDesc |
// |
// OK, this uses the Apple Event Manager to pick the icon data out of the |
// 'ifam' AEDesc. |
//---------------------------------------------------------------------------- |
static pascal OSErr BuildIconSuiteFromAEDesc |
(Boolean largeIcons, Handle *iconSuite, AEDesc *iconFam) |
{ |
OSErr err; |
Handle suite, icon; |
AERecord rec; |
Ptr buffer; |
DescType large[3] = {large8BitData, large4BitData, large1BitMask}; |
DescType small[3] = {small8BitData, small4BitData, small1BitMask}; |
DescType *type, iconType, typeCode; |
long count; |
Size maxSize, size, iconSize; |
Boolean maskAdded; |
DescType maskType; |
maskAdded = false; |
suite = NULL; |
maxSize = kLarge8BitIconSize; |
if (largeIcons == true) { |
type = large; |
maskType = large1BitMask; |
} |
else { |
type = small; |
maskType = small1BitMask; |
} |
buffer = NewPtr(maxSize); |
require(buffer != NULL, NewPtr); |
err = NewIconSuite(&suite); |
require(err == noErr, NewIconSuite); |
err = AECoerceDesc(iconFam, typeAERecord, (AEDesc *) &rec); |
require(err == noErr, AECoerceDesc); |
for (count = 0; count < 3; count ++) { |
// |
// loop through the icons and grab the data from the AERecord for |
// each type of icon we're interested in. |
// |
iconType = type[count]; |
size = GetSizeFromIconType(iconType); |
err = AEGetKeyPtr(&rec, iconType, iconType, &typeCode, |
buffer, maxSize, &iconSize); |
if (err == noErr) { |
// |
// We don't set the error code for this unless the NewHandle |
// call fails, because it's possible that the 'ifam' doesn't |
// have an icon for one that we're interested in. |
// |
icon = NewHandle(size); |
if (icon != NULL) { |
// |
// OK, the memory alloc succeeded and we have data. Copy |
// it into the allocated icon and add it to the suite. |
// Set atLeastOne to true, to indicate later that we did |
// in fact add at least one icon to this suite. |
// |
BlockMoveData(buffer, *icon, size); |
err = AddIconToSuite(icon, suite, iconType); |
if ((err == noErr) && (iconType == maskType)) |
maskAdded = true; |
} |
else |
err = memFullErr; |
} |
} |
(void) AEDisposeDesc(&rec); |
AECoerceDesc: |
if ((err != noErr) || (maskAdded == false)) { |
// |
// There was either an error in a memory allocation, or something |
// else went wrong (like no mask was added to the suite). Get |
// rid of the partially created suite. |
// |
DisposeIconSuite(suite, true); |
suite = NULL; |
} |
NewIconSuite: |
DisposePtr(buffer); |
NewPtr: |
*iconSuite = suite; |
return err; |
} |
//---------------------------------------------------------------------------- |
// GetIconSuiteFromFinder |
// |
// Send a GetData AE for the 'ifam' |
//---------------------------------------------------------------------------- |
OSErr GetIconSuiteFromFinder (FSSpecPtr hfsObj, Handle *iconSuite) |
{ |
OSErr err; |
AppleEvent finderEvent, replyEvent; |
AEDesc fileSpecifier, iconPropertySpecifier; |
DescType returnType; |
Size returnSize; |
long returnLong; |
AEDesc iconFamily; |
// |
// Set up our locals for easy cleanup |
// |
*iconSuite = NULL; |
// |
// Make sure the Finder is scriptable and is running. |
// |
err = paramErr; |
require(HaveScriptableFinder() == true, HaveScriptableFinder); |
// |
// Make a GetData Apple event to send to the Finder |
// |
err = MakeAppleEvent(kAECoreSuite, kAEGetData, &pFinderTarget, |
&finderEvent); |
require(err == noErr, MakeAppleEvent); |
// |
// Make an object specifier for the interesting file |
// |
err = MakeSpecifierForFile(hfsObj, &fileSpecifier); |
require(err == noErr, MakeSpecifierForFile); |
// |
// Make an icon family property specifier for the file |
// |
err = MakePropertySpecifierForSpecifier(pIconBitmap, &fileSpecifier, |
&iconPropertySpecifier); |
require(err == noErr, MakePropertySpecifierForSpecifier); |
// |
// Stuff it in the Apple event and send it |
// |
err = AEPutParamDesc(&finderEvent, keyDirectObject, &iconPropertySpecifier); |
require(err == noErr, AEPutParamDesc); |
err = SendAppleEvent(&finderEvent, &replyEvent, |
kAEWaitReply + kAECanInteract + kAECanSwitchLayer); |
require(err == noErr, SendAppleEvent); |
// |
// Now the Finder may have sent us an error number |
// |
err = AEGetParamPtr(&replyEvent, keyErrorNumber, typeLongInteger, |
&returnType, &returnLong, sizeof(long), &returnSize); |
if (err == noErr) |
err = (OSErr) returnLong; |
else if (err == errAEDescNotFound) |
err = noErr; |
// |
// If not, get the icon family and build an icon suite |
// |
if (!err) |
{ |
err = AEGetParamDesc(&replyEvent, keyDirectObject, typeWildCard, &iconFamily); |
require(err == noErr, AEGetParamDesc); |
err = BuildIconSuiteFromAEDesc(true, iconSuite, &iconFamily); |
} |
// |
// Clean up and exit |
// |
(void) AEDisposeDesc(&iconFamily); |
AEGetParamDesc: |
(void) AEDisposeDesc(&replyEvent); |
SendAppleEvent: |
AEPutParamDesc: |
(void) AEDisposeDesc(&iconPropertySpecifier); |
MakePropertySpecifierForSpecifier: |
(void) AEDisposeDesc(&fileSpecifier); |
MakeSpecifierForFile: |
(void) AEDisposeDesc(&finderEvent); |
MakeAppleEvent: |
HaveScriptableFinder: |
return err; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14