Back to index

lightning-sunbird  0.9+nobinonly
PatchableAppleSingle.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code, released
00016  * March 31, 1998.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Douglas Turner <dougt@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 #include "PatchableAppleSingle.h"
00040 
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <string.h>
00044 
00045 OSErr PAS_EncodeFile(FSSpec *inSpec, FSSpec *outSpec);
00046 OSErr PAS_DecodeFile(FSSpec *inSpec, FSSpec *outSpec);
00047 
00048 OSErr PAS_encodeResource(FSSpec *inFile, short outRefNum);
00049 OSErr PAS_decodeResource(PASEntry *entry, FSSpec *outFile, short inRefNum);
00050 
00051 OSErr PAS_encodeMisc(FSSpec *inFile, short outRefNum);
00052 OSErr PAS_decodeMisc(PASEntry *entry, FSSpec *outFile, short inRefNum);
00053 
00054 OSErr PAS_encodeData(FSSpec *inFile, short outRefNum);
00055 OSErr PAS_decodeData(PASEntry *entry, FSSpec *outFile, short inRefNum);
00056 
00057 OSErr PAS_encodeHeader(short refnum);
00058 OSErr PAS_decodeHeader(short refNum, PASHeader *header);
00059 
00060 
00061 unsigned long PAS_getDataSize(FSSpec *spec);
00062 short PAS_getResourceID(Handle resource);
00063 
00064 OSErr PAS_flattenResource(ResType type, short *ids, long count, short source, short dest);
00065 OSErr PAS_unflattenResource(PASResource *pasRes, Ptr buffer);
00066 
00067 void PAS_sortTypes(short sourceRefNum, ResType **resTypePtr, long *count);
00068 void PAS_sortIDs(short sourceRefNum, OSType theType, short **IdPtr, long *count);
00069 void PAS_bubbleSortResType(ResType *types, long count);
00070 void PAS_bubbleSortIDS(short *ids, long count);
00071 
00072 OSErr PAS_EncodeFile(FSSpec *inSpec, FSSpec *outSpec)
00073 {
00074        OSErr         err;
00075        short         outRefNum;
00076        
00077        PASEntry      dataEntry, miscEntry, resourceEntry;
00078        long          sizeOfEntry;
00079 
00080 
00081        if (inSpec == NULL || outSpec == NULL)
00082               return paramErr;
00083               
00084 
00085        memset(&dataEntry, 0, sizeof(PASEntry));
00086        memset(&miscEntry, 0, sizeof(PASEntry));
00087        memset(&resourceEntry, 0, sizeof(PASEntry));
00088        
00089        FSpDelete( outSpec ) ;
00090        
00091        err = FSpCreate( outSpec, kCreator, kType ,smSystemScript );
00092        
00093        if (err != noErr)    return err;
00094        
00095        
00096        err = FSpOpenDF(outSpec, fsRdWrPerm, &outRefNum);
00097        
00098        if (err != noErr)  goto error;
00099        
00100 
00101        // Write Out Header
00102               
00103        err = PAS_encodeHeader(outRefNum);
00104        if (err != noErr)  goto error;
00105        
00106        /* Why am I using three (3)?
00107               
00108               E stand for entry.
00109               
00110           The data for the entry is after the THREE headers 
00111        
00112               |---------|----|----|----|---------------------->
00113                  header    E    E    E
00114        
00115        */
00116        
00117        
00118        // Write Out Data Entry 
00119        dataEntry.entryID           =      ePas_Data;
00120        dataEntry.entryLength       =      PAS_getDataSize(inSpec);
00121        dataEntry.entryOffset       =      sizeof(PASHeader) + (3 * sizeof(PASEntry));
00122        
00123        sizeOfEntry                 =      sizeof(PASEntry);
00124        if(dataEntry.entryLength < 0)
00125        {
00126               err    = dataEntry.entryLength;
00127               goto error;
00128        }
00129        
00130        err = FSWrite(outRefNum, &sizeOfEntry, &dataEntry);
00131        if (err != noErr)    goto error;
00132        
00133        
00134        
00135        // Write Out Misc Entry 
00136        miscEntry.entryID           =      ePas_Misc;
00137        miscEntry.entryLength       =      sizeof(PASMiscInfo);
00138        miscEntry.entryOffset       =      sizeof(PASHeader) + (3 * sizeof(PASEntry)) + dataEntry.entryLength;
00139 
00140        sizeOfEntry                 =      sizeof(PASEntry);
00141        err = FSWrite(outRefNum, &sizeOfEntry, &miscEntry);
00142        if (err != noErr)    goto error;
00143        
00144        
00145        // Write Out Resource Entry 
00146        resourceEntry.entryID              =      ePas_Resource;
00147        resourceEntry.entryLength   =      -1;
00148        resourceEntry.entryOffset   =      sizeof(PASHeader) + (3 * sizeof(PASEntry)) + dataEntry.entryLength + miscEntry.entryLength;
00149 
00150 
00151        sizeOfEntry                 =      sizeof(PASEntry);
00152        err = FSWrite(outRefNum, &sizeOfEntry, &resourceEntry);
00153        if (err != noErr)    goto error;
00154        
00155        err =  PAS_encodeData(inSpec, outRefNum); 
00156        if (err != noErr)    goto error;
00157        
00158        
00159        err =  PAS_encodeMisc(inSpec, outRefNum); 
00160        if (err != noErr)    goto error;
00161        
00162        err =  PAS_encodeResource(inSpec, outRefNum);    
00163        
00164        if (err == kResFileNotOpened)
00165        {
00166               // there was no resource fork
00167               err = noErr;
00168        }
00169        else if (err != noErr)
00170        {
00171               goto error;
00172        }
00173               
00174        FSClose(outRefNum);
00175        
00176        return noErr;
00177        
00178        
00179        
00180 error:
00181               
00182               
00183        if (outRefNum != kResFileNotOpened)
00184        {
00185               FSClose(outRefNum);
00186        }
00187               
00188        FSpDelete( outSpec ) ;
00189         
00190        return err;
00191 
00192 }
00193 
00194 
00195 
00196 OSErr PAS_DecodeFile(FSSpec *inSpec, FSSpec *outSpec)
00197 {
00198        OSErr         err;
00199        short         inRefNum;
00200        
00201        PASHeader     header;
00202        
00203        PASEntry      dataEntry, miscEntry, resourceEntry;
00204        long          sizeOfEntry;
00205 
00206        if (inSpec == NULL || outSpec == NULL)
00207               return paramErr;
00208               
00209               
00210        FSpDelete( outSpec ) ;
00211        
00212        err = FSpCreate( outSpec, kCreator, kType ,smSystemScript );
00213        
00214        if (err != noErr)    return err;
00215        
00216        
00217        
00218        err = FSpOpenDF(inSpec, fsRdPerm, &inRefNum);
00219        
00220        if (err != noErr)  goto error;
00221 
00222        
00223        // Read Header 
00224               
00225        err    = PAS_decodeHeader(inRefNum, &header);
00226        if (err != noErr)  goto error;
00227        
00228        if(    header.magicNum != PAS_MAGIC_NUM ||
00229               header.versionNum != PAS_VERSION)
00230        {
00231               err = -1;
00232               goto error;
00233        }
00234        
00235        
00236        
00237        // Read Data Entry 
00238        
00239        
00240        err = SetFPos(inRefNum, fsFromStart, sizeof(PASHeader));
00241        if (err != noErr)    goto error;
00242        
00243        sizeOfEntry                 =      sizeof(PASEntry);
00244 
00245        err = FSRead(inRefNum, &sizeOfEntry, &dataEntry);
00246        if (err != noErr)    goto error;
00247        
00248        
00249        
00250        
00251        // Read Misc Entry 
00252        
00253        
00254        err = SetFPos(inRefNum, fsFromStart, (sizeof(PASHeader) + sizeof(PASEntry)));
00255        if (err != noErr)    goto error;
00256        
00257        sizeOfEntry                 =      sizeof(PASEntry);
00258 
00259        err = FSRead(inRefNum, &sizeOfEntry, &miscEntry);
00260        if (err != noErr)    goto error;
00261        
00262 
00263        // Read Resource Entry 
00264        
00265        
00266        err = SetFPos(inRefNum, fsFromStart, (sizeof(PASHeader) + (2 * sizeof(PASEntry)))) ;
00267        if (err != noErr)    goto error;
00268        
00269        sizeOfEntry                 =      sizeof(PASEntry);
00270 
00271        err = FSRead(inRefNum, &sizeOfEntry, &resourceEntry);
00272        if (err != noErr)    goto error;
00273 
00274 
00275 
00276 
00277 
00278        err =  PAS_decodeData(&dataEntry, outSpec, inRefNum);   
00279        if (err != noErr)    goto error;
00280 
00281        err =  PAS_decodeMisc(&miscEntry, outSpec, inRefNum);
00282        if (err != noErr)    goto error;
00283 
00284        err =  PAS_decodeResource(&resourceEntry, outSpec, inRefNum);  
00285        if (err == kResFileNotOpened)
00286        {
00287               // there was no resource fork
00288               err = noErr;
00289        }
00290        else if (err != noErr)
00291        {
00292               goto error;
00293        }
00294 
00295        
00296        FSClose(inRefNum);
00297        
00298        return noErr;
00299        
00300        
00301        
00302 error:
00303 
00304        if (inRefNum != kResFileNotOpened)
00305        {
00306               FSClose(inRefNum);
00307        }
00308               
00309        FSpDelete( outSpec ) ;
00310        
00311        return err;
00312        
00313 }
00314 
00315 
00316 
00317 
00318 #pragma mark -
00319 
00320 
00321 OSErr PAS_encodeResource(FSSpec *inFile, short outRefNum)
00322 {
00323        OSErr                err;   
00324        short                inRefNum;
00325        PASResFork           resInfo;
00326        SInt32               currentWrite;
00327        
00328        ResType              *resTypes;
00329        long                 typeCount;
00330        
00331        short                *ids;
00332        long                 idCount;
00333        
00334        short                oldResFile;
00335        
00336        oldResFile=CurResFile();
00337        inRefNum = FSpOpenResFile(inFile, fsRdPerm);
00338        if (inRefNum < noErr)       return inRefNum;
00339 
00340        UseResFile(inRefNum);
00341               
00342        memset(&resInfo, 0, sizeof(PASResFork));   
00343        
00344        PAS_sortTypes(inRefNum, &resTypes, &typeCount);
00345 
00346        resInfo.NumberOfTypes       =      typeCount;
00347        
00348        currentWrite  = sizeof(PASResFork);
00349        
00350        err = FSWrite(outRefNum, &currentWrite, &resInfo);
00351        if (err != noErr)    return err;
00352        
00353        for (typeCount = 0; ((typeCount < resInfo.NumberOfTypes) && (err == noErr)); typeCount++)
00354        {
00355               PAS_sortIDs(inRefNum, resTypes[typeCount], &ids, &idCount);
00356               err = PAS_flattenResource(resTypes[typeCount], ids, idCount, inRefNum, outRefNum);
00357               DisposePtr((Ptr)ids);
00358        }
00359        
00360        DisposePtr((Ptr)resTypes);
00361        
00362        
00363        UseResFile(oldResFile);            
00364        CloseResFile(inRefNum);
00365        
00366        return err;
00367 }
00368 
00369 OSErr PAS_decodeResource(PASEntry *entry, FSSpec *outFile, short inRefNum)
00370 {
00371        OSErr                err = noErr;  
00372        short                outRefNum;
00373        PASResFork           info;
00374        SInt32               infoSize;
00375        short                oldResFile;
00376        
00377        PASResource          pasRes;
00378        SInt32               pasResSize;
00379        
00380        long                 bufSize;
00381        Handle               buffer;
00382        long                 counter=0;
00383        
00384        infoSize      =      sizeof(PASResFork);
00385        
00386        err = SetFPos(inRefNum, fsFromStart, (*entry).entryOffset );
00387        if (err != noErr)    return err;
00388 
00389        err    = FSRead( inRefNum, &infoSize, &info);
00390        if (err != noErr)    return err;
00391 
00392        if(infoSize != sizeof(PASResFork))
00393        {
00394               err = -1;
00395               goto error;
00396        }
00397        
00398        oldResFile=CurResFile();
00399        
00400        outRefNum = FSpOpenResFile(outFile, fsRdWrPerm);
00401        if (outRefNum < noErr)      return outRefNum;
00402                             
00403        UseResFile(outRefNum);
00404        
00405        
00406        while (1)
00407        {
00408               pasResSize    =      sizeof(PASResource);
00409               err    = FSRead( inRefNum, &pasResSize, &pasRes);
00410               
00411               if (err != noErr)
00412               {
00413                      if(err == eofErr)
00414                             err = noErr;
00415                             
00416                      break;
00417               }
00418               
00419               bufSize       =      pasRes.length;
00420               buffer =      NewHandle(bufSize);
00421               HLock(buffer);
00422               
00423               if(buffer == NULL)
00424               {
00425                      //  if we did not get our memory, try updateresfile 
00426               
00427                      HUnlock(buffer);
00428 
00429 
00430                      UpdateResFile(outRefNum);
00431                      counter=0;
00432                      
00433                      buffer =      NewHandle(bufSize);
00434                      HLock(buffer);
00435                      
00436                      if(buffer == NULL)
00437                      {
00438                             err = memFullErr;
00439                             break;
00440                      }
00441               }
00442               
00443               err    = FSRead( inRefNum, &bufSize, &(**buffer));
00444               if (err != noErr && err != eofErr) break;
00445               
00446               AddResource(buffer, pasRes.attrType, pasRes.attrID, pasRes.attrName);
00447               WriteResource(buffer);
00448               
00449               SetResAttrs(buffer, pasRes.attr);
00450               ChangedResource(buffer);    
00451               WriteResource(buffer);
00452               
00453               ReleaseResource(buffer);    
00454               
00455               if (counter++ > 100)
00456               {
00457                      UpdateResFile(outRefNum);
00458                      counter=0;
00459               }
00460        
00461        }
00462 
00463 error:
00464               
00465        UseResFile(oldResFile);     
00466        CloseResFile(outRefNum);
00467               
00468        return err;
00469 }
00470 
00471 #pragma mark -
00472 
00473 OSErr PAS_encodeMisc(FSSpec *inFile, short outRefNum)
00474 {
00475        OSErr         err;   
00476        short         inRefNum;
00477        PASMiscInfo   infoBlock;
00478        FInfo         fInfo;
00479        SInt32        currentRead;
00480        
00481        err = FSpOpenDF(inFile, fsRdPerm, &inRefNum);
00482        if (err != noErr)    return err;
00483        
00484        memset(&infoBlock, 0, sizeof(PASMiscInfo));   
00485        
00486        err = FSpGetFInfo(inFile, &fInfo);
00487        if (err != noErr)    return err;
00488        
00489        infoBlock.fileType          =      fInfo.fdType;
00490        infoBlock.fileCreator       =      fInfo.fdCreator;
00491        infoBlock.fileFlags         =      fInfo.fdFlags;
00492        
00493               
00494        FSClose(inRefNum);
00495        
00496        
00497        inRefNum = FSpOpenResFile(inFile, fsRdPerm);
00498        if (inRefNum > noErr)
00499        {
00500               infoBlock.fileHasResFork    = 1;
00501               infoBlock.fileResAttrs             = GetResFileAttrs(inRefNum);
00502               FSClose(inRefNum);
00503        }
00504        else
00505        {
00506               infoBlock.fileHasResFork    = 0;
00507               infoBlock.fileResAttrs             = 0;
00508        }
00509        currentRead   = sizeof(PASMiscInfo);
00510        
00511        err = FSWrite(outRefNum, &currentRead, &infoBlock);
00512        if (err != noErr)    return err;
00513               
00514        CloseResFile(inRefNum);
00515        
00516        return noErr;
00517 }
00518 
00519 
00520 OSErr PAS_decodeMisc(PASEntry *entry, FSSpec *outFile, short inRefNum)
00521 {
00522        OSErr         err = noErr;  
00523        short         outRefNum;
00524        PASMiscInfo   info;
00525        SInt32        infoSize;
00526        FInfo         theFInfo;
00527               
00528        
00529        infoSize      =      sizeof(PASMiscInfo);
00530        
00531        err = SetFPos(inRefNum, fsFromStart, (*entry).entryOffset );
00532        if (err != noErr)    return err;
00533 
00534        err    = FSRead( inRefNum, &infoSize, &info);
00535        if (err != noErr)    return err;
00536 
00537        if(infoSize != sizeof(PASMiscInfo))
00538        {
00539               return -1;
00540        }
00541 
00542        err = FSpOpenDF(outFile, fsRdWrPerm, &outRefNum);
00543        if (err != noErr)    return err;
00544        
00545        memset(&theFInfo, 0, sizeof(FInfo));   
00546               
00547        theFInfo.fdType             =      info.fileType;
00548        theFInfo.fdCreator   =      info.fileCreator;    
00549        theFInfo.fdFlags     =      info.fileFlags;
00550        
00551        err = FSpSetFInfo(outFile, &theFInfo);
00552        if (err != noErr)    return err;
00553               
00554        FSClose(outRefNum);
00555        
00556        if (info.fileHasResFork)
00557        {
00558               outRefNum = FSpOpenResFile(outFile, fsRdWrPerm);
00559               if (outRefNum < noErr)
00560               {
00561                      // maybe it does not have one!
00562                      
00563                      FSpCreateResFile(outFile, info.fileCreator, info.fileType, smSystemScript);
00564                      
00565                      outRefNum = FSpOpenResFile(outFile, fsRdWrPerm); 
00566                      if (outRefNum < noErr) 
00567                      {
00568                             return outRefNum;
00569                      }
00570               }
00571               
00572               SetResFileAttrs(outRefNum, info.fileResAttrs);
00573               
00574               
00575               CloseResFile(outRefNum);
00576        }      
00577        
00578        
00579        if(info.fileType == 'APPL')
00580        {
00581               // we need to add applications to the desktop database.
00582               
00583 /*     FIX :: need to find DTSetAPPL() function  
00584               err = DTSetAPPL( NULL,
00585                       outFile->vRefNum,
00586                                   info.fileCreator,
00587                                   outFile->parID,
00588                          outFile->name);
00589 */     }
00590        
00591        
00592        return err;
00593        
00594        
00595 
00596 }
00597 
00598 #pragma mark -
00599 
00600 OSErr PAS_encodeData(FSSpec *inFile, short outRefNum)
00601 {
00602        OSErr         err;   
00603        short         inRefNum;
00604        Ptr           buffer;
00605        SInt32               currentRead =        PAS_BUFFER_SIZE;
00606               
00607        buffer =      NewPtr(currentRead);
00608 
00609        err = FSpOpenDF(inFile, fsRdPerm, &inRefNum);
00610        if (err != noErr)    return err;
00611        
00612        while ( currentRead > 0 )
00613     {
00614               err    = FSRead( inRefNum, &currentRead, buffer);
00615               if (err != noErr && err != eofErr) return err;
00616               
00617               err = FSWrite(outRefNum, &currentRead, buffer);
00618               if (err != noErr)    return err;
00619        }
00620        
00621        FSClose(inRefNum);
00622        
00623        DisposePtr(buffer);
00624        
00625        return noErr;
00626 }
00627 
00628 OSErr PAS_decodeData(PASEntry *entry, FSSpec *outFile, short inRefNum)
00629 {
00630        OSErr         err;   
00631        short         outRefNum;
00632        Ptr           buffer;
00633        SInt32               currentWrite =       PAS_BUFFER_SIZE;
00634        SInt32        totalSize;
00635        
00636        
00637        buffer = NewPtr(currentWrite);
00638        
00639        
00640        err = FSpOpenDF(outFile, fsRdWrPerm, &outRefNum);
00641        if (err != noErr)    return err;
00642        
00643        
00644        err = SetFPos(inRefNum, fsFromStart, (*entry).entryOffset );
00645        if (err != noErr)    return err;
00646        
00647        err = SetFPos(outRefNum, fsFromStart, 0 );
00648        if (err != noErr)    return err;
00649        
00650        totalSize = (*entry).entryLength;
00651        
00652        while(totalSize > 0)
00653        {      
00654               currentWrite = PAS_BUFFER_SIZE;
00655 
00656               if (totalSize < currentWrite)
00657               {
00658                      currentWrite = totalSize;
00659               }
00660 
00661               err    = FSRead( inRefNum, &currentWrite, buffer);
00662               if (err != noErr && err != eofErr) return err;
00663        
00664               err = FSWrite(outRefNum, &currentWrite, buffer);
00665               if (err != noErr)    return err;
00666               
00667               totalSize = totalSize - currentWrite;
00668 
00669        }
00670        
00671        FSClose(outRefNum);
00672        
00673        DisposePtr(buffer);
00674        
00675        return noErr;
00676 
00677 }
00678 
00679 #pragma mark -
00680 
00681 OSErr PAS_encodeHeader(short refnum)
00682 {
00683        PASHeader     header;
00684        long          sizeOfHeader;
00685        OSErr         err;
00686        
00687        
00688        sizeOfHeader = sizeof(PASHeader);
00689               
00690        memset(&header, 0, sizeOfHeader);   
00691        
00692        header.magicNum      = PAS_MAGIC_NUM;
00693        header.versionNum    = PAS_VERSION;
00694        header.numEntries    = 3;
00695        
00696        // Write Out Header 
00697        err = FSWrite(refnum, &sizeOfHeader, &header);
00698        
00699        return err;
00700 
00701 }
00702 
00703 OSErr PAS_decodeHeader(short refNum, PASHeader *header)
00704 {
00705        OSErr  err;
00706        long   sizeOfHeader = sizeof(PASHeader);
00707        
00708        memset(header, 0, sizeOfHeader);   
00709        
00710        err = FSRead(refNum, &sizeOfHeader, header);
00711        
00712        return err;
00713 }
00714 
00715 #pragma mark -
00716 
00717 
00718 unsigned long PAS_getDataSize(FSSpec *spec)
00719 {
00720        short         refNum;
00721        OSErr         err;
00722        Str255               temp;  
00723        CInfoPBRec    cbrec;
00724        err = FSpOpenDF(spec, fsRdPerm, &refNum);
00725 
00726        memcpy( temp, spec->name, spec->name[0] + 1);
00727 
00728        cbrec.hFileInfo.ioNamePtr          = temp;
00729        cbrec.hFileInfo.ioDirID            = spec->parID;
00730        cbrec.hFileInfo.ioVRefNum          = spec->vRefNum;
00731        cbrec.hFileInfo.ioFDirIndex     = 0;
00732 
00733        err = PBGetCatInfoSync(&cbrec);
00734        FSClose(refNum);
00735        
00736        if(err != noErr)
00737        {
00738               cbrec.hFileInfo.ioFlLgLen = err;
00739        }
00740 
00741        return (cbrec.hFileInfo.ioFlLgLen);
00742 }
00743 
00744 short PAS_getResourceID(Handle resource)
00745 {
00746        ResType                     theType;
00747        Str255               name;
00748        short                theID;
00749        
00750        memset(&name, 0, sizeof(Str255));  
00751                      
00752        GetResInfo(resource, &theID, &theType, name);
00753        
00754        return theID;
00755 }
00756 
00757 
00758 #pragma mark -
00759 OSErr PAS_flattenResource(ResType type, short *ids, long count, short source, short dest)
00760 {
00761        long                 idIndex;
00762        
00763        
00764        Handle               resToCopy;
00765        long                 handleLength;
00766        
00767        PASResource          pasResource;
00768        long                 pasResLen;
00769        
00770        OSErr                err;
00771        
00772        for (idIndex=0; idIndex < count; idIndex++)
00773        {
00774               if( (type == 'SIZE') && ( ids[idIndex] == 1 || ids[idIndex] == 0  ) )
00775               {
00776                      /*     
00777                             We do not want to encode/flatten SIZE 0 or 1 because this
00778                             is the resource that the user can modify.  Most applications
00779                             will not be affected if we remove these resources
00780                      */
00781               }
00782               else
00783               {      
00784                      resToCopy=Get1Resource(type,ids[idIndex]);
00785                                    
00786                      if(!resToCopy)       
00787                      {
00788                             return resNotFound;
00789                      }      
00790                             
00791                      memset(&pasResource, 0, sizeof(PASResource));    
00792                             
00793                      GetResInfo(   resToCopy,    
00794                                           &pasResource.attrID, 
00795                                           &pasResource.attrType, 
00796                                           pasResource.attrName);      
00797                      
00798                      pasResource.attr = GetResAttrs(resToCopy);
00799                      
00800                      DetachResource(resToCopy);  
00801                      HLock(resToCopy);
00802                      
00803                      pasResource.length   = GetHandleSize(resToCopy);
00804                      handleLength         = pasResource.length;
00805                      
00806                      pasResLen                   =      sizeof(PASResource);
00807                      
00808                      err = FSWrite(dest, &pasResLen, &pasResource);
00809                      
00810                      if(err != noErr) 
00811                      {
00812                             return err;
00813                      }
00814                      
00815                      err = FSWrite(dest, &handleLength, &(**resToCopy));
00816 
00817                      if(err != noErr) 
00818                      {
00819                             return err;
00820                      }
00821                      
00822                      HUnlock(resToCopy);
00823                      DisposeHandle(resToCopy);          
00824               }
00825        }
00826        
00827        
00828        return noErr;
00829 }
00830 
00831 
00832 #pragma mark -
00833 
00834 void PAS_sortTypes(short sourceRefNum, ResType **resTypePtr, long *count)
00835 {
00836        short                       oldRef;
00837        short                       typeIndex;
00838        short                       numberOfTypes;
00839               
00840        *count =      -1;
00841        
00842        oldRef = CurResFile();
00843               
00844        UseResFile(sourceRefNum);
00845 
00846        numberOfTypes = Count1Types();
00847        
00848        *resTypePtr   =      (ResType*) NewPtrClear( numberOfTypes * sizeof(OSType) );
00849        
00850        for (typeIndex=1; typeIndex <= numberOfTypes; typeIndex++)
00851        {
00852               Get1IndType(&(*resTypePtr)[typeIndex-1], typeIndex);
00853        }
00854        
00855        UseResFile(oldRef);
00856        
00857        PAS_bubbleSortResType(*resTypePtr, numberOfTypes);
00858        
00859        *count = numberOfTypes;
00860 }      
00861 
00862 
00863 void PAS_sortIDs(short sourceRefNum, OSType theType, short **IdPtr, long *count)
00864 {
00865        short                       oldRef;
00866        Handle                      theHandle;
00867        short                       resCount;
00868        short                       resIndex;
00869        
00870        *count =      -1;
00871        
00872        oldRef = CurResFile();
00873               
00874        UseResFile(sourceRefNum);
00875 
00876        resCount = Count1Resources(theType);
00877        
00878        *IdPtr =      (short*) NewPtrClear( resCount * sizeof(short) );
00879        
00880        for (resIndex=1; resIndex <= resCount; resIndex++)
00881        {
00882               theHandle = Get1IndResource(theType, resIndex);
00883               
00884               if(theHandle == NULL) return;
00885        
00886               (*IdPtr)[resIndex-1] = PAS_getResourceID(theHandle);
00887               
00888               ReleaseResource(theHandle);
00889        }
00890        
00891        UseResFile(oldRef);
00892        
00893        PAS_bubbleSortIDS(*IdPtr, resCount);
00894        
00895        
00896        *count = resCount;
00897 }
00898 
00899 #pragma mark -
00900 
00901 void
00902 PAS_bubbleSortResType(ResType *types, long count)
00903 {
00904        long   x, y;
00905        OSType temp;
00906        
00907        for (x=0; x < count-1; x++)      
00908        {
00909        for (y=0; y < count-x-1; y++)        
00910               {
00911               if (types[y] > types[y+1])        
00912                {  
00913                             temp=types[y];  
00914               types[y]=types[y+1];  
00915               types[y+1]=temp;        
00916               } 
00917               }
00918        }
00919 }
00920 
00921 void
00922 PAS_bubbleSortIDS(short *ids, long count)
00923 {
00924        long   x, y;
00925        short  temp;
00926        
00927        for (x=0; x < count-1; x++)      
00928        {
00929        for (y=0; y < count-x-1; y++)        
00930               {
00931               if (ids[y] > ids[y+1])        
00932                {  
00933                             temp=ids[y];  
00934               ids[y]=ids[y+1];  
00935               ids[y+1]=temp;        
00936               } 
00937               }
00938        }
00939 }
00940