home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 493.lha / SmallIFFParseLibrary / sources / handleiff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-06  |  10.8 KB  |  491 lines

  1. /*
  2. **
  3. **
  4. **
  5. **
  6. **
  7. */
  8. #include "handleiff.h"
  9. #include "undefs.h"
  10. #include "iffparse.pra"
  11. #include <ctype.h>
  12.  
  13. /*#####################*\
  14.  * Internal functions. *
  15. \*#####################*/
  16. /****************************\
  17.  * Name:     SeekStream     *
  18.  * Function: Move forward   *
  19.  * or backward in the file  *
  20.  * or in the clipboard      *
  21.  * relative where we are.   *
  22. \****************************/
  23. long
  24. SeekStream(struct IFF *iff, long delta)
  25. {
  26.     long error;
  27.  
  28.     geta4();
  29.     TraceCall;
  30.     if (iff->iff_Type==IOREQUEST) {
  31.         IOReq(iff)->io_Offset += delta;
  32.         error = SUCCESS;
  33.     } else {
  34.         if ((error = Seek(File(iff), delta, (long)OFFSET_CURRENT))>0)
  35.             error = SUCCESS;
  36.     }
  37.     return error;
  38. }
  39.  
  40. /*******************************\
  41.  * Name:     WriteStream       *
  42.  * Function: Write data to the *
  43.  * stream (a file or the clip- *
  44.  * board).                     *
  45. \*******************************/
  46. long 
  47. WriteStream(
  48.     struct IFF *iff, 
  49.     UBYTE *data, 
  50.     long length)  
  51. {
  52.     long error;
  53.  
  54.     geta4();
  55.     TraceCall;
  56.     if (iff->iff_Type==IOREQUEST) {
  57.         IOReq(iff)->io_Command = CMD_WRITE;
  58.         IOReq(iff)->io_Data = (UBYTE *)data;
  59.         IOReq(iff)->io_Length = (long)length;
  60.         DoClipIO(IOReq(iff));
  61.         error = (long)-IOReq(iff)->io_Error;
  62.     } else {
  63.         error = Write(File(iff), (char *)data, length);
  64.     }
  65.     if (error>0)
  66.         error = 0L;
  67.     return error;
  68. }
  69.  
  70. /********************************\
  71.  * Name:     ReadStream         *
  72.  * Function: Read data from the *
  73.  * device (a file or the clip-  *
  74.  * board).                      *
  75. \********************************/
  76. long
  77. ReadStream(struct IFF *iff, UBYTE *data, long length)  
  78. {
  79.     long error;
  80.  
  81.     geta4();
  82.     TraceCall;
  83.     if (iff->iff_Type==IOREQUEST) {
  84.         IOReq(iff)->io_Command = CMD_READ;
  85.         IOReq(iff)->io_Data = (UBYTE *)data;
  86.         IOReq(iff)->io_Length = (long)length;
  87.         DoClipIO(IOReq(iff));
  88.         if (IOReq(iff)->io_Error==0)
  89.             error = IOReq(iff)->io_Actual;
  90.         else
  91.             error = (long)-IOReq(iff)->io_Error;
  92.     } else {
  93.         error = Read(File(iff), (char *)data, length);
  94.     }
  95.     return error;
  96. }
  97.  
  98. /********************************\
  99.  * Name:     AlignStream        *
  100.  * Function: Align the read     *
  101.  * data so that it will be an   *
  102.  * even number of bytes.        *
  103. \********************************/
  104. long
  105. AlignStream(struct IFF *iff)
  106. {
  107.     long error;
  108.     
  109.     geta4();
  110.     TraceCall;
  111.     if (iff->iff_Type==IOREQUEST) {
  112.         if (IOReq(iff)->io_Offset%2)
  113.             IOReq(iff)->io_Offset++;
  114.         error = 0L;
  115.     } else {
  116.         if (Seek(File(iff), 0L, (long)OFFSET_CURRENT)%2)
  117.             error = Seek(File(iff), 1L, (long)OFFSET_CURRENT);
  118.     }
  119.     if (error>0L)
  120.         error = 0L;
  121.     return error;
  122. }
  123.  
  124.  
  125. /*############################*\
  126.  * Public iffparse functions. *
  127. \*############################*/
  128. /********************\
  129.  * Initializations. *
  130. \********************/
  131. long
  132. InitIFFasClip(struct IFF *iff)    
  133. {
  134.     geta4();
  135.     TraceCall;
  136.     iff->iff_Type = IOREQUEST;
  137.     return SUCCESS;
  138. }
  139.  
  140. long
  141. InitIFFasDOS(struct IFF *iff)
  142. {
  143.     geta4();
  144.     TraceCall;
  145.     iff->iff_Type = FILEHANDLE;
  146.     return SUCCESS;
  147. }
  148.  
  149. long
  150. OpenIFF(struct IFF *iff, long rwmode)
  151. {
  152.     geta4();
  153.     TraceCall;
  154.     IFFptr = 0;
  155.     IFFStack[0].Size = 0;
  156.     iff->iff_Flags = rwmode;
  157.     if (iff->iff_Type==IOREQUEST) {
  158.         if (rwmode==IFFF_READ)
  159.             IOReq(iff)->io_Command = CMD_READ;
  160.         else
  161.             IOReq(iff)->io_Command = CMD_WRITE;
  162.         IOReq(iff)->io_Offset = 0;
  163.         IOReq(iff)->io_ClipID = 0;
  164.     }
  165.     return SUCCESS;
  166. }
  167.  
  168. void
  169. CloseIFF(struct IFF *iff)
  170. {
  171.     geta4();
  172.     TraceCall;
  173.     if (iff->iff_Type==IOREQUEST) {
  174.         if ((iff->iff_Flags&IFFF_RWBITS)==IFFF_WRITE) { /* Make the clip public. */
  175.             IOReq(iff)->io_Command = CMD_UPDATE;
  176.             DoClipIO(IOReq(iff));
  177.         } else {                        /* Flush the stuff that is not used. */
  178.             long dummy;
  179.             while (IOReq(iff)->io_Actual && !IOReq(iff)->io_Error) {
  180.                 IOReq(iff)->io_Data = (STRPTR)&dummy;
  181.                 IOReq(iff)->io_Length = 4;
  182.                 DoClipIO(IOReq(iff));
  183.             }
  184.         }
  185.     }
  186. }
  187.  
  188. struct IFF *
  189. AllocIFF(void)
  190. {
  191.     struct IFF *iff;
  192.  
  193.     geta4();
  194.     TraceCall;
  195.     iff = NULL;
  196.     if ((iff = AllocMem((long)sizeof(struct IFF), MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  197.         return NULL;
  198.  
  199.     if ((iff->iff_Stack = AllocMem((long)sizeof(long)*256L, 0L))==NULL) {
  200.         FreeMem((APTR)iff, (long)sizeof(struct IFF));
  201.         iff = NULL;
  202.     }
  203.     return iff;
  204. }
  205.    
  206. void
  207. FreeIFF(struct IFF *iff)
  208. {
  209.     geta4();
  210.     TraceCall;
  211.     if (iff) {
  212.         if (iff->iff_Stack)
  213.             FreeMem((APTR)iff->iff_Stack, (long)sizeof(long)*256L);
  214.         FreeMem((APTR)iff, (long)sizeof(struct IFF));
  215.     }
  216. }
  217.             
  218. struct CBHandle *
  219. OpenClipboard(long unit)
  220. {
  221.     struct Library *IFFParseBase;
  222.     struct CBHandle *ch = NULL;
  223.  
  224.     geta4();
  225.     TraceCall;
  226.     if ((ch = AllocMem((long)sizeof(struct CBHandle), MEMF_CLEAR))==NULL)
  227.         goto fail;
  228.     if ((ch->cbh_CBport = CreatePort(0L, 0L))==NULL)
  229.         goto fail;
  230.     if ((ch->cbh_SatisfyPort = CreatePort(0L, 0L))==NULL)
  231.         goto fail;
  232.     if ((ch->cbh_Req = (struct IOClipReq *)CreateExtIO(ch->cbh_CBport, 
  233.                                                 (long)sizeof(struct IOClipReq)))==NULL)
  234.         goto fail;
  235.     if (OpenDevice("clipboard.device", unit, (struct IORequest *)ch->cbh_Req, 0L)) {
  236.         DeleteExtIO((struct IORequest *)ch->cbh_Req);
  237.         ch->cbh_Req = NULL;
  238.         goto fail;
  239.     }
  240.  
  241.     return ch;
  242.  
  243. fail:
  244.     CloseClipboard(ch);
  245.     return NULL;
  246. }
  247.  
  248. void
  249. CloseClipboard(struct CBHandle *ch)
  250. {
  251.     geta4();
  252.     TraceCall;
  253.     if (ch->cbh_Req) {
  254.         CloseDevice((struct IORequest *)ch->cbh_Req);
  255.         DeleteExtIO((struct IORequest *)ch->cbh_Req);
  256.         ch->cbh_Req = NULL;
  257.     }
  258.     if (ch->cbh_CBport)
  259.         DeletePort((struct MsgPort *)ch->cbh_CBport);
  260.     if (ch->cbh_SatisfyPort)
  261.         DeletePort((struct MsgPort *)ch->cbh_SatisfyPort);
  262.     if (ch)
  263.         FreeMem((APTR)ch, (long)sizeof(struct CBHandle));
  264. }
  265.  
  266. /*************************\
  267.  * Miscelous functions . *
  268. \*************************/
  269. long
  270. NOOP()
  271. {
  272.     geta4();
  273.     TraceCall;
  274.     return FAILED;
  275. }
  276.  
  277. void *
  278. NULL_NOOP()
  279. {
  280.     geta4();
  281.     TraceCall;
  282.     return NULL;
  283. }
  284.  
  285. UBYTE *
  286. IDtoStr(long ID, UBYTE *buf)
  287. {
  288.     geta4();
  289.     TraceCall;
  290.     *((long *)buf) = ID;
  291.     buf[4] = '\0';
  292.     return buf;
  293. }
  294.  
  295. #define ValidChar(l)    (isalpha(l) || ((l)==' '))
  296.  
  297. long
  298. GoodID(long ID)
  299. {
  300.     char *str = (char *)&ID;
  301.  
  302.     geta4();
  303.     TraceCall;
  304.     return (long)(ValidChar(str[0])
  305.                 && ValidChar(str[1])
  306.                 && ValidChar(str[2])
  307.                 && ValidChar(str[3]));
  308. }
  309.  
  310. long
  311. GoodType(long ID)
  312. {
  313.     char *str = (char *)&ID;
  314.  
  315.     geta4();
  316.     TraceCall;
  317.     return (long)(ValidChar(str[0])
  318.                 && ValidChar(str[1])
  319.                 && ValidChar(str[2])
  320.                 && ValidChar(str[3]));
  321. }
  322.  
  323. /************************\
  324.  * The 'big' functions. *
  325. \************************/
  326. long
  327. WriteChunkBytes(
  328.     struct IFF *iff, 
  329.     APTR data, 
  330.     long size)
  331. {
  332.     long datasize = size;   /* Due to Manx bug! */
  333.  
  334.     geta4();
  335.     TraceCall;
  336.     if (WriteStream(iff, (UBYTE *)data, datasize))
  337.         return IFFERR_READ;
  338.     IFFStack[IFFptr].Size += datasize;
  339.     return 0L;
  340. }
  341.  
  342. long
  343. ReadChunkBytes(
  344.     struct IFF *iff, 
  345.     APTR data, 
  346.     size_t size)
  347. {
  348.     long error;
  349.     long datasize = size;   /* Due to Manx bug! */
  350.  
  351.     geta4();
  352.     TraceCall;
  353.     if (data==NULL) {
  354.         return IFFERR_SYNTAX;
  355.     } else {
  356.         if ((datasize==0) || (datasize>IFFStack[IFFptr].Size))
  357.             datasize = IFFStack[IFFptr].Size;
  358.     }
  359.     if ((error=ReadStream(iff, (UBYTE *)data, datasize))<=0)
  360.         if (error==0)
  361.             return IFFERR_EOF;
  362.         else
  363.             return IFFERR_READ;
  364.     IFFStack[IFFptr].Size -= datasize;
  365.     if ((IFFStack[IFFptr].Size==0) && AlignStream(iff))
  366.         return IFFERR_NOTIFF;
  367.     return datasize;
  368. }
  369.  
  370. long
  371. PushChunk(
  372.     struct IFF *iff, 
  373.     long type, 
  374.     long id, 
  375.     long size)
  376. {
  377.     long t_type = type;
  378.  
  379.     geta4();
  380.     TraceCall;
  381.     if (WriteStream(iff, (UBYTE *)&id, 8L))
  382.         return IFFERR_WRITE;
  383.     if (t_type!=0L) {
  384.         if (WriteStream(iff, (UBYTE *)&t_type, 4L))
  385.             return IFFERR_WRITE;
  386.         IFFStack[++IFFptr].Size=4;
  387.     } else {
  388.         IFFStack[++IFFptr].Size=0;
  389.     }
  390.     return 0L;
  391. }
  392.  
  393. long
  394. PopChunk(struct IFF *iff)
  395. {
  396.     long offset;
  397.     long size;
  398.  
  399.     geta4();
  400.     TraceCall;
  401.     offset = IFFStack[IFFptr].Size;
  402.     if (SeekStream(iff, -offset-4L))
  403.         return IFFERR_SEEK;
  404.     size = IFFStack[IFFptr].Size;
  405.     if (WriteStream(iff, (UBYTE *)&size, 4L))
  406.         return IFFERR_READ;
  407.     if (IFFptr)
  408.         IFFStack[--IFFptr].Size+=IFFStack[IFFptr+1].Size+8L;
  409.     if (SeekStream(iff, offset))
  410.         return IFFERR_SEEK;
  411.     if (IFFStack[IFFptr+1].Size%2) {
  412.         if (WriteStream(iff, (UBYTE *)"", 1L))
  413.             return IFFERR_READ;
  414.         IFFStack[IFFptr].Size++;
  415.     }
  416.     return 0L;
  417. }
  418.  
  419. long
  420. ParseIFF(struct IFF *iff, long control)
  421. {
  422.     struct IFFParseBase *IFFParseBase;
  423.     long error;
  424.     long type = 0L; 
  425.     long id;
  426.     long size;
  427.  
  428.     geta4();
  429.     TraceCall;
  430.     if (control==IFFPARSE_RAWSTEP) {
  431.         if (IFFptr && IFFStack[IFFptr].Size==0) {
  432.             IFFptr--;
  433.             iff->current.cn_ID = 0L;
  434.             return IFFERR_EOC;
  435.         } else if (IFFptr && IFFStack[IFFptr].Complex==0) {
  436.             iff->current.cn_ID = 0L;
  437.             if (SeekStream(iff, (long)(IFFStack[IFFptr].Size+((IFFStack[IFFptr].Size)&1))))
  438.                 return IFFERR_SEEK;
  439.             IFFptr--;
  440.             return IFFERR_EOC;
  441.         }
  442.         
  443.         if ((error=ReadStream(iff, (UBYTE *)&id, 4L))<=0)
  444.             if (error==0)
  445.                 return IFFERR_EOF;
  446.             else
  447.                 return IFFERR_READ;
  448.  
  449.         if (!GoodID(id))
  450.             return IFFERR_NOTIFF;
  451.  
  452.         if ((error=ReadStream(iff, (UBYTE *)&size, 4L))<=0)
  453.             if (error==0)
  454.                 return IFFERR_EOF;
  455.             else
  456.                 return IFFERR_READ;
  457.  
  458.         if ((id==ID_FORM
  459.         || id==ID_PROP
  460.         || id==ID_CAT
  461.         || id==ID_LIST)
  462.         && ReadStream(iff, (UBYTE *)&type, 4L)<=0)
  463.             return IFFERR_READ;
  464.             
  465.  
  466.         if (type!=0L) {
  467.             IFFStack[IFFptr].Size -= size + (size%2) + 8L;
  468.             IFFStack[++IFFptr].Size = size - 4L;
  469.             IFFStack[IFFptr].Complex = 1;
  470.             iff->current.cn_Type = type;
  471.         } else {
  472.             IFFStack[IFFptr].Size -= size + (size%2) + 8L;
  473.             IFFStack[++IFFptr].Size = size;
  474.             IFFStack[IFFptr].Complex = 0;
  475.         }
  476.         iff->current.cn_ID = id;
  477.         iff->current.cn_Size = size;
  478.         iff->current.cn_Scan = ((type!=0) ? 4 : 0);
  479.         return SUCCESS;
  480.     } else
  481.         return FAILED;
  482. }
  483.  
  484. struct ContextNode*
  485. CurrentChunk(struct IFF *iff)
  486. {
  487.     geta4();
  488.     TraceCall;
  489.     return &iff->current;
  490. }
  491.