home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / datatypes / acbm_datatype / dispatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-09  |  34.3 KB  |  1,076 lines

  1.  
  2. /*
  3. **
  4. **  $VER: dispatch.c 1.3 (9.11.97)
  5. **  acbm.datatype 1.3
  6. **
  7. **  Dispatch routine for a DataTypes class
  8. **
  9. **  Written 1996/97 by Roland 'Gizzy' Mainz
  10. **  Original example source from David N. Junod
  11. **
  12. */
  13.  
  14. /* main includes */
  15. #include "classbase.h"
  16. #include "classdata.h"
  17.  
  18. /* ansi includes */
  19. #include <limits.h>
  20.  
  21. /*****************************************************************************/
  22.  
  23. /* local prototypes */
  24. static                 LONG              LoadACBM( struct ClassBase *, Object * );
  25. static                 BOOL              CMAP2Object( struct ClassBase *, Object *, UBYTE *, ULONG );
  26. static                 LONG              LoadABITBody( struct BitMap *, struct BitMapHeader *, BYTE *, ULONG );
  27.  
  28. #ifndef NO_ENCODER
  29. static                 ULONG             SaveIFFACBM( struct ClassBase *, Object *, struct dtWrite * );
  30.  
  31. static                 struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *, BPTR );
  32.  
  33. static                 LONG              PutIFFObjectInfo( struct ClassBase *, struct IFFHandle *, STRPTR, STRPTR, STRPTR, STRPTR, STRPTR );
  34. static                 LONG              PutIFFString( struct ClassBase *, struct IFFHandle *, ULONG, STRPTR );
  35.  
  36. static                 LONG              PutILBMCMAP( struct ClassBase *, struct IFFHandle *, ULONG *, ULONG );
  37. static                 LONG              PutACBMABIT( struct ClassBase *, struct IFFHandle *, struct BitMap *, struct BitMapHeader * );
  38. #endif /* NO_ENCODER */
  39.  
  40.  
  41.  
  42. /*****************************************************************************/
  43.  
  44. /* Create "acbm.datatype" BOOPSI class */
  45. struct IClass *initClass( struct ClassBase *cb )
  46. {
  47.     struct IClass *cl;
  48.  
  49.     /* Create our class... */
  50.     if( cl = MakeClass( ACBMDTCLASS, PICTUREDTCLASS, NULL, 0UL, 0UL ) )
  51.     {
  52. #define DTSTACKSIZE (16384UL)
  53.       cl -> cl_Dispatcher . h_Entry    = (HOOKFUNC)StackSwapDispatch; /* see stackswap.c */
  54.       cl -> cl_Dispatcher . h_SubEntry = (HOOKFUNC)Dispatch;          /* see stackswap.c */
  55.       cl -> cl_Dispatcher . h_Data     = (APTR)DTSTACKSIZE;           /* see stackswap.c */
  56.       cl -> cl_UserData                = (ULONG)cb;                   /* class library base as expected by datatypes.library */
  57.  
  58.       /* ... then make it public */
  59.       AddClass( cl );
  60.     }
  61.  
  62.     return( cl );
  63. }
  64.  
  65. /*****************************************************************************/
  66.  
  67. /* IFF errors to DOS errors */
  68. static
  69. const
  70. LONG ifferr2doserr[] =
  71. {
  72.     0L,                         /* End of file (not an error).                   */
  73.     0L,                         /* End of context (not an error).                */
  74.     DTERROR_INVALID_DATA,       /* No lexical scope.                             */
  75.     ERROR_NO_FREE_STORE,        /* Insufficient memory.                          */
  76.     ERROR_SEEK_ERROR,           /* Stream read error.                            */
  77.     ERROR_SEEK_ERROR,           /* Stream write error.                           */
  78.     ERROR_SEEK_ERROR,           /* Stream seek error.                            */
  79.     DTERROR_INVALID_DATA,       /* File is corrupt.                              */
  80.     DTERROR_INVALID_DATA,       /* IFF syntax error.                             */
  81.     ERROR_OBJECT_WRONG_TYPE,    /* Not an IFF file.                              */
  82.     ERROR_REQUIRED_ARG_MISSING, /* Required call-back hook missing.              */
  83.     0xDEADDEAD                  /* Return to client. You should never see this ! */
  84. };
  85.  
  86. /*****************************************************************************/
  87.  
  88. /* class dispatcher */
  89. DISPATCHERFLAGS
  90. ULONG Dispatch( REGA0 struct IClass *cl, REGA2 Object *o, REGA1 Msg msg )
  91. {
  92.     struct ClassBase     *cb = (struct ClassBase *)(cl -> cl_UserData);
  93.     ULONG                 retval = 0UL;
  94.  
  95.     switch( msg -> MethodID )
  96.     {
  97. /****** acbm.datatype/OM_NEW *************************************************
  98. *
  99. *    NAME
  100. *        OM_NEW -- Create a acbm.datatype object.
  101. *
  102. *    FUNCTION
  103. *        The OM_NEW method is used to create an instance of the acbm.datatype
  104. *        class.  This method is passed to the superclass first. After this,
  105. *        acbm.datatype parses the description file and loads the colormap,
  106. *        the bitmap and so on.
  107. *
  108. *    ATTRIBUTES
  109. *        The following attributes can be specified at creation time.
  110. *
  111. *        DTA_SourceType (ULONG) -- Determinates the type of DTA_Handle
  112. *            attribute. DTST_FILE, DTST_CLIPBOARD and DTST_RAM are supported.
  113. *            If any other type was set in a given DTA_SourceType,
  114. *            OM_NEW will be rejected.
  115. *            Defaults to DTST_FILE.
  116. *
  117. *        DTA_Handle -- For both supported DTST_FILE and DTST_CLIPBOARD, a
  118. *            (struct IFFHandle *) is expected.
  119. *            (DTST_FILE expects a IFF Stream handle because this is a IFF
  120. *            type DataType (DTF_IFF)).
  121. *            A DTST_RAM (create empty object) source type requires a NULL
  122. *            handle.
  123. *
  124. *    RESULT
  125. *        If the object was created a pointer to the object is returned,
  126. *        otherwise NULL is returned.
  127. *
  128. ******************************************************************************
  129. *
  130. */
  131.       case OM_NEW:
  132.       {
  133.           struct TagItem *ti;
  134.  
  135.           /* We only support DTST_FILE, DTST_CLIPBOARD or DTST_RAM as source type */
  136.           if( ti = FindTagItem( DTA_SourceType, (((struct opSet *)msg) -> ops_AttrList) ) )
  137.           {
  138.             if( ((ti -> ti_Data) != DTST_FILE)      &&
  139.                 ((ti -> ti_Data) != DTST_CLIPBOARD)
  140. #ifndef NO_ENCODER
  141.                 && ((ti -> ti_Data) != DTST_RAM)
  142. #endif /* !NO_ENCODER */
  143.  )
  144.             {
  145.               SetIoErr( ERROR_OBJECT_WRONG_TYPE );
  146.  
  147.               break;
  148.             }
  149.           }
  150.  
  151.           /* This must not be a subclass of acbm.datatype
  152.            * (not implemented yet)
  153.            */
  154.           if( o == (Object *)cl )
  155.           {
  156.             if( retval = DoSuperMethodA( cl, o, msg ) )
  157.             {
  158.               LONG error;
  159.  
  160.               /* Load picture... */
  161.               if( error = LoadACBM( cb, (Object *)retval ) )
  162.               {
  163.                 /* Something went fatally wrong, dispose object */
  164.                 CoerceMethod( cl, (Object *)retval, OM_DISPOSE );
  165.                 retval = 0UL;
  166.               }
  167.  
  168.               SetIoErr( error );
  169.             }
  170.           }
  171.           else
  172.           {
  173.             /* Subclasses of acbm.datatype are not implemented */
  174.             SetIoErr( ERROR_NOT_IMPLEMENTED );
  175.           }
  176.       }
  177.           break;
  178.  
  179.       case OM_UPDATE:
  180.       {
  181.           if( DoMethod( o, ICM_CHECKLOOP ) )
  182.           {
  183.             break;
  184.           }
  185.       }
  186.       case OM_SET:
  187.       {
  188.           /* Pass the attributes to the picture class and force a refresh if we need it */
  189.           if( retval = DoSuperMethodA( cl, o, msg ) )
  190.           {
  191. /* The following check statement isn't needed because OM_NEW does not allow subclasses of acbm.datatype,
  192.  * therefore, we're always the top instance...
  193.  */
  194. #ifdef COMMENTED_OUT
  195.             /* Top instance ? */
  196.             if( OCLASS( o ) == cl )
  197. #endif /* COMMENTED_OUT */
  198.             {
  199.               struct RastPort *rp;
  200.  
  201.               /* Get a pointer to the rastport */
  202.               if( rp = ObtainGIRPort( (((struct opSet *)msg) -> ops_GInfo) ) )
  203.               {
  204.                 struct gpRender gpr;
  205.  
  206.                 /* Force a redraw */
  207.                 gpr . MethodID   = GM_RENDER;
  208.                 gpr . gpr_GInfo  = ((struct opSet *)msg) -> ops_GInfo;
  209.                 gpr . gpr_RPort  = rp;
  210.                 gpr . gpr_Redraw = GREDRAW_UPDATE;
  211.  
  212.                 DoMethodA( o, (Msg)(&gpr) );
  213.  
  214.                 /* Release the temporary rastport */
  215.                 ReleaseGIRPort( rp );
  216.  
  217.                 /* We did a refresh... */
  218.                 retval = 0UL;
  219.               }
  220.             }
  221.           }
  222.       }
  223.           break;
  224.  
  225. /****** acbm.datatype/DTM_WRITE **********************************************
  226. *
  227. *    NAME
  228. *        DTM_WRITE -- Save data
  229. *
  230. *    FUNCTION
  231. *        This method saves the object's contents to disk.
  232. *
  233. *        If dtw_Mode is DTWM_IFF, the method is passed unchanged to the
  234. *        superclass, picture.datatype, which writes an IFF ILBM picture.
  235. *
  236. *        If dtw_mode is DTWM_RAW, the object writes an IFF ACBM picture to
  237. *        the filehandle given.
  238. *        (If the class library was compiled with the NO_ENCODER switch
  239. *        (not the default), result == 0 and resul2 == ERROR_NOT_IMPLEMENTED 
  240. *        are returned).
  241. *
  242. *    TAGS
  243. *        None defined.
  244. *
  245. *    RESULT
  246. *        Returns 0 for failure (IoErr() returns result2), non-zero
  247. *        for success.
  248. *
  249. ******************************************************************************
  250. *
  251. */
  252.       case DTM_WRITE:
  253.       {
  254.           struct dtWrite *dtw;
  255.  
  256.           dtw = (struct dtWrite *)msg;
  257.  
  258.           /* Local data format requested ? */
  259.           if( (dtw -> dtw_Mode) == DTWM_RAW )
  260.           {
  261. /* Enable the followng code if you don't have an encoder implemented... */
  262. #ifdef NO_ENCODER
  263.             SetIoErr( ERROR_NOT_IMPLEMENTED );
  264.             retval = 0UL;
  265. #else
  266.             retval = SaveIFFACBM( cb, o, dtw );
  267. #endif /* NO_ENCODER */
  268.           }
  269.           else
  270.           {
  271.             /* Pass msg to superclass (which writes an IFF ILBM picture)... */
  272.             retval = DoSuperMethodA( cl, o, msg );
  273.           }
  274.       }
  275.           break;
  276.  
  277.       /* Let the superclass handle everything else */
  278.       default:
  279.       {
  280.           retval = DoSuperMethodA( cl, o, msg );
  281.       }
  282.           break;
  283.     }
  284.  
  285.     return( retval );
  286. }
  287.  
  288.  
  289. static
  290. LONG LoadACBM( struct ClassBase *cb, Object *o )
  291. {
  292.     LONG                 error = 0L;
  293.  
  294.  
  295.     APTR                 fh;               /* IFF stream handle               */
  296.     ULONG                sourcetype;       /* type of stream (either DTST_FILE, DTST_CLIPBOARD or DTST_RAM */
  297.     struct BitMapHeader *bmh;              /* obj's bitmapheader              */
  298.     ULONG                modeid     = 0UL; /* picture's view mode             */
  299.  
  300.     /* Get file handle, handle type and BitMapHeader */
  301.     if( GetDTAttrs( o, DTA_SourceType,    (&sourcetype),
  302.                        DTA_Handle,        (&fh),
  303.                        PDTA_BitMapHeader, (&bmh),
  304.                        TAG_DONE ) == 3UL )
  305.     {
  306.       struct IFFHandle *iff = NULL;
  307.  
  308.       switch( sourcetype )
  309.       {
  310.         case DTST_CLIPBOARD:
  311.         case DTST_FILE:
  312.         {
  313.             /* This is an IFF DataType, datatypesclass provides an IFFHandle for us.
  314.              * (See datatypesclass autdocs for details !)
  315.              */
  316.             iff = (struct IFFHandle *)fh;
  317.         }
  318.             break;
  319.  
  320. #ifndef NO_ENCODER
  321.         case DTST_RAM:
  322.         {
  323.             /* Do nothing... */
  324.         }
  325.             break;
  326. #endif /* !NO_ENCODER */
  327.  
  328.         default:
  329.         {
  330.             /* unsupported source type */
  331.             error = ERROR_NOT_IMPLEMENTED;
  332.         }
  333.             break;
  334.       }
  335.  
  336.       /* Any error ? */
  337.       if( error == 0L )
  338.       {
  339.         /* Any handle to proccess ? */
  340.         if( iff )
  341.         {
  342.           struct BitMap         *bm             = NULL; /* resulting bitmap (e.g. PDTA_BitMap) */
  343.  
  344.           struct StoredProperty *bmhdprop       = NULL, /* ACBM BMHD (struct BitMapHeader) */
  345.                                 *camgprop       = NULL, /* ACBM CAMG (amiga view mode id)  */
  346.                                 *cmapprop       = NULL, /* ACBM CMAP (colormap)            */
  347.                                 *abitprop       = NULL, /* ACBM ABIT (Amiga BITplanes      */
  348.                                 *annoprop       = NULL, /* Generic IFF ANNO (annotation) chunk    */
  349.                                 *authprop       = NULL, /* Generic IFF AUTH (author) chunk        */
  350.                                 *copyrightprop  = NULL, /* Generic IFF (C)  (copyright) chunk     */
  351.                                 *fverprop       = NULL, /* Generic IFF FVER (version) chunk       */
  352.                                 *nameprop       = NULL; /* Generic IFF NAME (name) chunk          */
  353.  
  354. #define NUM_PROPCHUNKS (9L)
  355.           const
  356.           LONG propchunks[ (NUM_PROPCHUNKS * 2) ] =
  357.           {
  358.             ID_ACBM, ID_BMHD,
  359.             ID_ACBM, ID_CAMG,
  360.             ID_ACBM, ID_CMAP,
  361.             ID_ACBM, ID_ABIT,
  362.             ID_ACBM, ID_ANNO,
  363.             ID_ACBM, ID_AUTH,
  364.             ID_ACBM, ID_Copyright,
  365.             ID_ACBM, ID_FVER,
  366.             ID_ACBM, ID_NAME
  367.           };
  368.  
  369.           if( !(error = PropChunks( iff, (LONG *)propchunks, NUM_PROPCHUNKS )) )
  370.           {
  371.             /* Scan IFF stream until an error or an EOF occurs */
  372.             for( ;; )
  373.             {
  374.               if( error = ParseIFF( iff, IFFPARSE_STEP ) )
  375.               {
  376.                 /* EOF (End Of File) is no error here... */
  377.                 if( error == IFFERR_EOF )
  378.                 {
  379.                   error = 0L;
  380.                   break;
  381.                 }
  382.  
  383.                 /* bmhd header loaded ? */
  384.                 if( bmhdprop == NULL )
  385.                 {
  386.                   if( bmhdprop = FindProp( iff, ID_ACBM, ID_BMHD ) )
  387.                   {
  388.                     *bmh = *((struct BitMapHeader *)(bmhdprop -> sp_Data));
  389.  
  390.                     /* ABIT data __must__ not be compressed for IFF ACBM */
  391.                     if( (bmh -> bmh_Compression) != cmpNone )
  392.                     {
  393.                       error = DTERROR_INVALID_DATA;
  394.                     }
  395.                   }
  396.                 }
  397.  
  398.                 /* camg loaded ? */
  399.                 if( camgprop == NULL )
  400.                 {
  401.                   if( camgprop = FindProp( iff, ID_ACBM, ID_CAMG ) )
  402.                   {
  403.                     modeid = *(ULONG *)(camgprop -> sp_Data);
  404.                   }
  405.                 }
  406.  
  407.                 /* cmap loaded  ? */
  408.                 if( cmapprop == NULL )
  409.                 {
  410.                   if( cmapprop = FindProp( iff, ID_ACBM, ID_CMAP ) )
  411.                   {
  412.                     if( !CMAP2Object( cb, o, (cmapprop -> sp_Data), (cmapprop -> sp_Size) ) )
  413.                     {
  414.                       error = ERROR_NO_FREE_STORE;
  415.                     }
  416.                   }
  417.                 }
  418.  
  419.                 /* annotation loaded ? */
  420.                 if( annoprop == NULL )
  421.                 {
  422.                   /* IFF ANNO found ? */
  423.                   if( annoprop = FindProp( iff, ID_ACBM, ID_ANNO ) )
  424.                   {
  425.                     STRPTR buff;
  426.  
  427.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  428.                     if( buff = (STRPTR)AllocVec( ((annoprop -> sp_Size) + 2UL), MEMF_ANY ) )
  429.                     {
  430.                       stccpy( buff, (annoprop -> sp_Data), (int)(annoprop -> sp_Size) );
  431.  
  432.                       SetDTAttrs( o, NULL, NULL, DTA_ObjAnnotation, buff, TAG_DONE );
  433.  
  434.                       FreeVec( buff );
  435.                     }
  436.                     else
  437.                     {
  438.                       /* no temp. buffer */
  439.                       error = ERROR_NO_FREE_STORE;
  440.                     }
  441.                   }
  442.                 }
  443.  
  444.                 /* autor loaded ? */
  445.                 if( authprop == NULL )
  446.                 {
  447.                   /* IFF AUTH found ? */
  448.                   if( authprop = FindProp( iff, ID_ACBM, ID_AUTH ) )
  449.                   {
  450.                     STRPTR buff;
  451.  
  452.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  453.                     if( buff = (STRPTR)AllocVec( ((authprop -> sp_Size) + 2UL), MEMF_ANY ) )
  454.                     {
  455.                       stccpy( buff, (authprop -> sp_Data), (int)(authprop -> sp_Size) );
  456.  
  457.                       SetDTAttrs( o, NULL, NULL, DTA_ObjAuthor, buff, TAG_DONE );
  458.  
  459.                       FreeVec( buff );
  460.                     }
  461.                     else
  462.                     {
  463.                       /* no temp. buffer */
  464.                       error = ERROR_NO_FREE_STORE;
  465.                     }
  466.                   }
  467.                 }
  468.  
  469.                 /* copyright loaded ? */
  470.                 if( copyrightprop == NULL )
  471.                 {
  472.                   /* IFF (C) found ? */
  473.                   if( copyrightprop = FindProp( iff, ID_ACBM, ID_Copyright ) )
  474.                   {
  475.                     STRPTR buff;
  476.  
  477.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  478.                     if( buff = (STRPTR)AllocVec( ((copyrightprop -> sp_Size) + 2UL), MEMF_ANY ) )
  479.                     {
  480.                       stccpy( buff, (copyrightprop -> sp_Data), (int)(copyrightprop -> sp_Size) );
  481.  
  482.                       SetDTAttrs( o, NULL, NULL, DTA_ObjCopyright, buff, TAG_DONE );
  483.  
  484.                       FreeVec( buff );
  485.                     }
  486.                     else
  487.                     {
  488.                       /* no temp. buffer */
  489.                       error = ERROR_NO_FREE_STORE;
  490.                     }
  491.                   }
  492.                 }
  493.  
  494.                 /* file version loaded ? */
  495.                 if( fverprop == NULL )
  496.                 {
  497.                   /* IFF FVER found ? */
  498.                   if( fverprop = FindProp( iff, ID_ACBM, ID_FVER ) )
  499.                   {
  500.                     STRPTR buff;
  501.  
  502.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  503.                     if( buff = (STRPTR)AllocVec( ((fverprop -> sp_Size) + 2UL), MEMF_ANY ) )
  504.                     {
  505.                       stccpy( buff, (fverprop -> sp_Data), (int)(fverprop -> sp_Size) );
  506.  
  507.                       SetDTAttrs( o, NULL, NULL, DTA_ObjVersion, buff, TAG_DONE );
  508.  
  509.                       FreeVec( buff );
  510.                     }
  511.                     else
  512.                     {
  513.                       /* no temp. buffer */
  514.                       error = ERROR_NO_FREE_STORE;
  515.                     }
  516.                   }
  517.                 }
  518.  
  519.                 /* name loaded ? */
  520.                 if( nameprop == NULL )
  521.                 {
  522.                   /* IFF NAME found ? */
  523.                   if( nameprop = FindProp( iff, ID_ACBM, ID_NAME ) )
  524.                   {
  525.                     STRPTR buff;
  526.  
  527.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  528.                     if( buff = (STRPTR)AllocVec( ((nameprop -> sp_Size) + 2UL), MEMF_ANY ) )
  529.                     {
  530.                       stccpy( buff, (nameprop -> sp_Data), (int)(nameprop -> sp_Size) );
  531.  
  532.                       SetDTAttrs( o, NULL, NULL, DTA_ObjName, buff, TAG_DONE );
  533.  
  534.                       FreeVec( buff );
  535.                     }
  536.                     else
  537.                     {
  538.                       /* no temp. buffer */
  539.                       error = ERROR_NO_FREE_STORE;
  540.                     }
  541.                   }
  542.                 }
  543.  
  544.                 /* abit loaded  ? */
  545.                 if( abitprop == NULL )
  546.                 {
  547.                   if( abitprop = FindProp( iff, ID_ACBM, ID_ABIT ) )
  548.                   {
  549.                     if( bmhdprop )
  550.                     {
  551.                       if( bm = AllocBitMap( (ULONG)(bmh -> bmh_Width), (ULONG)(bmh -> bmh_Height), (ULONG)(bmh -> bmh_Depth), BMF_MINPLANES, NULL ) )
  552.                       {
  553.                         error = LoadABITBody( bm, bmh, (abitprop -> sp_Data), (abitprop -> sp_Size) );
  554.                       }
  555.                       else
  556.                       {
  557.                         /* Not bitmap (AllocBitMap failed) */
  558.                         error = ERROR_NO_FREE_STORE;
  559.                       }
  560.                     }
  561.                     else
  562.                     {
  563.                       /* No BMHD chunk before ABIT chunk */
  564.                       error = DTERROR_INVALID_DATA;
  565.                     }
  566.                   }
  567.                 }
  568.  
  569.                 /* on error: leave for-loop */
  570.                 if( error )
  571.                 {
  572.                   if( error != IFFERR_EOC )
  573.                   {
  574.                     break;
  575.                   }
  576.                 }
  577.               }
  578.             }
  579.           }
  580.  
  581.           /* bmh, cmap, abit and all other required information available  ? */
  582.           if( ((bmhdprop == NULL) || (cmapprop == NULL) || (abitprop == NULL) || (bm == NULL)) && (error == 0L) )
  583.           {
  584.             error = DTERROR_INVALID_DATA;
  585.           }
  586.  
  587.           /* Any error ? */
  588.           if( error == 0L )
  589.           {
  590.             /* No name chunk ? */
  591.             if( nameprop == NULL )
  592.             {
  593.               STRPTR name;
  594.  
  595.               GetDTAttrs( o, DTA_Name, (&name), TAG_DONE );
  596.               SetDTAttrs( o, NULL, NULL, DTA_ObjName, name, TAG_DONE );
  597.             }
  598.  
  599.             /* No mode id ? */
  600.             if( modeid == 0UL )
  601.             {
  602.               /* BUG: Does currently not support SUPERHIRES modes */
  603.               if( (bmh -> bmh_Width) >= 640UL )
  604.               {
  605.                 if( (bmh -> bmh_Height) >= 400 )
  606.                 {
  607.                   modeid = HIRESLACE_KEY;
  608.                 }
  609.                 else
  610.                 {
  611.                   modeid = HIRES_KEY;
  612.                 }
  613.               }
  614.               else
  615.               {
  616.                 if( (bmh -> bmh_Height) >= 400 )
  617.                 {
  618.                   modeid = LORESLACE_KEY;
  619.                 }
  620.                 else
  621.                 {
  622.                   modeid = LORES_KEY;
  623.                 }
  624.               }
  625.             }
  626.  
  627.             /* Set misc attributes */
  628.             SetDTAttrs( o, NULL, NULL,
  629.                         PDTA_ModeID,      modeid,
  630.                         PDTA_BitMap,      bm,
  631.                         DTA_NominalHoriz, (bmh -> bmh_Width),
  632.                         DTA_NominalVert,  (bmh -> bmh_Height),
  633.                         TAG_DONE );
  634.  
  635.             /* bm has been given to picture.datatype and will be freed there... */
  636.             bm = NULL;
  637.           }
  638.  
  639.           /* Free bitmap if it wasn't consumed by picture.datatype */
  640.           if( bm )
  641.           {
  642.             FreeBitMap( bm );
  643.           }
  644.         }
  645.         else
  646.         {
  647.           /* No iff handle ? - Be sure we got a DTST_RAM sourcetype */
  648.           if( sourcetype != DTST_RAM )
  649.           {
  650.             /* No handle ! */
  651.             error = ERROR_REQUIRED_ARG_MISSING;
  652.           }
  653.         }
  654.       }
  655.     }
  656.     else
  657.     {
  658.       /* can't get required attributes from superclass */
  659.       error = ERROR_OBJECT_WRONG_TYPE;
  660.     }
  661.  
  662.     /* Error codes below 0 are related to the IFFParse.library functions */
  663.     if( error < 0L )
  664.     {
  665.       /* convert IFFParse error to DOS error */
  666.       error = ifferr2doserr[ (-error - 1) ];
  667.     }
  668.  
  669.     return( error );
  670. }
  671.  
  672.  
  673. /* Put CMAP chunk into picture/animation object... */
  674. static
  675. BOOL CMAP2Object( struct ClassBase *cb, Object *o, UBYTE *rgb, ULONG rgbsize )
  676. {
  677.     struct ColorRegister *acm;
  678.     ULONG                *acregs;
  679.     ULONG                 nc;
  680.  
  681.     /* file has this many colors (e.g. each color has one byte per R,B,G-gun) */
  682.     nc = rgbsize / 3UL;
  683.  
  684.     SetDTAttrs( o, NULL, NULL, PDTA_NumColors, nc, TAG_DONE );
  685.  
  686.     /* Get color context */
  687.     if( GetDTAttrs( o,
  688.                     PDTA_ColorRegisters, (&acm),
  689.                     PDTA_CRegs,          (&acregs),
  690.                     PDTA_NumColors,      (&nc),
  691.                     TAG_DONE ) == 3UL )
  692.     {
  693.       /* All valid ? */
  694.       if( acm && acregs && nc )
  695.       {
  696.         ULONG i;
  697.  
  698.         for( i = 0UL ; i < nc ; i++, acm++ )
  699.         {
  700.           acm -> red   =  *rgb++;
  701.           acm -> green =  *rgb++;
  702.           acm -> blue  =  *rgb++;
  703.  
  704.           /* Replicate the color information.
  705.            * This surrounds an OS bug which uses the low-order bytes of the 32-bit colors
  706.            * instead of the high order ones
  707.            */
  708.           acregs[ ((i * 3) + 0) ] = ((ULONG)(acm -> red))   * 0x01010101UL;
  709.           acregs[ ((i * 3) + 1) ] = ((ULONG)(acm -> green)) * 0x01010101UL;
  710.           acregs[ ((i * 3) + 2) ] = ((ULONG)(acm -> blue))  * 0x01010101UL;
  711.         }
  712.  
  713.         return( TRUE );
  714.       }
  715.     }
  716.  
  717.     return( FALSE );
  718. }
  719.  
  720.  
  721. /* Load IFF ACBM ABIT chunk into given bitmap */
  722. static
  723. LONG LoadABITBody( struct BitMap *bitmap, struct BitMapHeader *bmhd, BYTE *buffer, ULONG buffersize )
  724. {
  725.     UBYTE    srcPlaneCnt  = bmhd -> bmh_Depth;          /* Haven't counted for mask plane yet */
  726.     WORD     srcRowBytes  = RowBytes( (bmhd -> bmh_Width) );
  727.     WORD     destRowBytes = bitmap -> BytesPerRow;      /* used as a modulo only */
  728.     LONG     nRows        = bmhd -> bmh_Height;
  729.     LONG     iPlane,
  730.              iRow;
  731.     BYTE    *buf;
  732.     BYTE    *planes[ MaxSrcPlanes ];                    /* array of ptrs to planes & mask */
  733.  
  734.     if( nRows > (bitmap -> Rows) )
  735.       nRows = bitmap -> Rows;
  736.  
  737.     /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
  738.     for( iPlane = 0 ; iPlane < (bitmap -> Depth) ; iPlane++ )
  739.     {
  740.       planes[ iPlane ] = (BYTE *)(bitmap -> Planes[ iPlane ]);
  741.     }
  742.  
  743.     for( ; iPlane < MaxSrcPlanes ; iPlane++ )
  744.     {
  745.       planes[ iPlane ] = NULL;
  746.     }
  747.  
  748.     /* Copy any mask plane ptr into corresponding "planes" slot. */
  749.     if( (bmhd -> bmh_Masking) == mskHasMask )
  750.     {
  751.       planes[ srcPlaneCnt ] = NULL; /* In case more dstPlanes than src. */
  752.       srcPlaneCnt += 1;             /* Include mask plane in count.     */
  753.     }
  754.  
  755.     /* Read the ABIT contents into client's bitmap. */
  756.     buf = buffer;
  757.  
  758.     for( iPlane = 0 ; iPlane < srcPlaneCnt ; iPlane++ )
  759.     {
  760.       for( iRow = nRows ; iRow > 0 ; iRow-- )
  761.       {
  762.         memcpy( planes[ iPlane ], buf, (size_t)srcRowBytes );
  763.         buf += srcRowBytes;
  764.  
  765.         planes[ iPlane ] += destRowBytes; /* Possibly skipping unused bytes */
  766.       }
  767.     }
  768.  
  769.     return( 0L );
  770. }
  771.  
  772.  
  773. #ifndef NO_ENCODER
  774. /* The IFF ACBM encoder */
  775. static
  776. ULONG SaveIFFACBM( struct ClassBase *cb, Object *o, struct dtWrite *dtw )
  777. {
  778.     ULONG retval = 0UL;
  779.     LONG  error  = 0L;
  780.  
  781.     /* A NULL file handle is a nop (GMultiView uses this to test if a datatype supports RAW writing) */
  782.     if( dtw -> dtw_FileHandle )
  783.     {
  784.       struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  785.       STRPTR                objname,
  786.                             objauthor,
  787.                             objannotation,
  788.                             objcopyright,
  789.                             objversion;
  790.       struct BitMapHeader  *bmh;
  791.       ULONG                 modeid;
  792.       ULONG                *cregs;
  793.       ULONG                 numcolors;
  794.       struct BitMap        *bm;
  795.  
  796.       /* Lock data that noone could change it...
  797.        * We use here a shared lock because we don't chaange any object data below
  798.        * Theoretically, this allows that multiple savers acts on the same object :-)
  799.        */
  800.       ObtainSemaphoreShared( (&(si -> si_Lock)) );
  801.  
  802.       if( GetDTAttrs( o, DTA_ObjName,       (&objname),
  803.                          DTA_ObjAuthor,     (&objauthor),
  804.                          DTA_ObjAnnotation, (&objannotation),
  805.                          DTA_ObjCopyright,  (&objcopyright),
  806.                          DTA_ObjVersion,    (&objversion),
  807.                          PDTA_BitMapHeader, (&bmh),
  808.                          PDTA_ModeID,       (&modeid),
  809.                          PDTA_CRegs,        (&cregs),
  810.                          PDTA_NumColors,    (&numcolors),
  811.                          PDTA_BitMap,       (&bm),
  812.                          TAG_DONE ) == 10UL )
  813.       {
  814.         if( bmh && cregs && numcolors && bm )
  815.         {
  816.           /* ABIT data __must__ not be compressed for IFF ACBM */
  817.           if( (bmh -> bmh_Compression) == cmpNone )
  818.           {
  819.             /* Check if this is a standard amiga bitmap (we're accessing it directly below, and cannot
  820.              * handle any other bitmap layout than the standart planar format)
  821.              */
  822.             if( GetBitMapAttr( bm, BMA_FLAGS ) & BMF_STANDARD )
  823.             {
  824.               struct IFFHandle *iff;
  825.  
  826.               /* Create IFF handle based in the given file handle */
  827.               if( iff = CreateDOSIFFHandle( cb, (dtw -> dtw_FileHandle) ) )
  828.               {
  829.                 if( !(error = OpenIFF( iff, IFFF_WRITE )) )
  830.                 {
  831.                   for( ;; ) /* not a loop, used as a jump table */
  832.                   {
  833.                     if( error = PushChunk( iff, ID_ACBM, ID_FORM, IFFSIZE_UNKNOWN ) )
  834.                       break;
  835.  
  836.                     /* write BMHD (BitMapHeader) */
  837.                     {
  838.                       if( error = PushChunk( iff, 0UL, ID_BMHD, sizeof( struct BitMapHeader ) ) )
  839.                         break;
  840.  
  841.                       if( (error = WriteChunkBytes( iff, (APTR)bmh, sizeof( struct BitMapHeader ) )) != sizeof( struct BitMapHeader ) )
  842.                       {
  843.                         break;
  844.                       }
  845.  
  846.                       if( error = PopChunk( iff ) )
  847.                         break;
  848.                     }
  849.  
  850.                     /* write CMAP (global color map) */
  851.                     if( error = PutILBMCMAP( cb, iff, cregs, numcolors ) )
  852.                       break;
  853.  
  854.                     /* write misc info (name, author, annotation etc.) */
  855.                     if( error = PutIFFObjectInfo( cb, iff, objname, objauthor, objannotation, objcopyright, objversion ) )
  856.                       break;
  857.  
  858.                     /* write CAMG (amiga view mode) (if available) */
  859.                     if( (modeid != 0UL) && (modeid != INVALID_ID) )
  860.                     {
  861.                       if( error = PushChunk( iff, 0UL, ID_CAMG, sizeof( ULONG ) ) )
  862.                         break;
  863.  
  864.                       if( (error = WriteChunkBytes( iff, (APTR)(&modeid), sizeof( ULONG ) )) != sizeof( ULONG ) )
  865.                       {
  866.                         break;
  867.                       }
  868.  
  869.                       if( error = PopChunk( iff ) )
  870.                         break;
  871.                     }
  872.  
  873.                     /* Write ACBM ABIT */
  874.                     if( error = PutACBMABIT( cb, iff, bm, bmh ) )
  875.                       break;
  876.  
  877.                     if( error = PopChunk( iff ) )
  878.                       break;
  879.  
  880.                     break; /* end of jump table */
  881.                   }
  882.  
  883.                   CloseIFF( iff );
  884.                 }
  885.  
  886.                 /* No error == success */
  887.                 if( error == 0L )
  888.                 {
  889.                   retval = 1UL; /* success ! */
  890.                 }
  891.  
  892.                 FreeIFF( iff );
  893.               }
  894.               else
  895.               {
  896.                 /* Can't alloc iff handle */
  897.                 error = ERROR_NO_FREE_STORE;
  898.               }
  899.             }
  900.             else
  901.             {
  902.               /* unknown bitmap layout (e.g. not a standard amiga bitmap) */
  903.               error = ERROR_OBJECT_WRONG_TYPE;
  904.             }
  905.           }
  906.           else
  907.           {
  908.             /* IFF ACBM does not support compression */
  909.             error = DTERROR_UNKNOWN_COMPRESSION;
  910.           }
  911.         }
  912.         else
  913.         {
  914.           /* Some things are missing (e.g. no bitmap etc.)... */
  915.           error = DTERROR_NOT_ENOUGH_DATA;
  916.         }
  917.       }
  918.       else
  919.       {
  920.         /* Object does not support the attributes we need... */
  921.         error = ERROR_OBJECT_WRONG_TYPE;
  922.       }
  923.  
  924.       /* Release data */
  925.       ReleaseSemaphore( (&(si -> si_Lock)) );
  926.     }
  927.  
  928.     /* Error codes below 0 are related to the IFFParse.library functions */
  929.     if( error < 0L )
  930.     {
  931.       /* convert IFFParse error to DOS error */
  932.       error = ifferr2doserr[ (-error - 1) ];
  933.     }
  934.  
  935.     /* Store Result2 */
  936.     SetIoErr( error );
  937.  
  938.     return( retval );
  939. }
  940.  
  941.  
  942. /* Create IFF handle based on given file handle */
  943. static
  944. struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *cb, BPTR fh )
  945. {
  946.     struct IFFHandle *iff;
  947.  
  948.     if( iff = AllocIFF() )
  949.     {
  950.       iff -> iff_Stream = (ULONG)fh;
  951.  
  952.       InitIFFasDOS( iff );
  953.     }
  954.  
  955.     return( iff );
  956. }
  957.  
  958.  
  959. /* Put IFF generic info chunks (NAME, AUTH, ANNO, (C), FVER etc. */
  960. static
  961. LONG PutIFFObjectInfo( struct ClassBase *cb, struct IFFHandle *iff, STRPTR objname, STRPTR objauthor, STRPTR objannotation, STRPTR objcopyright, STRPTR objversion )
  962. {
  963.     LONG error;
  964.  
  965.     if( error = PutIFFString( cb, iff, ID_NAME,      objname       ) ) return( error );
  966.     if( error = PutIFFString( cb, iff, ID_AUTH,      objauthor     ) ) return( error );
  967.     if( error = PutIFFString( cb, iff, ID_ANNO,      objannotation ) ) return( error );
  968.     if( error = PutIFFString( cb, iff, ID_Copyright, objcopyright  ) ) return( error );
  969.     if( error = PutIFFString( cb, iff, ID_FVER,      objversion    ) ) return( error );
  970.  
  971.     return( 0L );
  972. }
  973.  
  974.  
  975. /* write an string into a chunk (like generic AUTH, ANNO etc. chunks)  */
  976. static
  977. LONG PutIFFString( struct ClassBase *cb, struct IFFHandle *iff, ULONG id, STRPTR string )
  978. {
  979.     LONG error = 0L;
  980.  
  981.     if( string )
  982.     {
  983.       ULONG len = (ULONG)(strlen( string ) + 1UL);
  984.  
  985.       if( error = PushChunk( iff, 0UL, id, len ) )
  986.         return( error );
  987.  
  988.       if( (error = WriteChunkBytes( iff, (APTR)string, len )) != len )
  989.       {
  990.         return( error );
  991.       }
  992.  
  993.       error = PopChunk( iff );
  994.     }
  995.  
  996.     return( error );
  997. }
  998.  
  999.  
  1000. /* write ILBM CMAP  */
  1001. static
  1002. LONG PutILBMCMAP( struct ClassBase *cb, struct IFFHandle *iff, ULONG *cregs, ULONG numcolors )
  1003. {
  1004.     long                 error;
  1005.     ULONG                i;
  1006.     struct ColorRegister cm;
  1007.  
  1008. #define SIZEOF_CMAPENTRY (3L)
  1009.     if( error = PushChunk( iff, 0UL, ID_CMAP, (numcolors * SIZEOF_CMAPENTRY) ) )
  1010.       return( error );
  1011.  
  1012.     for( i = 0UL ; i < numcolors ; i++ )
  1013.     {
  1014.       /* reduce colors from 32 bits to cmap's 8 bit-per-gun */
  1015.       cm . red   = (UBYTE)(cregs[ ((i * 3) + 0) ] >> 24UL);
  1016.       cm . green = (UBYTE)(cregs[ ((i * 3) + 1) ] >> 24UL);
  1017.       cm . blue  = (UBYTE)(cregs[ ((i * 3) + 2) ] >> 24UL);
  1018.  
  1019.       /* Write R, B, G bytes */
  1020.       if( (error = WriteChunkBytes( iff, (APTR)(&cm), SIZEOF_CMAPENTRY )) != SIZEOF_CMAPENTRY )
  1021.       {
  1022.         return( error );
  1023.       }
  1024.     }
  1025.  
  1026.     return( PopChunk( iff ) );
  1027. }
  1028.  
  1029. /*****************************************************************************/
  1030.  
  1031. /* Write ACBM ABIT data */
  1032. static
  1033. LONG PutACBMABIT( struct ClassBase *cb, struct IFFHandle *iff, struct BitMap *bitmap, struct BitMapHeader *bmh )
  1034. {
  1035.     LONG     error;
  1036.     LONG     rowBytes        = bitmap -> BytesPerRow;           /* for source modulo only  */
  1037.     LONG     FileRowBytes    = RowBytes( (bmh -> bmh_Width) );  /* width to write in bytes */
  1038.     ULONG    planeCnt        = bmh -> bmh_Depth;                /* number of bit planes including mask */
  1039.     ULONG    iPlane,
  1040.              iRow;
  1041.     BYTE    *planes[ 24 ]; /* array of ptrs to planes & mask */
  1042.  
  1043.     /* Copy the ptrs to bit & mask planes into local array "planes" */
  1044.     for( iPlane = 0 ; iPlane < planeCnt; iPlane++ )
  1045.        planes[ iPlane ] = (BYTE *)(bitmap -> Planes[ iPlane ]);
  1046.  
  1047.     /* Write out a ABIT chunk header (size == number_of_planes * number_of_rows * bytes_per_row) */
  1048.     if( error = PushChunk( iff, 0L, ID_ABIT, (planeCnt * (bmh -> bmh_Height) * FileRowBytes) ) )
  1049.       return( error );
  1050.  
  1051.     /* Write out the ABIT contents */
  1052.     for( iPlane = 0 ; iPlane < planeCnt ; iPlane++ )
  1053.     {
  1054.       for( iRow = bmh -> bmh_Height ; iRow > 0 ; iRow-- )
  1055.       {
  1056.         /* Write next row.*/
  1057.         if( (error = WriteChunkBytes( iff, planes[ iPlane ], FileRowBytes )) != FileRowBytes )
  1058.           return( error );
  1059.  
  1060.         planes[ iPlane ] += rowBytes; /* Possibly skipping unused bytes */
  1061.       }
  1062.     }
  1063.  
  1064.     /* Finish the chunk */
  1065.     error = PopChunk( iff );
  1066.  
  1067.     return( error );
  1068. }
  1069.  
  1070. #endif /* NO_ENCODER */
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.