/** ReadPict.c **************************************************************
 *
 * Read an ILBM raster image file.   01/07/85.
 *
 * By Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts.
 * This software is in the public domain.
 *
 * USE THIS AS AN EXAMPLE PROGRAM FOR AN IFF READER.
 *
 * The IFF reader portion is essentially a recursive-descent parser.
 * This program will look into a CAT or LIST to find a FORM ILBM, but it
 * won't look inside another FORM type for a nested FORM ILBM.
 *
 * Modified for HAM images by Martin Hash.	12/20/86.
 *
 ****************************************************************************/
 
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include "df1:ilbm.h"
#include "df1:readpict.h"

/* LOCAL CONSTANTS */
 
/* Define the size of a temporary buffer used in unscrambling the ILBM rows.*/
#define bufSz 		512
#define maxColorReg	32
 
/* EXTERNAL FUNCTIONS */
 
extern IFFP OpenRGroup();
extern IFFP GetFChunkHdr();

/* LOCAL VARIABLES */
 
static ILBMFrame iFrame;
static BYTE bodyBuffer[bufSz];
static struct BitMap *bitmapptr;

/*------------ ILBM reader -----------------------------------------------*/
/* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file.
 * We allocate one of these on the stack for every LIST or FORM encountered
 * in the file and use it to hold BMHD & CMAP properties. We also allocate
 * an initial one for the whole file.
 * We allocate a new GroupContext (and initialize it by OpenRIFF or
 * OpenRGroup) for every group (FORM, CAT, LIST, or PROP) encountered. It's
 * just a context for reading (nested) chunks.
 *
 * If we were to scan the entire example file outlined below:
 *    reading          proc(s)                new               new
 *
 * --whole file--   ReadPicture+ReadIFF   GroupContext        ILBMFrame
 * CAT              ReadICat                GroupContext
 *   LIST           GetLiILBM+ReadIList       GroupContext        ILBMFrame
 *     PROP ILBM    GetPrILBM                   GroupContext
 *       CMAP       GetCMAP
 *       BMHD       GetBMHD
 *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
 *       BODY       GetBODY
 *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
 *       BODY       GetBODY
 *   FORM ILBM      GetFoILBM                 GroupContext        ILBMFrame
 */
 
/** GetFoILBM() *************************************************************
 *
 * Called via ReadPicture to handle every FORM encountered in an IFF file.
 * Reads FORMs ILBM and skips all others.
 * Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
 * finds no BODY or if it has no BMHD to decode the BODY.
 *
 ****************************************************************************/
 
IFFP GetFoILBM( parent )

GroupContext *parent;
{
   IFFP iffp;
   GroupContext formContext;
   ILBMFrame ilbmFrame;         /* only used for non-clientFrame fields.*/
 
   if (parent->subtype != ID_ILBM)
      return(IFF_OKAY); /* just continue scaning the file */
 
   ilbmFrame = *(ILBMFrame *)parent->clientFrame;
   iffp = OpenRGroup(parent, &formContext);
   CheckIFFP();
 
  do {
    iffp = GetFChunkHdr(&formContext);
    if (iffp == ID_BMHD) {
       ilbmFrame.foundBMHD = TRUE;
       iffp = GetBMHD(&formContext, &ilbmFrame.bmHdr);
    }
    else if (iffp == ID_CMAP) { 
       ilbmFrame.nColorRegs = maxColorReg;
       iffp = GetCMAP( &formContext, (WORD *)ilbmFrame.colorMap,
        &ilbmFrame.nColorRegs);
    }
    else if (iffp == ID_BODY) {
       if (!ilbmFrame.foundBMHD)  
          return(BAD_FORM);   /* No BMHD chunk! */
 
       iffp = GetBODY( &formContext, bitmapptr, NULL, &ilbmFrame.bmHdr,
        bodyBuffer, (long)bufSz);
 
       if (iffp == IFF_OKAY)
          iffp = IFF_DONE;      /* Eureka */
       iFrame = ilbmFrame;
    }
 
    else if (iffp == END_MARK)
       iffp = BAD_FORM;
 
  } while (iffp >= IFF_OKAY);  /* loop if valid ID of ignored chunk or a
                          * subroutine returned IFF_OKAY (no errors).*/
 
   if (iffp != IFF_DONE)  return(iffp);
 
   /* If we get this far, there were no errors. */
   CloseRGroup(&formContext);
   return(iffp);
}

/** ReadPicture() ***********************************************************
 *
 * Read a picture from an IFF file, given a file handle open for reading.
 * Allocates BitMap using (*Allocator)().
 *
 ****************************************************************************/
IFFP ReadPicture( file, bitmap, viewport )

LONG file;
struct BitMap *bitmap;
struct ViewPort *viewport;
{
   IFFP iffp;
 
   iFrame.clientFrame.getList = SkipGroup;
   iFrame.clientFrame.getProp = SkipGroup;
   iFrame.clientFrame.getForm = GetFoILBM;
   iFrame.clientFrame.getCat  = ReadICat ;
 
   /* Initialize the top-level client frame's property settings to the
    * program-wide defaults. This example just records that we haven't read
    * any BMHD property or CMAP color registers yet. For the color map, that
    * means the default is to leave the machine's color registers alone.
    * If you want to read a property like GRAB, init it here to (0, 0). */
   iFrame.foundBMHD  = FALSE;
   iFrame.nColorRegs = 0;

   bitmapptr = bitmap;
 
   iffp = ReadIFF(file, (ClientFrame *)&iFrame);
   LoadRGB4( viewport, iFrame.colorMap, iFrame.nColorRegs );
   return(iffp);
}
