home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Atlanta_1990 / Atlanta-Devcon.2 / Libraries / IFFParse / Examples / tiff2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-26  |  10.3 KB  |  474 lines

  1. /*  :ts=8 bk=0
  2.  *
  3.  * tiff2.c:    Frame concept ILBM scanner.
  4.  *         Alpha Concept Prototype.
  5.  *
  6.  * All the code needed for an ILBM reader, except the stuff to process the
  7.  * ILBM itself.  New one with a twist - the "frame" idea.
  8.  *
  9.  * Managing all the interactions of end of context and properties and
  10.  * data chunks is kind of a hassle to get right without groking all the
  11.  * complexities of recursive data structures and parsing, etc.  Frames
  12.  * are an idea to make things a little easier.  The client just creates
  13.  * a frame structure and a couple of handlers for dealing with them in
  14.  * a generic way.  Then the client just has to fill in the details of the
  15.  * frame by handling data chunks himself.  At the end of the context, 
  16.  * the client gets handed a completed frame and he can go about his
  17.  * business without concern for what got partly done or whatever.
  18.  *
  19.  * NOTE: This sucker ain't, like, totally done.
  20.  *
  21.  * Stuart Ferguson                    8901.02
  22.  * ewhac (Updated to 1.4 Beta)                8912.06
  23.  * Latticeification                    9005.31
  24.  */
  25. #include <exec/types.h>
  26. #include <libraries/dos.h>
  27. #include <utility/hooks.h>
  28. #include <libraries/iffparse.h>
  29. #include <clib/exec_protos.h>
  30. #include <clib/dos_protos.h>
  31. #include "iffparse_protos.h"
  32. #include "iffparse.p"
  33.  
  34. #define    ID_ILBM    MAKE_ID('I','L','B','M')
  35. #define    ID_BODY    MAKE_ID('B','O','D','Y')
  36. #define    ID_BMHD    MAKE_ID('B','M','H','D')
  37. #define    ID_CMAP    MAKE_ID('C','M','A','P')
  38. #define    ID_CAMG    MAKE_ID('C','A','M','G')
  39. #define    ID_CRNG    MAKE_ID('C','R','N','G')
  40.  
  41.  
  42. /*
  43.  * Forward function declarations.  (I hate ANSI.)
  44.  */
  45. struct Frame *FindFrame (struct IFFHandle *, LONG);
  46. LONG MakeFrame (struct IFFHandle *, LONG, struct Frame *(*)(), LONG (*)());
  47. LONG __saveds __asm EnterFrame (register __a0 struct Hook *, register __a2 struct IFFHandle *, register __a1 LONG *);
  48. LONG __saveds __asm FramePurge (register __a0 struct Hook *, register __a2 struct LocalContextItem *, register __a1 LONG *);
  49. void DisplayILBM (struct ILBMframe *);
  50. void ProcessBody (struct IFFHandle *, struct ILBMframe *);
  51. void ProcessCycle (struct IFFHandle *, struct ILBMframe *);
  52. static struct ILBMframe *CreateILBMframe (struct IFFHandle *);
  53. static LONG FreeILBMframe (struct ILBMframe *);
  54.  
  55. static long    ilbmprops[] = {
  56.     ID_ILBM, ID_BMHD,
  57.     ID_ILBM, ID_CMAP,
  58.     ID_ILBM, ID_CAMG
  59. };
  60.  
  61. static long    ilbmstops[] = {
  62.     ID_ILBM, ID_BODY,
  63.     ID_ILBM, ID_CRNG,
  64. };
  65.  
  66.  
  67. #define MAXCRNG    8
  68.  
  69. /*
  70.  * The "Frame" for a complete ILBM.  This stupid one will just be the
  71.  * sizes of each chunk (just to show that it works).
  72.  */
  73. struct ILBMframe {
  74.     LONG bmhd,body,cmap,camg;
  75.     int ncrng;
  76.     LONG crng[MAXCRNG];
  77. };
  78.  
  79.  
  80. struct Library    *IFFParseBase;
  81.  
  82.  
  83. main (argc, argv)
  84. int    argc;
  85. char    **argv;
  86. {
  87.     struct IFFHandle    *iff;
  88.     struct ContextNode    *top;
  89.     struct ILBMframe    *fr;
  90.     long            error;
  91.     int            foundilbm = 0;
  92.  
  93.     if (!(IFFParseBase = OpenLibrary ("iffparse.library", 0L))) {
  94.         puts ("Cannot open library.");
  95.         goto die;
  96.     }
  97.  
  98.     /*
  99.      * Create IFF file and open a DOS stream on it.
  100.      */
  101.     if (!(iff = AllocIFF())) {
  102.         puts ("AllocIFF() failed.");
  103.         goto die;
  104.     }
  105.  
  106.     if (!(iff -> iff_Stream = Open (argv[1], MODE_OLDFILE))) {
  107.         puts ("File open failed.");
  108.         goto die;
  109.     }
  110.     InitIFFasDOS (iff);
  111.  
  112.     /*
  113.      * Declare frame handlers for the ILBM format.
  114.      */
  115.     if (error = MakeFrame (iff, ID_ILBM, CreateILBMframe, FreeILBMframe))
  116.         goto err;
  117.  
  118.     /*
  119.      * Declare property, collection and stop chunks.
  120.      * (You still have to do this because YOU handle the data.)
  121.      */
  122.     if (error = PropChunks (iff, ilbmprops, 3L))
  123.         goto err;
  124.     if (error = StopChunks (iff, ilbmstops, 2L))
  125.         goto err;
  126.  
  127.     if (error = OpenIFF (iff, IFFF_READ))
  128.         goto err;
  129.  
  130.     error = 0;
  131.     while (!error) {
  132.         /*
  133.          * ParseIFF() will return on BODY and CRNG chunks
  134.          * or when the frame is filled.  In any case, we 
  135.          * should nab a frame for this context (even if
  136.          * it's really NULL).
  137.          */
  138.         error = ParseIFF (iff, IFFPARSE_SCAN);
  139.         fr = (struct ILBMframe *) FindFrame (iff, ID_ILBM);
  140.  
  141.         /*
  142.          * At end of context, do something with the finished frame.
  143.          * This code will scan and do the same thing with all the
  144.          * ILBM FORM's in the file.
  145.          */
  146.         if (error == IFFERR_EOC) {
  147.             foundilbm = 1;
  148.             DisplayILBM (fr);
  149.             error = 0;
  150.             continue;
  151.         }
  152.  
  153.         /*
  154.          * Other errors are real and possibily nasty errors.
  155.          */
  156.         if (error)
  157.             break;
  158.  
  159.         /*
  160.          * We've hit data.  Switch and decode.
  161.          * Make sure it's inside a FORM, otherwise storing
  162.          * data into the frame (if there even is one) is wrong.
  163.          */
  164.         top = CurrentChunk (iff);
  165.         if (ParentChunk (top) -> cn_ID == ID_FORM)
  166.             switch (top -> cn_ID) {
  167.                 case ID_BODY:
  168.                 ProcessBody (iff, fr);
  169.                 break;
  170.                 case ID_CRNG:
  171.                 ProcessCycle (iff, fr);
  172.                 break;
  173.             }
  174.     }
  175. err:
  176.     if (error == IFFERR_EOF) {
  177.         if (foundilbm)
  178.             puts ("File scan complete.");
  179.         else
  180.             puts ("Failed to find a FORM ILBM.");
  181.     } else
  182.         printf ("File scan aborted (%ld)\n", error);
  183.  
  184. die:
  185.     if (iff) {
  186.         CloseIFF (iff);
  187.         if (iff -> iff_Stream)
  188.             Close (iff -> iff_Stream);
  189.         FreeIFF (iff);
  190.     }
  191.  
  192.     if (IFFParseBase)    CloseLibrary (IFFParseBase);
  193. }
  194.  
  195.  
  196. /*
  197.  * Just show that something happened.
  198.  */
  199. void
  200. DisplayILBM (fr)
  201. struct ILBMframe    *fr;
  202. {
  203.     int    i;
  204.  
  205.     printf ("A Picture:  BMHD:%ld, CMAP:%ld, CAMG:%ld, BODY:%ld\n",
  206.         fr -> bmhd, fr -> cmap, fr -> camg, fr -> body);
  207.     if (fr -> ncrng) {
  208.         for (i = 0; i < fr -> ncrng; i++)
  209.             printf ("CRNG:%ld  ", fr -> crng[i]);
  210.         printf ("\n");
  211.     } else
  212.         printf ("No CRNG chunks.\n");
  213. }
  214.  
  215.  
  216. /*
  217.  * Process a BODY chunk in an ILBM.  Just get the sizes of the various
  218.  * properties and data for now.
  219.  */
  220. void
  221. ProcessBody (iff, fr)
  222. struct IFFHandle     *iff;
  223. struct ILBMframe    *fr;
  224. {
  225.     register struct StoredProperty    *sp;
  226.  
  227.     printf ("Body.\n");
  228.  
  229.     if (sp = FindProp (iff, ID_ILBM, ID_BMHD))
  230.         fr -> bmhd = sp -> sp_Size;
  231.  
  232.     if (sp = FindProp (iff, ID_ILBM, ID_CMAP))
  233.         fr -> cmap = sp -> sp_Size;
  234.  
  235.     if (sp = FindProp (iff, ID_ILBM, ID_CAMG))
  236.         fr -> camg = sp -> sp_Size;
  237.  
  238.     fr -> body = CurrentChunk (iff) -> cn_Size;
  239. }
  240.  
  241.  
  242. void
  243. ProcessCycle (iff, fr)
  244. struct IFFHandle     *iff;
  245. struct ILBMframe    *fr;
  246. {
  247.     printf ("Cycle.\n");
  248.  
  249.     fr -> crng[fr -> ncrng ++] = CurrentChunk (iff) -> cn_Size;
  250. }
  251.  
  252.  
  253. /*
  254.  * Demi-handler to create a new frame and init to default values.
  255.  * The IFF is provided in case any default values are there.
  256.  */
  257. static struct ILBMframe *
  258. CreateILBMframe (iff)
  259. struct IFFHandle    *iff;
  260. {
  261.     struct ILBMframe    *f;
  262.  
  263.     if (!(f = (struct ILBMframe *) AllocMem ((LONG) sizeof (*f), 0L)))
  264.         return NULL;
  265.     printf ("Creating new frame: %lx\n", f);
  266.  
  267.     f -> bmhd = f -> body = f -> cmap = f -> camg = -1;
  268.     f -> ncrng = 0;
  269.     return f;
  270. }
  271.  
  272.  
  273. /*
  274.  * Client call-back to free up his frame.  Deletes frame and all
  275.  * associated memory.
  276.  */
  277. static LONG
  278. FreeILBMframe (f)
  279. struct ILBMframe    *f;
  280. {
  281.     printf ("Freeing frame: %lx\n", f);
  282.     FreeMem (f, (LONG) sizeof (*f));
  283.     return (0);
  284. }
  285.  
  286.  
  287. /*
  288.  * ====
  289.  * This stuff would be in the library to make the Frame management
  290.  * capability available to all.
  291.  * ====
  292.  */
  293.  
  294. struct FrameDescriptor {
  295.     struct Frame        *(*fd_Create)();
  296.     LONG            (*fd_Delete)();
  297. };
  298.  
  299. struct FrameInstance {
  300.     struct Frame        *fi_Frame;
  301.     struct IFFHandle    *fi_iff;    /*  We need this pointer  */
  302. };
  303.  
  304. #define IFFLCI_FRAMEDESC    MAKE_ID('f','d','e','s')
  305. #define IFFLCI_FRAME        MAKE_ID('f','r','a','m')
  306.  
  307. /*
  308.  * Declare the handlers for a frame.  Client provides functions for
  309.  * creating and deleting frames and the library will call them at the
  310.  * appropriate times (entering and exiting the specified FORM).  These
  311.  * function vectors get stored in a frame descriptor which will be
  312.  * used by the generic entry and exit handlers.
  313.  */
  314. LONG
  315. MakeFrame (iff, type, create_f, delete_f)
  316. struct IFFHandle *iff;
  317. LONG         type;
  318. struct Frame     *(*create_f)();
  319. LONG         (*delete_f)();
  320. {
  321.     register struct LocalContextItem *lci;
  322.     register struct FrameDescriptor     *fd;
  323.     register LONG             error;
  324.     static struct Hook         EnterHook = {
  325.         { NULL },
  326.         (ULONG (*)()) EnterFrame,
  327.         NULL,
  328.         NULL
  329.     };
  330.  
  331.     if (!(lci = AllocLocalItem (type, 0L, IFFLCI_FRAMEDESC,
  332.                     (long) sizeof (*fd))))
  333.         return (IFFERR_NOMEM);
  334.  
  335.     fd = (struct FrameDescriptor *) LocalItemData (lci);
  336.     fd -> fd_Create = create_f;
  337.     fd -> fd_Delete = delete_f;
  338.  
  339.     if (error = StoreLocalItem (iff, lci, IFFSLI_TOP))
  340.         goto fail;
  341.     if (error = EntryHandler
  342.              (iff, type, ID_FORM, IFFSLI_TOP, &EnterHook, (APTR)iff))
  343.         goto fail;
  344.     if (error = StopOnExit (iff, type, ID_FORM))
  345.         goto fail;
  346.     return (0);
  347.  
  348. fail:
  349.     FreeLocalItem (lci);
  350.     return (error);
  351. }
  352.  
  353.  
  354. /*
  355.  * Returns the current frame for the given context.
  356.  */
  357. struct Frame *
  358. FindFrame (iff, type)
  359. struct IFFHandle *iff;
  360. LONG         type;
  361. {
  362.     struct LocalContextItem *lci;
  363.  
  364.     if (!(lci = FindLocalItem (iff, type, 0L, IFFLCI_FRAME)))
  365.         return (NULL);
  366.  
  367.     return (((struct FrameInstance *) LocalItemData (lci)) -> fi_Frame);
  368. }
  369.  
  370.  
  371. /*
  372.  * On entering the FORM associated with a frame, create a new
  373.  * frame and store it for this context.
  374.  */
  375. LONG __saveds __asm
  376. EnterFrame (
  377. register __a0 struct Hook    *hook,
  378. register __a2 struct IFFHandle    *iff,
  379. register __a1 LONG        *cmd
  380. )
  381. {
  382.     struct LocalContextItem *lci;
  383.     struct ContextNode    *cn;
  384.     struct FrameInstance    *fi;
  385.     struct FrameDescriptor    *fd;
  386.     LONG            error, type;
  387.     static struct Hook    PurgeHook = {
  388.         { NULL },
  389.         (ULONG (*)()) FramePurge,
  390.         NULL,
  391.         NULL
  392.     };
  393.  
  394.     cn = CurrentChunk (iff);
  395.     type = cn -> cn_Type;
  396.  
  397.     if (!(lci = FindLocalItem (iff, type, 0L, IFFLCI_FRAMEDESC))) {
  398.         puts ("It's where you thought.");
  399.         return (IFFERR_NOSCOPE);
  400.     }
  401.  
  402.     fd = (struct FrameDescriptor *) LocalItemData (lci);
  403.  
  404.     if (!(lci = AllocLocalItem (type, 0L, IFFLCI_FRAME,
  405.                     (LONG) sizeof (*fi))))
  406.         return (IFFERR_NOMEM);
  407.     fi = (struct FrameInstance *) LocalItemData (lci);
  408.  
  409.     fi -> fi_iff = iff;
  410.     if (!(fi -> fi_Frame = (*(fd -> fd_Create)) (iff))) {
  411.         error = IFFERR_NOMEM;
  412.         goto fail;
  413.     }
  414.     SetLocalItemPurge (lci, &PurgeHook);
  415.  
  416.     if (error = StoreLocalItem (iff, lci, IFFSLI_TOP))
  417.         goto fail;
  418.     return (0);
  419.  
  420. fail:
  421.     FreeLocalItem (lci);
  422.     return (error);
  423. }
  424.  
  425.  
  426. /* What's this, Stu?
  427.  *
  428.  * Hmmm..  What's what?  <whistle, whistle ...>
  429.  *
  430. static LONG
  431. ExitFrame (hook, iff, cn)
  432. struct Hook        *hook;
  433. struct IFFHandle    *iff;
  434. LONG            *cmd;
  435. {
  436. }
  437.  *
  438.  */
  439.  
  440.  
  441. LONG __saveds __asm
  442. FramePurge (
  443. register __a0 struct Hook        *hook,
  444. register __a2 struct LocalContextItem    *lci,
  445. register __a1 LONG            *cmd
  446. )
  447. {
  448.     struct FrameInstance    *fi;
  449.     struct FrameDescriptor    *fd;
  450.  
  451.     fi = (struct FrameInstance *) LocalItemData (lci);
  452.  
  453.     fd = (struct FrameDescriptor *) LocalItemData (FindLocalItem
  454.         (fi -> fi_iff, lci -> lci_Type, 0L, IFFLCI_FRAMEDESC));
  455.  
  456.     (*(fd -> fd_Delete)) (fi -> fi_Frame);
  457.  
  458.     FreeLocalItem (lci);
  459.     return (0);
  460. }
  461.  
  462. /*
  463.  * Disable Lattice's default ^C trap.
  464.  */
  465. chkabort ()
  466. {
  467.     return (0);
  468. }
  469.  
  470. CXBRK ()
  471. {
  472.     return (0);
  473. }
  474.