home *** CD-ROM | disk | FTP | other *** search
- /* copychunks
- *
- * For Read/Modify/Write programs and other programs that need
- * to close the IFF file but still reference gathered chunks.
- * Copies your gathered property and collection chunks
- * from an iff context so that IFF handle may be
- * closed right after parsing (allowing file or clipboard to
- * to be reopened for read or write by self or other programs)
- *
- * The created list of chunks can be modified and written
- * back out to a new handle with writechunklist().
- *
- * If you have used copychunks(), remember to free the copied
- * chunks with freechunklist(), when ready, to deallocate them.
- *
- * Note that this implementation is flat and is suitable only
- * for simple FORMs.
- */
-
- #include "iffp/iff.h"
-
- /* copychunks()
- *
- * Copies chunks specified in propchks and collectchks
- * FROM an already-parsed IFFHandle
- * TO a singly linked list of Chunk structures,
- * and returns a pointer to the start of the list.
- *
- * Generally you would store this pointer in parseInfo.copiedchunks.
- *
- * You must later free the list of copied chunks by calling
- * FreeChunkList().
- *
- * Reorders collection chunks so they appear in SAME ORDER
- * in chunk list as they did in the file.
- *
- * Returns 0 for failure
- */
- struct Chunk *copychunks(struct IFFHandle *iff,
- LONG *propchks, LONG *collectchks,
- ULONG memtype)
- {
- struct Chunk *chunk, *first=NULL, *prevchunk = NULL;
- struct StoredProperty *sp;
- struct CollectionItem *ci, *cii;
- long error;
- int k, kk, bk;
-
- if(!iff) return(NULL);
-
- /* Copy gathered property chunks */
- error = 0;
- for(k=0; (!error) && (propchks) && (propchks[k] != TAG_DONE); k+=2)
- {
- if(sp=FindProp(iff,propchks[k],propchks[k+1]))
- {
- D(bug("copying %.4s.%.4s chunk\n",&propchks[k],&propchks[k+1]));
-
- if(chunk=(struct Chunk *)
- AllocMem(sizeof(struct Chunk),memtype|MEMF_CLEAR))
- {
- chunk->ch_Type = propchks[k];
- chunk->ch_ID = propchks[k+1];
- if(chunk->ch_Data = AllocMem(sp->sp_Size,memtype))
- {
- chunk->ch_Size = sp->sp_Size;
- CopyMem(sp->sp_Data,chunk->ch_Data,sp->sp_Size);
- if(prevchunk) prevchunk->ch_Next = chunk;
- else first = chunk;
- prevchunk = chunk;
- }
- else
- {
- FreeMem(chunk,sizeof(struct Chunk));
- chunk=NULL;
- error = 1;
- }
- }
- else error = 1;
- }
- }
-
- /* Copy gathered collection chunks in reverse order */
- for(k=0; (!error) && (collectchks) && (collectchks[k] != TAG_DONE); k+=2)
- {
- if(ci=FindCollection(iff,collectchks[k],collectchks[k+1]))
- {
- D(bug("copying %.4s.%.4s collection\n",&collectchks[k],&collectchks[k+1]));
- for(cii=ci, bk=0; cii; cii=cii->ci_Next) bk++;
-
- D(bug(" There are %ld of these, first is at $%lx\n",bk,ci));
-
- for( bk; bk; bk--)
- {
- for(kk=1, cii=ci; kk<bk; kk++) cii=cii->ci_Next;
-
- D(bug(" copying number %ld\n",kk));
-
- if(chunk=(struct Chunk *)
- AllocMem(sizeof(struct Chunk),memtype|MEMF_CLEAR))
- {
- chunk->ch_Type = collectchks[k];
- chunk->ch_ID = collectchks[k+1];
- if(chunk->ch_Data = AllocMem(cii->ci_Size,memtype))
- {
- chunk->ch_Size = cii->ci_Size;
- CopyMem(cii->ci_Data,chunk->ch_Data,cii->ci_Size);
- if(prevchunk) prevchunk->ch_Next = chunk;
- else first = chunk;
- prevchunk = chunk;
- }
- else
- {
- FreeMem(chunk,sizeof(struct Chunk));
- chunk=NULL;
- error = 1;
- }
- }
- else error = 1;
- }
- }
- }
-
- if(error)
- {
- if(first) freechunklist(first);
- first = NULL;
- }
-
- return(first);
- }
-
- /* freechunklist - Free a dynamically allocated Chunk list and
- * all of its ch_Data.
- *
- * Note - if a chunk's ch_Size is IFFSIZE_UNKNOWN, its ch_Data
- * will not be deallocated.
- */
- void freechunklist(struct Chunk *first)
- {
- struct Chunk *chunk, *next;
-
- chunk = first;
- while(chunk)
- {
- next = chunk->ch_Next;
- if((chunk->ch_Data)&&(chunk->ch_Size != IFFSIZE_UNKNOWN))
- FreeMem(chunk->ch_Data,chunk->ch_Size);
- FreeMem(chunk, sizeof(struct Chunk));
- chunk = next;
- }
- }
-
-
- /* findchunk - find first matching chunk in list of struct Chunks
- * example finchunk(pi->copiedchunks,ID_ILBM,ID_CRNG);
- *
- * returns struct Chunk *, or NULL if none found
- */
- struct Chunk *findchunk(struct Chunk *first, long type, long id)
- {
- struct Chunk *chunk;
-
- for(chunk=first; chunk; chunk=chunk->ch_Next)
- {
- if((chunk->ch_Type == type)&&(chunk->ch_ID == id)) return(chunk);
- }
- return(NULL);
- }
-
-
- /* writechunklist - write out list of struct Chunk's
- * If data is a null terminated string, you may use
- * IFFSIZE_UNKNOWN as the ch_Szie and strlen(chunk->ch_Data)
- * will be used here as size.
- *
- * Returns 0 for success or an IFFERR
- */
- long writechunklist(struct IFFHandle *iff, struct Chunk *first)
- {
- struct Chunk *chunk;
- long size, error = 0;
-
- D(bug("writechunklist: first chunk pointer = $%lx\n",first));
-
- for(chunk=first; chunk && (!error); chunk=chunk->ch_Next)
- {
- size = (chunk->ch_Size == IFFSIZE_UNKNOWN) ?
- strlen(chunk->ch_Data) : chunk->ch_Size;
- error = PutCk(iff, chunk->ch_ID, size, chunk->ch_Data);
- D(bug("writechunklist: put %.4s size=%ld, error=%ld\n",
- &chunk->ch_ID,size, error));
- }
- return(error);
- }
-
-