home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / new / gfx / edit / tsmorph / src / parse.c < prev    next >
C/C++ Source or Header  |  1994-02-23  |  10KB  |  443 lines

  1. /*  
  2.  * parse.c - iffparse file IO support module
  3.  *   based on some of looki.c by Leo Schwab
  4.  *
  5.  * The filename for clipboard is -c or -cUnit as in -c0 -c1 etc. (default 0)
  6.  */
  7.  
  8. // Minor changes to error handlin MJP
  9.  
  10. #include <exec/types.h>
  11.  
  12. #include "iffp/iff.h"
  13.  
  14. /* local function prototypes */
  15.  
  16. static LONG stdio_stream(struct Hook *, struct IFFHandle *, struct IFFStreamCmd *);
  17.  
  18. UBYTE *omodes[2] = {"r","w"};
  19.  
  20.  
  21. /* openifile
  22.  *
  23.  * Passed a ParseInfo structure with a not-in-use IFFHandle, filename
  24.  *   ("-c" or -cUnit like "-c1" for clipboard), and IFF open mode
  25.  *   (IFFF_READ or IFFF_WRITE) opens file or clipboard for use with
  26.  *   iffparse.library support modules.
  27.  *
  28.  * Returns 0 for success or an IFFERR (libraries/iffparse.h)
  29.  */
  30.  
  31. LONG openifile(struct ParseInfo *pi, UBYTE *filename, ULONG iffopenmode)
  32. {
  33.     struct IFFHandle    *iff;
  34.     BOOL    cboard;
  35.     ULONG     unit = PRIMARY_CLIP;
  36.     LONG     error;
  37.  
  38.     if(!pi)            return(CLIENT_ERROR);
  39.         if(!(iff=pi->iff))    return(CLIENT_ERROR);
  40.  
  41.     cboard = (*filename == '-'  &&  filename[1] == 'c');
  42.      if(cboard && filename[2])    unit = atoi(&filename[2]);
  43.  
  44.     if (cboard)
  45.         {
  46.         /*
  47.          * Set up IFFHandle for Clipboard I/O.
  48.          */
  49.         pi->clipboard = TRUE;
  50.         if (!(iff->iff_Stream =
  51.                 (ULONG)OpenClipboard(unit)))
  52.             {
  53. //            message(SI(MSG_IFFP_NOCLIP_D),unit);    // MJP
  54.             message(SI(MSG_IFFP_NOCLIP_D),NULL,5);    // MJP 5 = HE_IFFCLIP
  55.             return(NOFILE);
  56.             }
  57.         InitIFFasClip(iff);
  58.         }
  59.     else
  60.         {
  61.         pi->clipboard = FALSE;
  62.         /*
  63.          * Set up IFFHandle for buffered stdio I/O.
  64.          */
  65.         if (!(iff->iff_Stream = (ULONG)
  66.            fopen(filename, omodes[iffopenmode & 1])))
  67.             {
  68.             message(SI(MSG_IFFP_NOFILE_S),filename,7);    // MJP 7 = HE_IFFFileS
  69.             return(NOFILE);
  70.             }
  71.         else initiffasstdio(iff);
  72.         }
  73.  
  74.     D(bug("%s file opened: \n", cboard ? "[Clipboard]" : filename));
  75.  
  76.     pi->filename = filename;
  77.  
  78.     error=OpenIFF(iff, iffopenmode);
  79.  
  80.     pi->opened = error ? FALSE : TRUE;    /* currently open handle */
  81.  
  82.     D(bug("OpenIFF error = %ld\n",error));
  83.     return(error);
  84. }
  85.  
  86.  
  87. /* closeifile
  88.  *
  89.  * closes file or clipboard opened with openifile, and frees all
  90.  *   iffparse context parsed by parseifile.
  91.  *
  92.  * Note - You should closeifile as soon as possible if using clipboard
  93.  *   ("-c[n]").  You also need to closeifile if, for example, you wish to
  94.  *   reopen the file to write changes back out.  See the copychunks.c
  95.  *   module for routines which allow you clone the chunks iffparse has
  96.  *   gathered so that you can closeifile and still be able to modify and
  97.  *   write back out gathered chunks.
  98.  *   
  99.  */
  100.  
  101. void closeifile(struct ParseInfo *pi)
  102. {
  103. struct IFFHandle *iff;
  104.  
  105.     D(bug("closeifile:\n"));
  106.  
  107.     if(!pi)            return;
  108.         if(!(iff=pi->iff))    return;
  109.  
  110.     DD(bug("closeifile: About to CloseIFF if open, iff=$%lx, opened=%ld\n",
  111.             iff, pi->opened));
  112.  
  113.     if(pi->opened)    CloseIFF(iff);
  114.  
  115.     DD(bug("closeifile: About to close %s, stream=$%lx\n",
  116.             pi->clipboard ? "clipboard" : "file", iff->iff_Stream));
  117.     if(iff->iff_Stream)
  118.         {
  119.         if (pi->clipboard)
  120.            CloseClipboard((struct ClipboardHandle *)(iff->iff_Stream));    // MJP
  121.         else
  122.            fclose ((FILE *)(iff->iff_Stream));
  123.         }
  124.  
  125.     iff->iff_Stream = NULL;
  126.     pi->clipboard = NULL;
  127.     pi->opened = NULL;
  128. }
  129.  
  130.  
  131. /* parseifile
  132.  *
  133.  * Passed a ParseInfo with an initialized and open IFFHandle,
  134.  *  grouptype (like ID_FORM), groupid (like ID_ILBM),
  135.  *  and TAG_DONE terminated longword arrays of type,id
  136.  *  for chunks to be grabbed, gathered, and stopped on
  137.  *  (like { ID_ILBM, ID_BMHD, ID_ILBM, ID_CAMG, TAG_DONE })
  138.  *  will parse an IFF file, grabbing/gathering and stopping
  139.  *  on specified chunk.
  140.  *
  141.  * Note - you can call getcontext() (to continue after a stop chunk) or
  142.  *  nextcontext() (after IFFERR_EOC, to parse next form in the same file)
  143.  *  if you wish to continue parsing the same IFF file.  If parseifile()
  144.  *  has to delve into a complex format to find your desired FORM, the
  145.  *  pi->hunt flag will be set.  This should be a signal to you that
  146.  *  you may not have the capability to simply modify and rewrite
  147.  *  the data you have gathered.
  148.  *
  149.  * Returns 0 for success else and IFFERR (libraries/iffparse.h)
  150.  */ 
  151.  
  152. LONG parseifile(pi,groupid,grouptype,propchks,collectchks,stopchks)
  153. struct    ParseInfo *pi;
  154. LONG groupid, grouptype;
  155. LONG *propchks, *collectchks, *stopchks;
  156. {
  157. struct IFFHandle *iff;    
  158. register struct ContextNode    *cn;
  159. LONG            error = 0L;
  160.  
  161.  
  162.         if(!(iff=pi->iff))    return(CLIENT_ERROR);
  163.  
  164.     if(!iff->iff_Stream)    return(IFFERR_READ);
  165.  
  166.     pi->hunt = FALSE;
  167.  
  168.     /*
  169.      * Declare property, collection and stop chunks.
  170.      */
  171.     if (propchks)
  172.       if (error = PropChunks (iff, propchks, chkcnt(propchks)))
  173.         return (error);
  174.     if (collectchks)
  175.       if (error =
  176.           CollectionChunks(iff, collectchks, chkcnt(collectchks)))
  177.         return (error);
  178.     if (stopchks)
  179.       if (error = StopChunks (iff, stopchks, chkcnt(stopchks)))
  180.         return (error);
  181.  
  182.     /*
  183.      * We want to stop at the end of an ILBM context.
  184.      */
  185.     if (grouptype)
  186.       if (error = StopOnExit (iff, grouptype, groupid))
  187.         return(error);
  188.  
  189.     /*
  190.      * Take first parse step to enter main chunk.
  191.      */
  192.     if (error = ParseIFF (iff, IFFPARSE_STEP))
  193.         return(error);
  194.  
  195.     /*
  196.      * Test the chunk info to see if simple form of type we want (ILBM).
  197.      */
  198.     if (!(cn = CurrentChunk (iff)))
  199.         {
  200.         /*
  201.          * This really should never happen.  If it does, it means
  202.          * our parser is broken.
  203.          */
  204.         message(SI(MSG_IFFP_NOTOP),NULL,8);        // MJP 8 = HE_IFFTOP
  205.         return(NOFILE);
  206.         }
  207.  
  208.     if (cn->cn_ID != groupid  ||  cn->cn_Type != grouptype)
  209.         {
  210.         
  211.         D(bug("This is a(n) %.4s.%.4s.  Looking for embedded %.4s's...\n",
  212.           &cn->cn_Type, &cn->cn_ID, &grouptype));
  213.  
  214.         pi->hunt = TRUE;    /* Warning - this is a complex file */
  215.         }
  216.  
  217.     if(!error)    error = getcontext(iff);
  218.     return(error);
  219. }
  220.  
  221. /* chkcnt
  222.  *
  223.  * simply counts the number of chunk pairs (type,id) in array
  224.  */
  225. LONG chkcnt(LONG *taggedarray)
  226. {
  227. LONG k = 0;
  228.  
  229.     while(taggedarray[k] != TAG_DONE) k++;
  230.     return(k>>1);
  231. }
  232.  
  233.  
  234. /* currentchunkis
  235.  *
  236.  * returns the ID of the current chunk (like ID_CAMG)
  237.  */
  238. LONG currentchunkis(struct IFFHandle *iff, LONG type, LONG id)
  239. {
  240. register struct ContextNode    *cn;
  241. LONG result = 0;
  242.  
  243.     if (cn = CurrentChunk (iff))
  244.         {
  245.         if((cn->cn_Type == type)&&(cn->cn_ID == id)) result = 1;
  246.         }
  247.     return(result);
  248. }
  249.  
  250.  
  251. /* contextis
  252.  *
  253.  * returns the enclosing context of the current chunk (like ID_ILBM)
  254.  */
  255. LONG contextis(struct IFFHandle *iff, LONG type, LONG id)
  256. {
  257. register struct ContextNode    *cn;
  258. LONG result = 0;
  259.  
  260.        if (cn = (CurrentChunk (iff)))
  261.            {
  262.            if (cn = (ParentChunk(cn)))
  263.                {
  264.                if((cn->cn_Type == type)&&(cn->cn_ID == id)) result = 1;
  265.                }
  266.        }
  267.  
  268.     D(bug("This is a %.4s %.4s\n",&cn->cn_Type,&cn->cn_ID));
  269.  
  270.     return(result);
  271. }
  272.  
  273.  
  274. /* getcontext()
  275.  *
  276.  * Continues to gather the context which was specified to parseifile(),
  277.  *  stopping at specified stop chunk, or end of context, or EOF
  278.  *
  279.  * Returns 0 (stopped on a stop chunk)
  280.  *      or IFFERR_EOC (end of context, not an error)
  281.  *      or IFFER_EOF (end of file)
  282.  */
  283. LONG getcontext(iff)
  284. struct    IFFHandle *iff;
  285. {
  286.     LONG error = 0L;
  287.  
  288.     /* Based on our parse initialization,
  289.      * ParseIFF() will return on a stop chunk (error = 0)
  290.      * or end of context for an ILBM FORM (error = IFFERR_EOC)
  291.      * or end of file (error = IFFERR_EOF)
  292.      */
  293.     return(error = ParseIFF(iff, IFFPARSE_SCAN));
  294. }
  295.  
  296.  
  297. /* nextcontext
  298.  *
  299.  * If you have finished parsing and reading your context (IFFERR_EOC),
  300.  *   nextcontext will enter the next context contained in the file
  301.  *   and parse it.
  302.  *
  303.  * Returns 0 or an IFFERR such as IFFERR_EOF (end of file)
  304.  */
  305.  
  306. LONG nextcontext(iff)
  307. struct    IFFHandle *iff;
  308. {
  309.     LONG error = 0L;
  310.  
  311.     error = ParseIFF(iff, IFFPARSE_STEP);
  312.  
  313.     D(bug("nextcontext: Got through next step\n"));
  314.  
  315.     return(error);
  316. }
  317.  
  318.  
  319. /* findpropdata
  320.  *
  321.  * finds specified chunk parsed from IFF file, and
  322.  *   returns pointer to its sp_Data (or 0 for not found)
  323.  */
  324. UBYTE *findpropdata(iff, type, id)
  325. struct IFFHandle    *iff;
  326. LONG type, id;
  327.     {
  328.     register struct StoredProperty    *sp;
  329.  
  330.     if(sp = FindProp (iff, type, id)) return(sp->sp_Data);
  331.     return(0);
  332.     }
  333.  
  334.  
  335. /*
  336.  * File I/O hook functions which the IFF library will call.
  337.  * A return of 0 indicates success (no error).
  338.  *
  339.  * Iffparse.library calls this code via struct Hook and Hook.asm
  340.  */
  341. static LONG
  342. stdio_stream (struct Hook *hook, struct IFFHandle *if