home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Misc / TRSICAT.LZX / CATS_CD2_TRSI / Reference_Library / Devices / modules / copychunks.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-21  |  5.2 KB  |  197 lines

  1. /* copychunks
  2.  *
  3.  * For Read/Modify/Write programs and other programs that need
  4.  *   to close the IFF file but still reference gathered chunks.
  5.  * Copies your gathered property and collection chunks
  6.  *   from an iff context so that IFF handle may be
  7.  *   closed right after parsing (allowing file or clipboard to
  8.  *   to be reopened for read or write by self or other programs)
  9.  *
  10.  * The created list of chunks can be modified and written
  11.  *   back out to a new handle with writechunklist().
  12.  *
  13.  * If you have used copychunks(), remember to free the copied
  14.  *   chunks with freechunklist(), when ready, to deallocate them.
  15.  * 
  16.  * Note that this implementation is flat and is suitable only
  17.  *   for simple FORMs.
  18.  */
  19.  
  20. #include "iffp/iff.h"
  21.  
  22. /* copychunks()
  23.  *
  24.  * Copies chunks specified in propchks and collectchks
  25.  *   FROM an already-parsed IFFHandle
  26.  *   TO a singly linked list of Chunk structures,
  27.  * and returns a pointer to the start of the list.
  28.  *
  29.  * Generally you would store this pointer in parseInfo.copiedchunks.
  30.  *
  31.  * You must later free the list of copied chunks by calling
  32.  *   FreeChunkList().
  33.  *
  34.  * Reorders collection chunks so they appear in SAME ORDER
  35.  * in chunk list as they did in the file.
  36.  *
  37.  * Returns 0 for failure
  38.  */  
  39. struct Chunk *copychunks(struct IFFHandle *iff,
  40.             LONG *propchks, LONG *collectchks,
  41.             ULONG memtype)
  42.     {
  43.     struct Chunk *chunk, *first=NULL, *prevchunk = NULL;
  44.     struct StoredProperty *sp;
  45.     struct CollectionItem *ci, *cii;
  46.     long error;
  47.     int k, kk, bk;
  48.  
  49.     if(!iff)    return(NULL);
  50.  
  51.     /* Copy gathered property chunks */
  52.     error = 0;
  53.     for(k=0; (!error) && (propchks) && (propchks[k] != TAG_DONE); k+=2)
  54.     {
  55.     if(sp=FindProp(iff,propchks[k],propchks[k+1]))
  56.         {
  57.         D(bug("copying %.4s.%.4s chunk\n",&propchks[k],&propchks[k+1]));
  58.  
  59.         if(chunk=(struct Chunk *)
  60.             AllocMem(sizeof(struct Chunk),memtype|MEMF_CLEAR))
  61.         {
  62.         chunk->ch_Type = propchks[k];
  63.         chunk->ch_ID   = propchks[k+1];
  64.         if(chunk->ch_Data = AllocMem(sp->sp_Size,memtype))
  65.             {
  66.             chunk->ch_Size = sp->sp_Size;
  67.             CopyMem(sp->sp_Data,chunk->ch_Data,sp->sp_Size);
  68.             if(prevchunk)    prevchunk->ch_Next = chunk;
  69.             else         first = chunk;
  70.             prevchunk = chunk;
  71.             }
  72.         else
  73.             {
  74.             FreeMem(chunk,sizeof(struct Chunk));
  75.             chunk=NULL;
  76.             error = 1;
  77.             }
  78.         }
  79.         else error = 1;
  80.         }
  81.     }
  82.  
  83.     /* Copy gathered collection chunks in reverse order */
  84.     for(k=0; (!error) && (collectchks) && (collectchks[k] != TAG_DONE); k+=2)
  85.     {
  86.     if(ci=FindCollection(iff,collectchks[k],collectchks[k+1]))
  87.         {
  88.         D(bug("copying %.4s.%.4s collection\n",&collectchks[k],&collectchks[k+1]));
  89.         for(cii=ci, bk=0; cii; cii=cii->ci_Next)    bk++;
  90.  
  91.         D(bug(" There are %ld of these, first is at $%lx\n",bk,ci));
  92.  
  93.         for( bk; bk; bk--)
  94.         {
  95.          for(kk=1, cii=ci; kk<bk; kk++) cii=cii->ci_Next;
  96.  
  97.         D(bug("  copying number %ld\n",kk));
  98.  
  99.             if(chunk=(struct Chunk *)
  100.             AllocMem(sizeof(struct Chunk),memtype|MEMF_CLEAR))
  101.             {
  102.             chunk->ch_Type = collectchks[k];
  103.             chunk->ch_ID   = collectchks[k+1];
  104.             if(chunk->ch_Data = AllocMem(cii->ci_Size,memtype))
  105.                 {
  106.                 chunk->ch_Size = cii->ci_Size;
  107.                 CopyMem(cii->ci_Data,chunk->ch_Data,cii->ci_Size);
  108.                 if(prevchunk)    prevchunk->ch_Next = chunk;
  109.                 else         first = chunk;
  110.                 prevchunk = chunk;
  111.                 }
  112.             else
  113.                 {
  114.                 FreeMem(chunk,sizeof(struct Chunk));
  115.                 chunk=NULL;
  116.                 error = 1;
  117.                 }
  118.             }
  119.             else error = 1;
  120.         }
  121.         }
  122.     }
  123.  
  124.     if(error)
  125.     {
  126.     if(first) freechunklist(first);
  127.     first = NULL;
  128.     }
  129.  
  130.     return(first);
  131.     }
  132.  
  133. /* freechunklist - Free a dynamically allocated Chunk list and
  134.  *   all of its ch_Data.
  135.  *
  136.  * Note - if a chunk's ch_Size is IFFSIZE_UNKNOWN, its ch_Data
  137.  *   will not be deallocated.
  138.  */
  139. void freechunklist(struct Chunk *first)
  140.     {
  141.     struct Chunk *chunk, *next;
  142.  
  143.     chunk = first;
  144.     while(chunk)
  145.     {
  146.     next = chunk->ch_Next;
  147.     if((chunk->ch_Data)&&(chunk->ch_Size != IFFSIZE_UNKNOWN))
  148.         FreeMem(chunk->ch_Data,chunk->ch_Size);
  149.     FreeMem(chunk, sizeof(struct Chunk));    
  150.     chunk = next;
  151.     }
  152.     }
  153.  
  154.  
  155. /* findchunk - find first matching chunk in list of struct Chunks
  156.  *    example  finchunk(pi->copiedchunks,ID_ILBM,ID_CRNG);
  157.  *
  158.  * returns struct Chunk *, or NULL if none found
  159.  */
  160. struct Chunk *findchunk(struct Chunk *first, long type, long id)
  161.     {
  162.     struct Chunk *chunk;
  163.  
  164.     for(chunk=first; chunk; chunk=chunk->ch_Next)
  165.     {
  166.     if((chunk->ch_Type == type)&&(chunk->ch_ID == id)) return(chunk); 
  167.     }
  168.     return(NULL);
  169.     }
  170.  
  171.  
  172. /* writechunklist - write out list of struct Chunk's
  173.  * If data is a null terminated string, you may use
  174.  * IFFSIZE_UNKNOWN as the ch_Szie and strlen(chunk->ch_Data)
  175.  * will be used here as size.
  176.  *
  177.  * Returns 0 for success or an IFFERR
  178.  */
  179. long writechunklist(struct IFFHandle *iff, struct Chunk *first)
  180.     {
  181.     struct Chunk *chunk;
  182.     long size, error = 0;
  183.  
  184.     D(bug("writechunklist: first chunk pointer = $%lx\n",first));
  185.  
  186.     for(chunk=first; chunk && (!error); chunk=chunk->ch_Next)
  187.     {
  188.     size  = (chunk->ch_Size == IFFSIZE_UNKNOWN) ?
  189.             strlen(chunk->ch_Data) :  chunk->ch_Size;
  190.     error = PutCk(iff, chunk->ch_ID, size, chunk->ch_Data);
  191.     D(bug("writechunklist: put %.4s size=%ld, error=%ld\n",
  192.                 &chunk->ch_ID,size, error));
  193.     }
  194.     return(error);
  195.     }
  196.  
  197.