home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Snippets / GetFileIcon 1.1 / Old Headers / GetFileIcon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-15  |  13.2 KB  |  521 lines  |  [TEXT/KAHL]

  1. #include "GetFileIcon.h"
  2.  
  3.  
  4. #ifdef THINK_C
  5. #define LMGetFinderName() ((StringPtr)0x02E0)
  6. #endif
  7.  
  8. /*    ------------------------------------------------------------------
  9.     GetFileIcon        Given a file specification for a file, folder, or
  10.                     volume, create an appropriate icon suite
  11.                     and find its label color.
  12.     ------------------------------------------------------------------ */
  13. pascal OSErr GetFileIcon(
  14. /* --> */    FSSpec                *thing,
  15. /* --> */    IconSelectorValue    iconSelector,
  16. /* <-- */    Handle                *theSuite)
  17. {
  18.     CInfoPBRec        cpb;
  19.     OSErr            err;
  20.  
  21.  
  22.     *theSuite = NULL;
  23.  
  24.     if( IsVolEjected(thing->vRefNum) )
  25.     {
  26.         err = volOffLinErr;
  27.     }
  28.     else
  29.     {
  30.         cpb.hFileInfo.ioVRefNum        = thing->vRefNum;
  31.         cpb.hFileInfo.ioDirID        = thing->parID;
  32.         cpb.hFileInfo.ioNamePtr        = thing->name;
  33.         cpb.hFileInfo.ioFDirIndex    = 0;
  34.         err = PBGetCatInfoSync( &cpb );
  35.  
  36.         if( !err )
  37.         {
  38.             if( (cpb.hFileInfo.ioFlAttrib & ioDirMask) == 0)    // file
  39.             {
  40.                 if(cpb.hFileInfo.ioFlFndrInfo.fdFlags & kHasCustomIcon)
  41.                 {
  42.                     err = GetCustomFileIcon(thing, iconSelector, theSuite );
  43.                 }
  44.                 else    // no custom icon
  45.                 {
  46.                     err = GetNormalFileIcon(&cpb, iconSelector, theSuite);
  47.                 }
  48.             }
  49.             // ----------- end of normal case --------------
  50.         }    
  51.     }
  52.  
  53.     // ------- error handler ---------
  54.     /*if(thing->parID == fsRtParID)    // a volume
  55.     {
  56.         if(err == volOffLinErr)
  57.         {
  58.             *labelColor = ttOffline;
  59.         }
  60.         err = GetVolumeIcon(thing->vRefNum, iconSelector, theSuite);
  61.     }*/
  62.  
  63.     return( err );
  64. }
  65.  
  66.  
  67. Boolean    IsVolEjected( short vRefNum )
  68. {
  69.     OSErr            err;
  70.     HVolumeParam    vol_pb;
  71.     
  72.     vol_pb.ioNamePtr    = NULL;
  73.     vol_pb.ioVRefNum    = vRefNum;
  74.     vol_pb.ioVolIndex    = 0;
  75.     err = PBHGetVInfoSync( (HParmBlkPtr )&vol_pb );
  76.     
  77.     return( (err == noErr) && (vol_pb.ioVDRefNum > 0) );
  78. }
  79.  
  80.  
  81.  
  82. OSErr    GetCustomFileIcon(
  83. /* --> */    FSSpec                *filespec,
  84. /* --> */    IconSelectorValue    iconSelector,
  85. /* <-- */    Handle                *theSuite)
  86. {
  87.     short    saveResFile, customResFile;
  88.     OSErr    err;
  89.     
  90.     saveResFile = CurResFile();
  91.     SetResLoad( false );
  92.     customResFile = FSpOpenResFile(filespec, fsRdPerm);
  93.  
  94.     SetResLoad( true );
  95.  
  96.     if(customResFile == -1)
  97.     {
  98.         err = ResError();
  99.     }
  100.     else
  101.     {
  102.         err = GetResourceIcons(theSuite, kCustomIconResource, iconSelector);
  103.         if( !err )
  104.         {
  105.             if( IsSuiteEmpty( *theSuite ) )
  106.             {
  107.                 err = GetResourceIcons(theSuite, kVolumeAliasIconResource, iconSelector);
  108.             }
  109.         }
  110.  
  111.         CloseResFile( customResFile );
  112.         UseResFile( saveResFile );
  113.     }
  114.     return( err );
  115. }
  116.  
  117.  
  118. OSErr    GetNormalFileIcon(
  119. /* --> */    CInfoPBRec            *cpb,
  120. /* --> */    IconSelectorValue    iconSelector,
  121. /* <-- */    Handle                *theSuite)
  122. {
  123.     OSErr            err;
  124.     long            dataSize;
  125.     Handle            iconData;
  126.     Byte            iconType;
  127.     GetIconData        getData;
  128.     short            iconID;
  129.     Boolean            inFinder;
  130.     short            saveResFile, FinderResFile, sysVRefNum;
  131.     long            sysDirID;
  132.     Str255            finderName;
  133.  
  134.  
  135.     iconID = FindGenericIconID(cpb->hFileInfo.ioFlFndrInfo.fdType, &inFinder );
  136.     saveResFile = CurResFile();
  137.  
  138.     if( inFinder )
  139.     {
  140.         FindFolder(kOnSystemDisk, kSystemFolderType, kDontCreateFolder, &sysVRefNum, &sysDirID);
  141.  
  142.         SetResLoad( false );
  143.         GetFinderFilename( finderName );
  144.         FinderResFile = HOpenResFile(sysVRefNum, sysDirID, finderName, fsRdPerm);
  145.         SetResLoad( true );
  146.  
  147.         if(FinderResFile == -1)
  148.         {
  149.             err = ResError();
  150.         }
  151.         else
  152.         {
  153.             err = GetResourceIcons(theSuite, iconID, iconSelector);
  154.             CloseResFile( FinderResFile );
  155.         }
  156.     }
  157.     else    // icons in desktop DB or in System
  158.     {
  159.         getData.DTRefNum = FindDesktopDatabase(cpb->dirInfo.ioVRefNum,
  160.             cpb->hFileInfo.ioFlFndrInfo.fdCreator );
  161.  
  162.         if(getData.DTRefNum != 0)    // the right icons are in some desktop
  163.         {
  164.             err = NewIconSuite( theSuite );
  165.             if( !err )
  166.             {
  167.                 getData.fileCreator    = cpb->hFileInfo.ioFlFndrInfo.fdCreator;
  168.                 getData.fileType    = cpb->hFileInfo.ioFlFndrInfo.fdType;
  169.                 if(getData.fileType == kApplicationAliasType)
  170.                 {
  171.                     getData.fileType = 'APPL';
  172.                 }
  173.                 err = ForEachIconDo(*theSuite, iconSelector, GetIconProc, &getData);
  174.             }
  175.         }
  176.         if( (getData.DTRefNum == 0) || IsSuiteEmpty( *theSuite ) )
  177.         {
  178.             UseResFile( 0 );
  179.             err = GetResourceIcons(theSuite, iconID, iconSelector);
  180.         }
  181.     }
  182.  
  183.     UseResFile( saveResFile );
  184.  
  185.     return( err );
  186. }
  187.  
  188.  
  189. void GetFinderFilename(
  190. /* <-- */    StringPtr       _finderFilename)
  191. {
  192.     Str255          _defaultFinderFilename="\pFinder";
  193.     StringPtr       _lowMemFinderName;
  194.  
  195.     _lowMemFinderName = LMGetFinderName();
  196.     if( (_lowMemFinderName != (StringPtr )nil) && (_lowMemFinderName[0] > 0))
  197.         BlockMove(_lowMemFinderName, _finderFilename, _lowMemFinderName[0]+1);
  198.     else
  199.         BlockMove(_defaultFinderFilename, _finderFilename, _defaultFinderFilename[0]+1);
  200. }
  201.  
  202.  
  203. /*    ------------------------------------------------------------------
  204.     GetIcon        This is an IconAction procedure to fill in one
  205.                     slot of an icon suite, given a file type, creator,
  206.                     and desktop database.
  207.     ------------------------------------------------------------------ */
  208. //static    pascal OSErr GetIconProc(ResType theType, Handle *theIcon, void *yourDataPtr)
  209. pascal OSErr GetIconProc(ResType theType, Handle *theIcon, void *yourDataPtr)
  210. {
  211.     OSErr            err;
  212.     GetIconData        *data;
  213.     DTPBRec            deskRec;
  214.  
  215.     err = noErr;
  216.     data = (GetIconData *)yourDataPtr;
  217.     *theIcon = NewHandle( kLarge8BitIconSize );
  218.  
  219.     if( !(*theIcon) )
  220.     {
  221.         err = memFullErr;
  222.     }
  223.     else
  224.     {
  225.         HLock( *theIcon );
  226.     
  227.         deskRec.ioDTRefNum        = data->DTRefNum;
  228.         deskRec.ioDTBuffer        = **theIcon;
  229.         deskRec.ioDTReqCount    = kLarge8BitIconSize;
  230.         deskRec.ioFileCreator    = data->fileCreator;
  231.         deskRec.ioFileType        = data->fileType;
  232.     
  233.         switch( theType )
  234.         {
  235.             case large1BitMask:
  236.                 deskRec.ioIconType = kLargeIcon;
  237.                 break;
  238.     
  239.             case large4BitData:
  240.                 deskRec.ioIconType = kLarge4BitIcon;
  241.                 break;
  242.     
  243.             case large8BitData:
  244.                 deskRec.ioIconType = kLarge8BitIcon;
  245.                 break;
  246.     
  247.             case small1BitMask:
  248.                 deskRec.ioIconType = kSmallIcon;
  249.                 break;
  250.     
  251.             case small4BitData:
  252.                 deskRec.ioIconType = kSmall4BitIcon;
  253.                 break;
  254.     
  255.             case small8BitData:
  256.                 deskRec.ioIconType = kSmall8BitIcon;
  257.                 break;
  258.             
  259.             default:
  260.                 // The desktop database does not have "mini" icons
  261.                 deskRec.ioIconType = 1000;
  262.                 break;
  263.         }
  264.  
  265.         err = PBDTGetIconSync( &deskRec );
  266.         if(err == noErr)
  267.         {
  268.             HUnlock( *theIcon );
  269.             SetHandleSize(*theIcon, deskRec.ioDTActCount);
  270.         }
  271.         else
  272.         {
  273.             DisposeHandle( *theIcon );
  274.             *theIcon = NULL;
  275.             err = noErr;
  276.         }
  277.     }
  278.     return( err );
  279. }
  280.  
  281.  
  282. /*    ------------------------------------------------------------------
  283.     Find_desktop_database            Find the reference number of a
  284.                                     desktop database containing icons
  285.                                     for a specified creator code.
  286.     The search begins on a specified volume, but covers all volumes.
  287.     ------------------------------------------------------------------ */
  288. static    short    FindDesktopDatabase(
  289. /* --> */    short    firstVRefNum,
  290. /* --> */    OSType    fileCreator)    // returns a DT refnum or 0
  291. {
  292.     OSErr            err;
  293.     VolumeParam        vpb;
  294.     short            DTRefNum = 0;
  295.  
  296.     if( !InOneDesktop(firstVRefNum, fileCreator, &DTRefNum) )
  297.     {
  298.         vpb.ioNamePtr = NULL;
  299.         for(vpb.ioVolIndex = 1; PBGetVInfoSync((ParmBlkPtr )&vpb) == noErr; ++vpb.ioVolIndex)
  300.         {
  301.             if(vpb.ioVRefNum == firstVRefNum)
  302.                 continue;
  303.             if( InOneDesktop(vpb.ioVRefNum, fileCreator, &DTRefNum) )
  304.                 break;
  305.         }
  306.     }
  307.     return( DTRefNum );
  308. }
  309.  
  310.  
  311.  
  312. /*    ------------------------------------------------------------------
  313.     InOneDesktop            Determine whether the desktop database for
  314.                             one particular volume contains icons for
  315.                             a given creator code, and if so, return its
  316.                             reference number.
  317.     ------------------------------------------------------------------
  318. */
  319. static    Boolean    InOneDesktop(
  320. /* --> */    short    vRefNum,
  321. /* --> */    OSType    fileCreator,
  322. /* <-- */    short    *dtRefNum)
  323. {
  324.     OSErr        err;
  325.     DTPBRec        deskRec;
  326.     Boolean        retVal;
  327.     
  328.     HParamBlockRec         _myHPB;
  329.     GetVolParmsInfoBuffer  _infoBuffer;
  330.     
  331.     retVal = false;    // default to failure
  332.     deskRec.ioNamePtr = NULL;
  333.     deskRec.ioVRefNum = vRefNum;
  334.  
  335.     // check to make sure we've got a database first:
  336.     _myHPB.ioParam.ioNamePtr  = (StringPtr)nil;
  337.     _myHPB.ioParam.ioVRefNum  = vRefNum;
  338.     _myHPB.ioParam.ioBuffer   = (Ptr)&_infoBuffer;
  339.     _myHPB.ioParam.ioReqCount = sizeof(_infoBuffer);
  340.     if ( ((err=PBHGetVolParms(&_myHPB,false/*async*/))!=noErr) ||
  341.     ((_infoBuffer.vMAttrib&(1L<<bHasDesktopMgr))==0) )
  342.         return( retVal );
  343.  
  344.     err = PBDTGetPath( &deskRec );
  345.     if( !err )
  346.     {
  347.         /*    We want to ignore any non-icon data, such as the 'paul'
  348.             item that is used for drag-and-drop. */
  349.         deskRec.ioFileCreator = fileCreator;
  350.         deskRec.ioIndex = 1;
  351.         do
  352.         {
  353.             deskRec.ioTagInfo = 0;
  354.             err = PBDTGetIconInfoSync( &deskRec );
  355.             deskRec.ioIndex += 1;
  356.         }while( (err == noErr) && (deskRec.ioIconType <= 0) );
  357.     
  358.         if(err == noErr)
  359.         {
  360.             retVal = true;
  361.             *dtRefNum = deskRec.ioDTRefNum;
  362.         }
  363.     }
  364.     return( retVal );
  365. }
  366.  
  367.  
  368. pascal OSErr GetResourceIcons(
  369. /* <-- */    Handle    *theSuite,
  370. /* --> */    short    theID,
  371. /* --> */    long    theSelector)
  372. {
  373.     OSErr    err;
  374.     
  375.     err = Get1IconSuite(theSuite, theID, theSelector);
  376.     if(err == noErr)
  377.     {
  378.         err = CopyEachIcon( *theSuite );
  379.     }
  380.     return( err );
  381. }
  382.  
  383.  
  384. pascal OSErr CopyOneIcon(
  385. /* --> */    ResType        theType,
  386. /* <-> */    Handle        *theIcon,
  387. /* --- */    void        *yourDataPtr)
  388. {
  389.     OSErr    err;
  390.     
  391.     if(*theIcon != NULL)
  392.     {
  393.         LoadResource( *theIcon );
  394.         err = HandToHand( theIcon );
  395.         if(err != noErr)
  396.             *theIcon = NULL;
  397.     }
  398.     return( noErr );
  399. }
  400.  
  401.  
  402. OSErr CopyEachIcon(
  403. /* <-> */    Handle theSuite)
  404. {
  405.     return( ForEachIconDo(theSuite, svAllAvailableData, CopyOneIcon, NULL) );
  406. }
  407.  
  408.  
  409. typedef struct genericIconInfo { OSType type; short id; } GenericIconInfo;
  410. static GenericIconInfo gGenericFinderIcons[]={ {'ifil',12500},
  411.                                                {'ifil',12500},
  412.                                                {'sfil',14000},
  413.                                                {'ffil',14500},
  414.                                                {'tfil',14501},
  415.                                                {'kfil',14750},
  416.                                                {'FFIL',15500},
  417.                                                {'DFIL',15750}
  418.                                               };
  419. static GenericIconInfo gGenericSysIcons[]={ {kContainerFolderAliasType,genericFolderIconResource},
  420.                                             {kContainerTrashAliasType,trashIconResource},
  421.                                             {kSystemFolderAliasType,systemFolderIconResource},
  422.                                             {'INIT',genericExtensionIconResource},
  423.                                             {'APPL',genericApplicationIconResource},
  424.                                             {'dfil',genericDeskAccessoryIconResource},
  425.                                             {'pref',genericPreferencesIconResource},
  426.                                             {kAppleMenuFolderAliasType,appleMenuFolderIconResource},
  427.                                             {kControlPanelFolderAliasType,controlPanelFolderIconResource},
  428.                                             {kExtensionFolderAliasType,extensionsFolderIconResource},
  429.                                             {kPreferencesFolderAliasType,preferencesFolderIconResource},
  430.                                             {kStartupFolderAliasType,startupFolderIconResource},
  431.                                             {kApplicationAliasType,genericApplicationIconResource},
  432.                                             {kExportedFolderAliasType,ownedFolderIconResource},
  433.                                             {kDropFolderAliasType,dropFolderIconResource},
  434.                                             {kSharedFolderAliasType,sharedFolderIconResource},
  435.                                             {kMountedFolderAliasType,mountedFolderIconResource}
  436.                                            };
  437.  
  438.  
  439. static short FindGenericIconID(
  440. /* --> */    OSType theType,
  441. /* <-- */    Boolean    *inFinder)
  442. {
  443.     short            id = genericDocumentIconResource; // default
  444.     GenericIconInfo    *_icon, *_endIcon;
  445.  
  446.     for(_icon=gGenericFinderIcons,_endIcon=_icon+sizeof(gGenericFinderIcons)/sizeof(GenericIconInfo);
  447.         (_icon<_endIcon)&&(_icon->type!=theType); _icon++) ;
  448.     if( !(*inFinder=(_icon<_endIcon)) )
  449.     {
  450.         for(_icon=gGenericSysIcons,_endIcon=_icon + sizeof(gGenericSysIcons)/sizeof(GenericIconInfo);
  451.             (_icon<_endIcon) && (_icon->type!=theType); _icon++)    ;
  452.     }
  453.     if(_icon<_endIcon)
  454.         id = _icon->id;
  455.  
  456.     return( id );
  457. }
  458.  
  459.  
  460. /*    --------------------------------------------------------------------
  461.     Get1IconSuite            Like GetIconSuite, but only looks in
  462.                             the current resource file.
  463.     
  464.     In case you're wondering why it would be necessary to ensure that
  465.     icons come from only one file, suppose you're looking at a
  466.     file that has its custom icon bit set, but for some reason does
  467.     not contain a custom icon, or at least not a full family.
  468.     Way down the resource chain, there may be another file, say a
  469.     font file, that does have a full family of custom icons. 
  470.     So you get an unexpected icon.
  471.     -------------------------------------------------------------------- */
  472.  
  473. pascal OSErr Get1IconSuite(
  474. /* <-- */    Handle    *theSuite,
  475. /* --> */    short    theID,
  476. /* --> */    long    theSelector)
  477. {
  478.     OSErr        err;
  479.  
  480.     err = NewIconSuite( theSuite );
  481.     if( !err )
  482.     {
  483.         err = ForEachIconDo(*theSuite, theSelector,
  484.             (IconAction ) Get1Icon, &theID);
  485.     }
  486.     return( err );
  487. }
  488.  
  489.  
  490. pascal OSErr Get1Icon(
  491. /* --> */    ResType    theType,
  492. /* <-> */    Handle    *theIcon,
  493. /* --> */    short    *resID)
  494. {
  495.     *theIcon = Get1Resource(theType, *resID);
  496.  
  497.     return( noErr );
  498. }
  499.  
  500.  
  501. pascal OSErr TestHandle(ResType theType, Handle *theIcon, void *yourDataPtr)
  502. {
  503.     if(*theIcon != NULL)
  504.         *(Boolean *)yourDataPtr = false;    // not empty!
  505.  
  506.     return( noErr );
  507. }
  508.  
  509.  
  510. Boolean IsSuiteEmpty( Handle theSuite )
  511. {
  512.     Boolean        retVal;
  513.     
  514.     retVal = true;
  515.     ForEachIconDo(theSuite, svAllAvailableData, TestHandle, &retVal);
  516.  
  517.     return( retVal );
  518. }
  519.  
  520.  
  521.