home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 004.lha / Dpaintx_source / dpaintx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-03-02  |  19.8 KB  |  621 lines

  1.  /*****************************************************************
  2.  *
  3.  * Read an ILBM file and display as a screen/window until closed.
  4.  *   Simulated close gadget in upper left corner of window.
  5.  *   Clicking below title bar area toggles screen bar for dragging.
  6.  *
  7.  *  By Carolyn Scheppner   CBM  03/15/86
  8.  *
  9.  * Based on early ShowILBM.c    11/12/85
  10.  *  By Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts.
  11.  *  This software is in the public domain.
  12.  *
  13.  * >>NOTE<<: This example must be linked with additional IFF rtn files.
  14.  *           See linkage information below.
  15.  *
  16.  * The IFF reader portion is essentially a recursive-descent parser.
  17.  * This program will look into a CAT or LIST to find a FORM ILBM, but it
  18.  * won't look inside another FORM type for a nested FORM ILBM.
  19.  *
  20.  * The display portion is specific to the Commodore Amiga computer.
  21.  *
  22.  * Linkage Information:
  23.  *
  24.  * FROM     LStartup.obj, SeeILBM.o, iffr.o, ilbmr.o, unpacker.o
  25.  * TO       SeeILBM
  26.  * LIBRARY  LC.lib, Amiga.lib
  27.  * 
  28.  **************************************************************************/
  29.  
  30. #include <exec/types.h>
  31. #include <exec/memory.h>
  32. #include <libraries/dos.h>
  33. #include <graphics/gfxbase.h>
  34. #include <graphics/rastport.h>
  35. #include <graphics/gfx.h>
  36. #include <graphics/view.h>
  37. #include <workbench/startup.h>
  38. #include <intuition/intuition.h>
  39. #include <lattice/stdio.h>
  40.  
  41. #include "iff/ilbm.h"
  42.  
  43. /* This example's max number of planes in a bitmap. Could use MaxAmDepth. */
  44. #define EXDepth 6
  45. #define maxColorReg 32
  46. #define MIN(a,b) ((a)<(b)?(a):(b))
  47.  
  48. #define SafeFreeMem(p,q) {if(p)FreeMem(p,q);}
  49.     
  50. /* Define the size of a temp buffer used in unscrambling the ILBM rows.*/
  51. #define bufSz 512
  52.  
  53. /* general usage pointers */
  54. struct GfxBase       *GfxBase;
  55. struct IntuitionBase *IntuitionBase;
  56. struct IntuiMessage  *message;
  57.  
  58. /* Globals for displaying an image */
  59. struct Screen   *screen1;
  60. struct Window   *window1;
  61. struct RastPort *rport1;
  62. struct ViewPort *vport1;
  63.  
  64. struct BitMap   tBitMap;      /* Temp BitMap struct for small pics  */
  65.  
  66. /* For WorkBench startup */    
  67. extern struct WBStartup *WBenchMsg;
  68. BOOL   fromWB;
  69. struct FileLock *startLock, *newLock;
  70.  
  71. /* Other globals */
  72. int   i, error;
  73. BYTE  c;
  74. BOOL  TBtoggle, Done;
  75. ULONG class, code, pBytes;
  76.  
  77. /* Structures for new Screen, new Window */
  78.  
  79. struct   TextAttr       TextFont = {
  80.    "topaz.font",                    /* Font Name   */
  81.    TOPAZ_EIGHTY,                    /* Font Height */
  82.    FS_NORMAL,                       /* Style       */
  83.    FPF_ROMFONT,                     /* Preferences */
  84.    };
  85.  
  86. struct   NewScreen      ns = {
  87.    0, 0,                                  /* LeftEdge and TopEdge   */
  88.    0, 0,                                  /* Width and Height       */
  89.    0,                                     /* Depth                  */
  90.    -1, -1,                                /* DetailPen and BlockPen */
  91.    NULL,                                  /* Special display modes  */
  92.    CUSTOMSCREEN,                          /* Screen Type            */
  93.    &TextFont,                             /* Use my font            */
  94.    NULL,                                  /* Title                  */
  95.    NULL,                                  /* No gadgets yet         */
  96.    NULL,                                  /* Ptr to CustomBitmap    */
  97.    };
  98.  
  99. struct   NewWindow      nw = {
  100.    0, 0,                                  /* LeftEdge and TopEdge */
  101.    0, 0,                                  /* Width and Height */
  102.    -1, -1,                                /* DetailPen and BlockPen */
  103.    MOUSEBUTTONS,                          /* IDCMP Flags */
  104.    ACTIVATE
  105.    |BACKDROP
  106.    |BORDERLESS,                           /* Flags */
  107.    NULL, NULL,                            /* Gadget and Image pointers */
  108.    NULL,                                  /* Title string */
  109.    NULL,                                  /* Put Screen ptr here */
  110.    NULL,                                  /* SuperBitMap pointer */
  111.    0, 0,                                  /* MinWidth and MinHeight */
  112.    0, 0,                                  /* MaxWidth and MaxHeight */
  113.    CUSTOMSCREEN,                          /* Type of window */
  114.    };
  115.  
  116. USHORT  allBgColor[32];
  117.  
  118.  
  119. /* Message strings for IFFP codes. */
  120. char MsgOkay[]        = {"(IFF_OKAY) No FORM ILBM in the file." };
  121. char MsgEndMark[]     = {"(END_MARK) How did you get this message?" };
  122. char MsgDone[]        = {"(IFF_DONE) All done."};
  123. char MsgDos[]         = {"(DOS_ERROR) The DOS returned an error." };
  124. char MsgNot[]         = {"(NOT_IFF) Not an IFF file." };
  125. char MsgNoFile[]      = {"(NO_FILE) No such file found." };
  126. char MsgClientError[] = {"(CLIENT_ERROR) ShowILBM bug or insufficient RAM."};
  127. char MsgForm[]        = {"(BAD_FORM) A malformed FORM ILBM." };
  128. char MsgShort[]       = {"(SHORT_CHUNK) A malformed FORM ILBM." };
  129. char MsgBad[]         = {"(BAD_IFF) A mangled IFF file." };
  130.  
  131. /* THESE MUST APPEAR IN RIGHT ORDER!! */
  132. char *IFFPMessages[-LAST_ERROR+1] = {
  133.     /*IFF_OKAY*/  MsgOkay,
  134.     /*END_MARK*/  MsgEndMark,
  135.     /*IFF_DONE*/  MsgDone,
  136.     /*DOS_ERROR*/ MsgDos,
  137.     /*NOT_IFF*/   MsgNot,
  138.     /*NO_FILE*/   MsgNoFile,
  139.     /*CLIENT_ERROR*/ MsgClientError,
  140.     /*BAD_FORM*/  MsgForm,
  141.     /*SHORT_CHUNK*/  MsgShort,
  142.     /*BAD_IFF*/   MsgBad
  143.     };
  144.  
  145. /*------------ ILBM reader -----------------------------------------------*/
  146. /* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file.
  147.  * We allocate one of these on the stack for every LIST or FORM encountered
  148.  * in the file and use it to hold BMHD & CMAP properties. We also allocate
  149.  * an initial one for the whole file.
  150.  * We allocate a new GroupContext (and initialize it by OpenRIFF or
  151.  * OpenRGroup) for every group (FORM, CAT, LIST, or PROP) encountered. It's
  152.  * just a context for reading (nested) chunks.
  153.  *
  154.  * If we were to scan the entire example file outlined below:
  155.  *    reading          proc(s)                new               new
  156.  *
  157.  * --whole file--   ReadPicture+ReadIFF   GroupContext        ILBMFrame
  158.  * CAT              ReadICat                GroupContext
  159.  *   LIST           GetLiILBM+ReadIList       GroupContext        ILBMFrame
  160.  *     PROP ILBM    GetPrILBM                   GroupContext
  161.  *       CMAP       GetCMAP
  162.  *       BMHD       GetBMHD
  163.  *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
  164.  *       BODY       GetBODY
  165.  *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
  166.  *       BODY       GetBODY
  167.  *   FORM ILBM      GetFoILBM                 GroupContext        ILBMFrame
  168.  */
  169. typedef struct {
  170.    ClientFrame clientFrame;
  171.    UBYTE foundBMHD;
  172.    UBYTE nColorRegs;
  173.    BitMapHeader bmHdr;
  174.    Color4 colorMap[maxColorReg];
  175.    /* If you want to read any other property chunks, e.g. GRAB or CAMG, add
  176.     * fields to this record to store them. */
  177.    } ILBMFrame;
  178.  
  179.  
  180. /* NOTE: For a simple version of this program, set Fancy to 0.
  181.  * That'll compile a program that skips all LISTs and PROPs in the input
  182.  * file. It will look in CATs for FORMs ILBM. That's suitable for most uses.
  183.  *
  184.  * For a fancy version that handles LISTs and PROPs, set Fancy to 1. */
  185.  
  186. #define Fancy  1
  187.  
  188. /* Modified by C. Scheppner */
  189. /*  iFrame    made global -  moved from ReadPicture() */
  190. /*  ilbmFrame made global -  moved from GetFoILBM()   */
  191.  
  192. ILBMFrame   iFrame;       /* top level client frame */
  193. ILBMFrame   ilbmFrame;    /* global bitmap frame    */
  194.  
  195.  
  196. /** main() ****************************************************************/
  197. main(argc, argv)
  198.    int argc;
  199.    char **argv;
  200.    {
  201.    LONG            file;
  202.    IFFP            iffp = NO_FILE;
  203.    struct WBArg    *arg;  
  204.    char            *filename;
  205.  
  206.    fromWB = (argc==0) ? TRUE : FALSE;
  207.  
  208.    if(argc>1)                 /* Passed filename via command line  */
  209.       {
  210.       filename = argv[1];
  211.       }
  212.    else if ((argc==0)&&(WBenchMsg->sm_NumArgs > 1))
  213.       {                        /* Passed filename via  WorkBench */
  214.       arg = WBenchMsg->sm_ArgList;
  215.       arg++;
  216.       filename = (char *)arg->wa_Name;
  217.       newLock    = (struct FileLock *)arg->wa_Lock;
  218.       startLock  = (struct FileLock *)CurrentDir(newLock);
  219.       }
  220.    else if (argc==1)           /* From CLI but no filename */
  221.       cleanexit("Usage: 'SeeILBM filename'\n");
  222.    else                        /* From WB but no filename */
  223.       cleanexit("\nClick ONCE on SeeILBM\nSHIFT and DoubleClick on Pic\n");
  224.  
  225.  
  226.  
  227.    if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)))
  228.       cleanexit("Can't open graphics library\n");
  229.  
  230.    if(!(IntuitionBase=
  231.           (struct IntuitionBase *)OpenLibrary("intuition.library",0)))
  232.       cleanexit("Can't open graphics library\n");
  233.  
  234.    if(file = Open(filename, MODE_OLDFILE))
  235.       {
  236.       printf("\nCLICK PIC TOP LEFT TO END DISPLAY\n");
  237.       printf("CLICK LOWER TO TOGGLE DRAG BAR\n");
  238.   /*  Delay(150);  wait about 3 seconds to give person time to read it */
  239.  
  240.       iffp = ReadPicture(file);
  241.       Close(file);
  242.       if (iffp == IFF_DONE)
  243.          {
  244.          error = DisplayPic(&ilbmFrame);
  245.          if(error)  cleanexit("Can't open screen or window\n");
  246.  
  247.          TBtoggle   = FALSE;      /* Title bar toggle */
  248.          Done       = FALSE;      /* Close flag       */
  249.          while (!Done)
  250.             {
  251.             if(1<<window1->UserPort->mp_SigBit)   chkmsg();
  252.             }
  253.          }
  254.       else cleanexit(IFFPMessages[-iffp]);
  255.       }
  256.    else cleanexit("Picture file not found.\n");
  257.  
  258.    cleanup();
  259.    }
  260.  
  261.  
  262. chkmsg()
  263.    {
  264.    while(message=(struct IntuiMessage *)GetMsg(window1->UserPort))
  265.       {
  266.       class = message->Class;
  267.       code  = message->Code;
  268.       ReplyMsg(message);
  269.       switch(class)
  270.          {
  271.          case MOUSEBUTTONS:
  272.             if ((code == SELECTDOWN)&&
  273.                   (window1->MouseX < 10)&&(window1->MouseY<10))
  274.                {
  275.                Done = TRUE;
  276.                }
  277.             else if ((code == SELECTDOWN)&&
  278.                        (window1->MouseY>10)&&(TBtoggle==FALSE))
  279.                {
  280.                TBtoggle = TRUE;
  281.                ShowTitle(screen1,TRUE);
  282.                }
  283.             else if ((code == SELECTDOWN)&&
  284.                        (window1->MouseY>10)&&(TBtoggle==TRUE))
  285.                {
  286.                TBtoggle = FALSE;
  287.                ShowTitle(screen1,FALSE);
  288.                }
  289.             break;
  290.          default:
  291.             printf("Unknown IDCMP message\n");
  292.          }
  293.       }
  294.    }
  295.  
  296.  
  297. cleanexit(errstr)
  298.    char  *errstr;
  299.    {
  300.    printf("\n %s \n",errstr);
  301.    cleanup();
  302.    if (fromWB)    /* Wait so user can read messages */
  303.       {
  304.       printf("\nPRESS RETURN TO CLOSE THIS WINDOW\n");
  305.       while ((c=getchar()) != '\n');
  306.       }
  307.    exit();
  308.    }
  309.  
  310. cleanup()
  311.    {
  312.    /* tBitMap planes were deallocated in DisplayPic() */
  313.    if (window1) CloseWindow(window1);
  314.    if (screen1) CloseScreen(screen1);
  315.    if (IntuitionBase) CloseLibrary(IntuitionBase);
  316.    if (GfxBase)       CloseLibrary(GfxBase);
  317.    if (newLock != startLock)  CurrentDir(startLock);
  318.    }
  319.  
  320.  
  321. /** getBitMap() *********************************************************
  322.  *
  323.  * Open screen or temp bitmap.
  324.  *   Returns ptr destBitMap  or  0 = error
  325.  *
  326.  *************************************************************************/
  327. struct BitMap *getBitMap(ptilbmFrame)
  328.    ILBMFrame *ptilbmFrame;
  329.    {
  330.    int     i, nPlanes, plsize;
  331.    SHORT  sWidth, sHeight, dWidth, dHeight;
  332.    struct BitMap *destBitMap;
  333.  
  334.    sWidth  = ptilbmFrame->bmHdr.w;
  335.    sHeight = ptilbmFrame->bmHdr.h;
  336.    dWidth  = ptilbmFrame->bmHdr.pageWidth;
  337.    dHeight = ptilbmFrame->bmHdr.pageHeight;
  338.    nPlanes   = MIN(ptilbmFrame->bmHdr.nPlanes, EXDepth);
  339.  
  340.    for (i = 0; i < ptilbmFrame->nColorRegs; i++)
  341.       {
  342.       allBgColor[i] = ptilbmFrame->colorMap[0];
  343.       }
  344.  
  345.    ns.Width  = dWidth;
  346.    ns.Height = dHeight;
  347.    ns.Depth  = nPlanes;
  348.  
  349.    if (ptilbmFrame->bmHdr.pageWidth <= 320)
  350.       ns.ViewModes = 0;
  351.    else
  352.       ns.ViewModes = HIRES;
  353.  
  354.    if (ptilbmFrame->bmHdr.pageHeight > 200)
  355.       ns.ViewModes |= LACE;
  356.  
  357.    if (nPlanes == 6)
  358.       ns.ViewModes = HAM;
  359.  
  360.    if ((screen1 = (struct Screen *)OpenScreen(&ns))==NULL)    return(0);
  361.  
  362.    vport1 = &screen1->ViewPort;
  363.    LoadRGB4(vport1, &allBgColor[0], ptilbmFrame->nColorRegs);
  364.  
  365.    nw.Width  = dWidth;
  366.    nw.Height = dHeight;
  367.    nw.Screen = screen1;
  368.  
  369.    if ((window1 = (struct Window *)OpenWindow(&nw))==NULL)    return(0);
  370.  
  371.    ShowTitle(screen1, FALSE);
  372.  
  373.    if ((sWidth == dWidth) && (sHeight == dHeight))
  374.       {
  375.       destBitMap = (struct BitMap *)screen1->RastPort.BitMap;
  376.       }
  377.    else
  378.       {
  379.       InitBitMap( &tBitMap,
  380.                   nPlanes,
  381.                   sWidth,
  382.                   sHeight);
  383.  
  384.       plsize = RowBytes(ptilbmFrame->bmHdr.w) * ptilbmFrame->bmHdr.h;
  385.       if (tBitMap.Planes[0] =
  386.        (PLANEPTR)AllocMem(nPlanes * plsize, MEMF_CHIP))
  387.          {
  388.          for (i = 1; i < nPlanes; i++)
  389.             tBitMap.Planes[i] = (PLANEPTR)tBitMap.Planes[0] + plsize*i;
  390.          destBitMap = &tBitMap;
  391.          }
  392.       else
  393.          {
  394.          return(0);  /* can't allocate temp BitMap */
  395.          }
  396.       }
  397.    return(destBitMap);          /* destBitMap allocated */
  398.    }
  399.  
  400.  
  401. /** DisplayPic() *********************************************************
  402.  *
  403.  * Display loaded bitmap.  If tBitMap, first transfer to screen.
  404.  *
  405.  *************************************************************************/
  406. DisplayPic(ptilbmFrame)
  407.    ILBMFrame *ptilbmFrame;
  408.    {
  409.    int    i, row, byte, nrows, nbytes;
  410.    struct BitMap  *tbp, *sbp; /* temp and screen BitMap ptrs */
  411.    UBYTE  *tpp, *spp;         /* temp and screen plane ptrs  */
  412.  
  413.    if (tBitMap.Planes[0])     /* transfer from tBitMap if nec. */
  414.       {
  415.       tbp = &tBitMap;
  416.       sbp = screen1->RastPort.BitMap;
  417.       nrows  = MIN(tbp->Rows, sbp->Rows);
  418.       nbytes = MIN(tbp->BytesPerRow, sbp->BytesPerRow);
  419.  
  420.       for (i = 0; i < sbp->Depth; i++)
  421.          {
  422.          tpp = (UBYTE *)tbp->Planes[i];
  423.          spp = (UBYTE *)sbp->Planes[i];
  424.          for (row = 0; row < nrows; row++)
  425.             {
  426.             tpp = tbp->Planes[i] + (row * tbp->BytesPerRow);
  427.             spp = sbp->Planes[i] + (row * sbp->BytesPerRow);
  428.             for (byte = 0; byte < nbytes; byte++)
  429.                {
  430.                *spp++ = *tpp++;
  431.                }
  432.             }
  433.          }
  434.       /*  Can now deallocate the temp BitMap  */
  435.       FreeMem(tBitMap.Planes[0],
  436.                  tBitMap.BytesPerRow * tBitMap.Rows * tBitMap.Depth);
  437.       }
  438.  
  439.    vport1 = &screen1->ViewPort;
  440.    LoadRGB4(vport1, ptilbmFrame->colorMap, ptilbmFrame->nColorRegs);
  441.  
  442.    return(0);
  443.    }
  444.  
  445.  
  446. /** GetLiILBM() **********************************************************
  447.  *
  448.  * Called via ReadPicture to handle every LIST encountered in an IFF file.
  449.  *
  450.  *************************************************************************/
  451. #if Fancy
  452. IFFP GetLiILBM(parent)
  453. GroupContext *parent; {
  454.     ILBMFrame newFrame;   /* allocate a new Frame */
  455.  
  456.     newFrame = *(ILBMFrame *)parent->clientFrame;  /* copy parent frame */
  457.  
  458.     return( ReadIList(parent, (ClientFrame *)&newFrame) );
  459.     }
  460. #endif
  461.  
  462.  
  463. /** GetPrILBM() **********************************************************
  464.  *
  465.  * Called via ReadPicture to handle every PROP encountered in an IFF file.
  466.  * Reads PROPs ILBM and skips all others.
  467.  *
  468.  *************************************************************************/
  469. #if Fancy
  470. IFFP GetPrILBM(parent)
  471. GroupContext *parent; {
  472.    /*compilerBug register*/ IFFP iffp;
  473.    GroupContext propContext;
  474.    ILBMFrame *ilbmFrame = (ILBMFrame *)parent->clientFrame;
  475.  
  476.    if (parent->subtype != ID_ILBM)
  477.       return(IFF_OKAY);   /* just continue scaning the file */
  478.  
  479.    iffp = OpenRGroup(parent, &propContext);
  480.    CheckIFFP();
  481.  
  482.    do switch (iffp = GetPChunkHdr(&propContext)) {
  483.       case ID_BMHD: {
  484.          ilbmFrame->foundBMHD = TRUE;
  485.          iffp = GetBMHD(&propContext, &ilbmFrame->bmHdr);
  486.          break; }
  487.       case ID_CMAP: {
  488.          ilbmFrame->nColorRegs = maxColorReg; /* room for this many */
  489.          iffp = GetCMAP( &propContext, (WORD *)ilbmFrame->colorMap,
  490.                           &ilbmFrame->nColorRegs);
  491.          break; }
  492.  
  493.       } while (iffp >= IFF_OKAY);/* loop if valid ID of ignored chunk or
  494.                                   * subrtn returned IFF_OKAY (no errors).*/
  495.  
  496.    CloseRGroup(&propContext);
  497.    return(iffp == END_MARK ? IFF_OKAY : iffp);
  498.    }
  499. #endif
  500.  
  501.  
  502. /** GetFoILBM() **********************************************************
  503.  *
  504.  * Called via ReadPicture to handle every FORM encountered in an IFF file.
  505.  * Reads FORMs ILBM and skips all others.
  506.  * Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
  507.  * finds no BODY or if it has no BMHD to decode the BODY.
  508.  *
  509.  * Once we find a BODY chunk, we'll allocate the BitMap and read the image.
  510.  *
  511.  * Modified by C. Scheppner:  ilbmFrame moved above main making it
  512.  *                            global so main can call DisplayPic()
  513.  *
  514.  *************************************************************************/
  515. IFFP GetFoILBM(parent)
  516.    GroupContext *parent;
  517.    {
  518.    IFFP iffp;
  519.    GroupContext formContext;
  520.    BYTE buffer[bufSz];
  521.    struct BitMap *destBitMap;
  522.  
  523.    if (parent->subtype != ID_ILBM)
  524.       return(IFF_OKAY);   /* just continue scaning the file */
  525.  
  526.    ilbmFrame = *(ILBMFrame *)parent->clientFrame;
  527.    iffp = OpenRGroup(parent, &formContext);
  528.    CheckIFFP();
  529.  
  530.    do switch (iffp = GetFChunkHdr(&formContext)) {
  531.       case ID_BMHD: {
  532.          ilbmFrame.foundBMHD = TRUE;
  533.          iffp = GetBMHD(&formContext, &ilbmFrame.bmHdr);
  534.          break; }
  535.       case ID_CMAP: {
  536.          ilbmFrame.nColorRegs = maxColorReg;  /* we have room for this many */
  537.          iffp = GetCMAP(&formContext, (WORD *)ilbmFrame.colorMap,
  538.                            &ilbmFrame.nColorRegs);
  539.          break; }
  540.       case ID_BODY: {
  541.          if (!ilbmFrame.foundBMHD)  return(BAD_FORM);   /* No BMHD chunk! */
  542.  
  543.          if(destBitMap=(struct BitMap *)getBitMap(&ilbmFrame))
  544.             {
  545.             iffp = GetBODY( &formContext,
  546.                             destBitMap,
  547.                             NULL,
  548.                             &ilbmFrame.bmHdr,
  549.                             buffer,
  550.                             bufSz);
  551.             if (iffp == IFF_OKAY) iffp = IFF_DONE;   /* Eureka */
  552.             }
  553.          else
  554.             iffp = CLIENT_ERROR;   /* not enough RAM for the bitmap */
  555.          break; }
  556.  
  557.       case END_MARK: {
  558.          iffp = BAD_FORM;
  559.          break; }
  560.  
  561.    } while (iffp >= IFF_OKAY);  /* loop if valid ID of ignored chunk or a
  562.            * subroutine returned IFF_OKAY (no errors).*/
  563.  
  564.    if (iffp != IFF_DONE)  return(iffp);
  565.  
  566.    CloseRGroup(&formContext);
  567.    return(iffp);
  568.    }
  569.  
  570. /** Notes on extending GetFoILBM *****************************************
  571.  *
  572.  * To read more kinds of chunks, just add clauses to the switch statement.
  573.  * To read more kinds of property chunks (GRAB, CAMG, etc.) add clauses to
  574.  * the switch statement in GetPrILBM, too.
  575.  *
  576.  * To read a FORM type that contains a variable number of data chunks--e.g.
  577.  * a FORM FTXT with any number of CHRS chunks--replace the ID_BODY case with
  578.  * an ID_CHRS case that doesn't set iffp = IFF_DONE, and make the END_MARK
  579.  * case do whatever cleanup you need.
  580.  *
  581.  *************************************************************************/
  582.  
  583.  
  584. /** ReadPicture() ********************************************************
  585.  *
  586.  * Read a picture from an IFF file, given a file handle open for reading.
  587.  *
  588.  * Modified by Carolyn Scheppner   CBM   03-86
  589.  *   iFrame made global (above main)
  590.  *   Close(file) moved to main
  591.  *
  592.  *************************************************************************/
  593. IFFP ReadPicture(file)
  594.       LONG file;
  595.    {
  596.    IFFP iffp = IFF_OKAY;
  597.  
  598. #if Fancy
  599.    iFrame.clientFrame.getList = GetLiILBM;
  600.    iFrame.clientFrame.getProp = GetPrILBM;
  601. #else
  602.    iFrame.clientFrame.getList = SkipGroup;
  603.    iFrame.clientFrame.getProp = SkipGroup;
  604. #endif
  605.    iFrame.clientFrame.getForm = GetFoILBM;
  606.    iFrame.clientFrame.getCat  = ReadICat ;
  607.  
  608.    /* Initialize the top-level client frame's property settings to the
  609.     * program-wide defaults. This example just records that we haven't read
  610.     * any BMHD property or CMAP color registers yet. For the color map, that
  611.     * means the default is to leave the machine's color registers alone.
  612.     * If you want to read a property like GRAB, init it here to (0, 0). */
  613.    iFrame.foundBMHD  = FALSE;
  614.    iFrame.nColorRegs = 0;
  615.  
  616.    iffp = ReadIFF(file, (ClientFrame *)&iFrame);
  617.    return(iffp);
  618.    }
  619.  
  620.  
  621.