home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #4 / amigamamagazinepolishissue1998.iso / datatypes / gifanimdtc201.lha / gifanim_datatype / classbase.c < prev    next >
C/C++ Source or Header  |  1998-03-23  |  24KB  |  670 lines

  1.  
  2. /*
  3. **
  4. **  $VER: classbase.c 2.1 (23.3.98)
  5. **  gifanim.datatype 2.1
  6. **
  7. **  Library routines for a DataTypes class
  8. **
  9. **  Written 1997/1998 by Roland 'Gizzy' Mainz
  10. **  Original example source from David N. Junod
  11. **
  12. */
  13.  
  14.  
  15. /* main includes */
  16. #include "classbase.h"
  17.  
  18.  
  19. /****** gifanim.datatype/MAIN ************************************************
  20. *
  21. *    INTRODUCTION
  22. *        Datatypes class for GIF animations. Based on "giftopnm" by David
  23. *        Koblas, "ppmtogif" by Marcel Wijkstra <wijkstra@fwi.uva.nl> and
  24. *        David Rowley <mgardi@watdscu.waterloo.edu> and the CBM datatypes 
  25. *        example source/ documents written by David Junod.
  26. *
  27. *    LEGAL
  28. *      * Note that this implementation uses LZW, which is PATENTED by UniSys
  29. *        in the U.S.A.
  30. *
  31. *        Therefore, this application must not be used inside the United
  32. *        States of America except for research purposes.
  33. *
  34. *      - Compuserves banner:
  35. *
  36. *      "The Graphics Interchange Format(c) is the Copyright property of
  37. *      CompuServe Incorporated. GIF(sm) is a Service Mark property of
  38. *      CompuServe Incorporated."
  39. *
  40. *      - "giftopnm" legal info:
  41. *      +-------------------------------------------------------------------+
  42. *      | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    |
  43. *      |   Permission to use, copy, modify, and distribute this software   |
  44. *      |   and its documentation for any purpose and without fee is hereby |
  45. *      |   granted, provided that the above copyright notice appear in all |
  46. *      |   copies and that both that copyright notice and this permission  |
  47. *      |   notice appear in supporting documentation.  This software is    |
  48. *      |   provided "as is" without express or implied warranty.           |
  49. *      +-------------------------------------------------------------------+
  50. *
  51. *    REQUIREMENTS
  52. *        - You need at least Kick/WB 3.0.
  53. *          | Many people wrote me that they cannot find an
  54. *          | "animation.datatype" class.
  55. *          | Only the 3.1 release contains it. (Subclasses of)
  56. *          | animation.datatype can run under 3.0.
  57. *
  58. *        - "datatypes/animation.datatype", >= V41
  59. *          "animation.datatype V41" requires itself some
  60. *          libraries/boopsi classes:
  61. *        - "realtime.library", >= V39              - for timing
  62. *        - "gadgets/tapedeck.gadget" (any version) - for the controls
  63. *
  64. *           If you want to attach samples, you need "sound.datatype" >= V39
  65. *           and your prefereed subclass (8svx.datatype for IFF 8SVX samples
  66. *           etc.).
  67. *
  68. *    USAGE
  69. *        If the datatypes descriptor file was activated, any attempt to load
  70. *        a GIF anim stream using GMultiView, MultiView, AmigaGuide or
  71. *        SwitchWindow will load and play the animation. If the source was a
  72. *        file, gifanim.datatype loads frames dynamically from disk.
  73. *
  74. *        If you want to save the current animation in gifanim.datatype's
  75. *        local format, use MultiView's "Project/Save As..." menu (or
  76. *        GMultiView's "Project/Save As Raw...").
  77. *        gifanim.datatype saves the current animation, starting with the
  78. *        current frame as GIF animation.
  79. *
  80. *        If you want to attach samples to the animation, you must edit the
  81. *        prefs file (ENV:Classes/DataTypes/gifanim.prefs) and add the
  82. *        following line:
  83. *        VERBOSE SAMPLE="ram:have_a_nice_day.8svx"
  84. *        Which loads and attaches the sample "ram:have_a_nice_day.8svx" to
  85. *        the animation. See gifanim.datatype.doc/preferences for a complete
  86. *        description of the prefs file.
  87. *
  88. *    INSTALLATION
  89. *        After unpacking this archive:
  90. *        Because this version does not include an Installer script, you have
  91. *        to do the installation manually through the shell:
  92. *
  93. *          - Unpack this archive and copy the "gifanim.datatype" to
  94. *            SYS:Classes/DataTypes/:
  95. *
  96. *        Copy CLONE FROM "gifanim.datatype" TO
  97. *         "SYS:Classes/DataTypes/gifanim.datatype"
  98. *
  99. *          - Then copy the datatypes descriptor into the DEVS:DataTypes
  100. *            directory.
  101. *            If the descriptor already exists, you should not replace it,
  102. *            otherwise you may loose "toolnodes" and other settings stored in
  103. *            the existing descriptor.
  104. *
  105. *     Copy CLONE FROM "GIFANIM(%|.info)" TO DEVS:Datatypes/
  106. *
  107. *    SOURCE
  108. *        Source is included as an example how to write an
  109. *        animation.datatype subclass which deals with things chunky bitmaps
  110. *        deltas and an encoder...
  111. *
  112. *    AUTHOR
  113. *        If you want to blame me, report any bugs, or wants a new version
  114. *        send your letter to:
  115. *                        Roland Mainz
  116. *                        Hohenstaufenstraße 8
  117. *                        52388 Nörvenich
  118. *                        GERMANY
  119. *
  120. *        Phone: (+49)(0)2426/901568
  121. *        Fax:   (+49)(0)2426/901569
  122. *
  123. *        EMAIL is also available (if you want to send me attachments
  124. *        larger than 1MB (up to 5MB, more with my permission):
  125. *
  126. *        GISBURN@w-specht.rhein-ruhr.de
  127. *
  128. *        Up to May 1998 I'm reachable using this email address, too:
  129. *        Reinhold.A.Mainz@KBV.DE
  130. *
  131. *        | Please put your name and address in your mails !
  132. *        | German mailers should add their phone numbers.
  133. *        | See BUGS section above when submitting bug reports.
  134. *
  135. *        Sorry, but I can only look once a week for mails.
  136. *        If you don't hear something from me within three weeks, please
  137. *        send your mail again (but watch about new releases) (problems with
  138. *        this email port are caused by reconfigurations, hackers, network
  139. *        problems etc.).
  140. *
  141. *        The  entire  "gifanim.datatype"  package  may  be  noncommercially
  142. *        redistributed, provided  that  the package  is always  distributed
  143. *        in it's complete  form (including it's documentation). A small
  144. *        copy fee  for media costs is okay but any kind of commercial
  145. *        distribution is strictly forbidden without my permission !
  146. *        Comments and suggestions how to improve this program are
  147. *        generally appreciated!
  148. *
  149. *        Thanks to David Junod, who wrote the animation.datatype and lots of
  150. *        the datatypes example code, David Koblas for his "giftopnm"
  151. *        and other people for their compression formats, Peter McGavin for
  152. *        his C2P function, Matt Dillon for his DICE, Olaf 'Olsen' Barthel
  153. *        for his help, ideas and some text clips from his documentations.
  154. *
  155. ******************************************************************************
  156. *
  157. */
  158.  
  159.  
  160.  
  161. /****** gifanim.datatype/--datasheed-- ***************************************
  162. *
  163. *   NAME
  164. *       gifanim.datatype -- data type for GIF Animations
  165. *
  166. *   SUPERCLASS
  167. *       animation.datatype
  168. *
  169. *   DESCRIPTION
  170. *       The anim datatype, a sub-class of the animation.datatype, is used to
  171. *       load, play and encode (save) GIF animations.
  172. *       It supports GIF 87a and GIF 89a compressed animations.
  173. *       Using the prefs-file, any sound can be attached to the animation.
  174. *
  175. *   METHODS
  176. *       OM_NEW -- Create a new animation object from a description file. The
  177. *           source may only be a file. Or an empty object can be created for 
  178. *           encoding (which must be filled by the application before 
  179. *           encoding).
  180. *
  181. *       OM_DISPOSE -- Dispose instance and contents (frames, colormaps, sounds
  182. *           etc.), then pass msg to superclass
  183. *
  184. *       OM_UPDATE -- Perform an ICM_CHECKLOOP check, and if succesfull, the
  185. *           method will be executed like OM_SET downstairs.
  186. *
  187. *       OM_SET -- Pass msg to superclass and call GM_RENDER if retval from
  188. *           superclass was != 0UL.
  189. *
  190. *       DTM_WRITE -- Save object's contents in local (GIF Animation) or
  191. *           superclass (IFF ILBM) format.
  192. *
  193. *       ADTM_LOADFRAME -- Fill in struct adtFrame with requested information
  194. *           from internal FrameNode list like bitmap, colormap and sample. If
  195. *           the bitmap information is not loaded yet, it will be loaded from
  196. *           disk.
  197. *
  198. *       ADTM_UNLOADFRAME -- Free resources obtained by ADTM_UNLOADFRAME.
  199. *
  200. *       All other methods are passed unchanged to superclass.
  201. *
  202. *   ATTRIBUTES
  203. *       Following attributes are set by the object and are READ-ONLY for
  204. *       applications:
  205. *       DTA_ObjName             - file name
  206. *       DTA_ObjAnnotation       - set by extension blocks (gif 89a comment
  207. *                                 extention)
  208. *       DTA_TotalHoriz          - same as ADTA_Width
  209. *       DTA_TotalVert           - same as ADTA_Height
  210. *       ADTA_Width              - set by GIF screen
  211. *       ADTA_Height             - set by GIF screen
  212. *       ADTA_Depth              - set by GIF screen
  213. *       ADTA_Frames             - number of frames in animation
  214. *       ADTA_FramesPerSecond    - fixed to 100 fps
  215. *       ADTA_ModeID             - mode id flags
  216. *       ADTA_KeyFrame           - Key frame of animation
  217. *
  218. *       The following attributes are only set if a sample is attached using 
  219. *       the prefs-file:
  220. *       ADTA_Sample             - only set to notify the anmation.datatype
  221. *                                 instance that the object has sound data
  222. *       ADTA_SampleLength       - size of sample data played within one 
  223. *                                 timestamp
  224. *       ADTA_Period             - sample period
  225. *       ADTA_Volume             - volume as set by the prefs-file
  226. *
  227. *   BUGS
  228. *       * The whole code looks like a big hack; sorry, but this datatype was
  229. *         put together within 2 hours...
  230. *         ...V1.2 only fixes some bugs and adds a few features.
  231. *         ...V1.3 fixed some things, adds some legal stuff and CyberGFX
  232. *            support
  233. *
  234. *       - Does not support transparency yet.
  235. *
  236. *       - Very slow playback.
  237. *         Reasons:
  238. *         - Multiple memory allocations, Seek's and Read's in one
  239. *           ADTM_LOADFRAME
  240. *         - Unbufferd loading
  241. *         - C2P conversion (fast, but not the fastest possible)
  242. *         - crap design
  243. *         - Slow gif decoder. Rewriting the beast in ASM maybe speed up
  244. *           things, but I don't know much about m68k assember.
  245. *           Anybody out there who wants to do the job ?
  246. *         ....
  247. *
  248. *         To get rid of this problem, the LOADALL switch is set for now.
  249. *         On >= mc68040/40MHz, the LOADALL switch in unneccesary, use
  250. *         NOLOADALL in this case...
  251. *
  252. *       - Some anims get a trashed background, maybe due a bug in the GIF89a
  253. *         frame disposal support code.
  254. *
  255. *       - This datatype was written for animation.datatype V41. Using this
  256. *         datatype with animation.datatype V40.6 does not work !
  257. *
  258. *       - In large videos, the frames at the end will be played slower than
  259. *         those at the beginning of the file. This is the result of the
  260. *         sequential search internally used (only serious with more than 25000
  261. *         frames (mc6030/50mhz)).
  262. *         May or may not be fixed.
  263. *
  264. *       - CyberGFX support is still under development. It seems that it works
  265. *         good, but...
  266. *
  267. *       - CyberGFX C2C conversion (LUT8 -> RGB16/24) uses a very crap method
  268. *         througth WriteRGBPixel...
  269. *
  270. *   TODO
  271. *       - Fixing the bugs above.
  272. *
  273. *       - Write the "--input_format--"-Autodoc section.
  274. *
  275. *   HISTORY
  276. *       V1.1
  277. *         Released to the Waldspecht-BBS for testing.
  278. *
  279. *       V1.2
  280. *         - Found and fixed the longstanding bug that animation.datatype
  281. *           V40.7 didn't free some frames. Reason is that ADTM_LOADFRAME
  282. *           may be used like "realloc". Now alf_UserData is checked;
  283. *           any given frame will be freed (ADTM_UNLOADFRAME).
  284. *           Fixed.
  285. *
  286. *         - Minor houskeeping changes; removed some unneccesary code.
  287. *
  288. *         - Now uses buffered reading (FRead instead of Read and SetVBuf).
  289. *           Maybe this speeds up loading a little bit.
  290. *
  291. *         - Fixed the bug in NOLOADALL loading mode (dynamic loading of
  292. *           frames from disk) that some "disposal" modes (previous image)
  293. *           didn't work properly under some conditions.
  294. *           Fixed.
  295. *
  296. *         - Fixed the bug that animations with a static background were
  297. *           not correctly handled in LOADALL mode (I simply forgot
  298. *           to write the code...).
  299. *           Thanks to Francis Labrie (fb691875@er.uquam.ca) for reporting
  300. *           the bug.
  301. *           Fixed.
  302. *
  303. *         - Fixed the bug that ADTM_LOADFRAME returns evertimes
  304. *           ERROR_NO_FREE_STORE on failure instead of returning the real
  305. *           cause.
  306. *           Also fixed the error handling code in ADTM_LOADFRAME.
  307. *           Fixed.
  308. *
  309. *         - Implemented a delta mode for WPA8. If possible (e.g. if the
  310. *           current frame uses the previous one as it's background), only
  311. *           the changed areas are processed by the C2P code.
  312. *
  313. *         - Now supports the GIF comment extension. The character set is
  314. *           converted automatically, chars > 128 are replaced by '_'
  315. *           except the german 'ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü' and 'ß'.
  316. *           Multiple comment chunks are merged together.
  317. *           The comment will be stored in DTA_ObjAnnotation.
  318. *
  319. *         - Cut some unneccesary VERBOSE output.
  320. *
  321. *       V1.3
  322. *         | Internal testing release to search for the mysterious memory loss
  323. *         | in conjunction with the 24BITCHUNKY option.
  324. *
  325. *         - Added the notice that UniSys holds the LZW patents in the USA.
  326. *
  327. *         - Removed BestModeIDA, because animation.datatype does the same
  328. *           thing.
  329. *
  330. *         - Small code cleanup.
  331. *           Removed some of the debugging code and removed some parts of
  332. *           dead code.
  333. *
  334. *         - Fixed the "maximum timestamp" (ADTA_Frames) calculation.
  335. *           the old way was very crap...
  336. *           Fixed.
  337. *
  338. *         - Added some padding bytes in the decoder (instance data) part.
  339. *           Now the data are aligned, which should speed up the decoding.
  340. *
  341. *         - Fixed possible problems when a GIF "Comment Extension" text is
  342. *           not '\0'-terminated. Now the load buffer is zero'ed for each new
  343. *           cycle.
  344. *           Fixed.
  345. *
  346. *         - Added some VERBOSE about the "Plain Text Extension". The contents
  347. *           are now shown in the verbose output.
  348. *
  349. *         - Fixed the bug that in the case that the first frame has no bitmap
  350. *           a bitmap with 0,0,0 dimensions would be allocated.
  351. *           (Did not occur, but...)
  352. *           Fixed.
  353. *
  354. *         - Implemented a prefetch buffer for dynamic load mode (e.g.
  355. *           NOLOADALL); now all data needed for the frame are loaded with one
  356. *           Read statement, all following accesses are redirected to the
  357. *           filled buffer.
  358. *           Switched from FRead to Read again because we're now loading
  359. *           larger blocks.
  360. *
  361. *         - Fixed the width padding problem, which caused an ugly border
  362. *           filled with rubbish in some anims.
  363. *           Fixed.
  364. *
  365. *         - Now supports different disposal modes in one animation (each
  366. *           frame can have it's own disposal mode).
  367. *
  368. *         - Now supports different transarent colors in one animation (each
  369. *           frame can have it's own transparent color).
  370. *
  371. *         - Removed all references to ADTA_BitMapHeader. It's not required
  372. *           for this format.
  373. *
  374. *         - Now saves the transparent color values from the previous colormap.
  375. *
  376. *         - Fixed the bug that the datatypes creates everytimes a
  377. *           palette-per-frame instead of creating them only if neccesary.
  378. *           Fixed.
  379. *
  380. *         - Now sets the GIF Screen background color to 0 if there is no
  381. *           global colormap.
  382. *
  383. *         - Added CyberGFX-Support. Upon request, the datatype tries to create
  384. *           a 24-bit chunky bitmap if the 24BITCHUNKY prefs switch is set.
  385. *           WARNING: Does only work with animation.datatype V41 or higher
  386. *           (<= V41.2 had a small bug which has been fixed in V41.3).
  387. *
  388. *         - Added CyberGFX bug workaround when BestCModeIDA fails when the
  389. *           dimensions given are too small (e.g. 32 * 50 returns INVALID_ID).
  390. *           Then 640 * 480 are set.
  391. *           Not very nice.
  392. *
  393. *         - Added GIF Picture descriptor to replace any version with a wrong
  394. *           mask.
  395. *
  396. *       V1.4
  397. *         - Very much thanks to Frank Mariak (fmariak@chaosengine.ping.de)
  398. *           for finding the silly "too big palette"-bug in conjunction
  399. *           with the new chunkypixel output.
  400. *
  401. *       V1.5
  402. *         - Major code cleanup. BOOPSI class structures have been moved
  403. *           to classdata.h, class independed functions have been moved
  404. *           into misc.c, class preferences to prefs.c
  405. *
  406. *         - Replaced the custom stackswapping code with my "standard"
  407. *           module "stackswap.c".
  408. *
  409. *         - OM_DISPOSE now preserves Result2 (IoErr()).
  410. *
  411. *         - Fixed the longstandig bug in ScanFrames that if an OS function
  412. *           failed, and IoErr results 0, havoc broke out.
  413. *           Fixed.
  414. *
  415. *         - ADTA_SampleLength calculations were wrong. The value was got
  416. *           from the first frame. Now the value is set correctly to
  417. *           alf_SampleLength / (alf_Duration + 1)
  418. *           Fixed.
  419. *
  420. *         - If a ADTM_LOADFRAME method gets a message from a previous
  421. *           ADTM_LOADFRAME call, the contents are freed now after
  422. *           the requested data have been loaded. This avoids the
  423. *           pathological case that if the same frame should be freed and
  424. *           returned the frame IS freed and then re-loaded.
  425. *           Now the free of the given frame is done after the loading
  426. *           of the requested frame which avoids this inefficienty.
  427. *           Fixed.
  428. *
  429. *         - Switched truecolor output down to 16 bit (565-bits-per-gun)
  430. *           to save some mem...
  431. *
  432. *         - Added 16BITCHUNKY, NO16BITCHUNKY, TRUECOLOR and NOTRUECOLOR
  433. *           options.
  434. *
  435. *         - Fixed ModeID handling. The previous behaviour was that
  436. *           a 0 mode id causes the datatype to select it's own mode id.
  437. *           But 0 means LORES. Now the default is -1 (which means
  438. +           INVALID_ID), which causes the datatype to do it's own
  439. *           calculations.
  440. *           Fixed.
  441. *
  442. *       V2.1
  443. *         - Implemeted the GIF animation encoder part.
  444. *           The encoder writes GIF89a animation streams out.
  445. *
  446. *         - Fixed a mask bug in the suppied "GIF" descriptor;
  447. *           a byte after the "GIF" signature was set to match,
  448. *           Fixed.
  449. *
  450. *         - gifanim.datatype now requires at least animation.datatype V41
  451. *           as base class.
  452. *           (mainly to get rid of the V40 workround code which tried to
  453. *           get class working with animation.datatype V40).
  454. *
  455. *         - Updated and cleaned-up the autodoc a little bit.
  456. *
  457. *   NOTES
  458. *       This datatype first scans the whole animation to get index
  459. *       information (if the LOADALL switch was set in the prefs-file,
  460. *       the entire animation will be loaded), colormaps will be loaded
  461. *       immediately.
  462. *
  463. *   SEE ALSO
  464. *       animation.datatype,
  465. *       anim.datatype,
  466. *       mpegsystem.datatype, mpegvideo.datatype,
  467. *       picmovie.datatype,
  468. *       cdxl.datatype, avi.datatype, quicktime.datatype,
  469. *       moviesetter.datatype,
  470. *       film.datatype,
  471. *       directory.datatype,
  472. *       markabletextdtclass
  473. *
  474. *******************************************************************************
  475. *
  476. */
  477.  
  478.  
  479. /****** gifanim.datatype/--input_format-- ************************************
  480. *
  481. *    NAME
  482. *        GIF ANIM -- GIF Animation format
  483. *
  484. *    DESCRIPTION
  485. *        <Not written yet, sorry>
  486. *
  487. *    SEE ALSO
  488. *        gif.doc, gif89a.doc, compress.gif
  489. *
  490. *******************************************************************************
  491. *
  492. */
  493.  
  494.  
  495.  
  496. /*****************************************************************************/
  497.  
  498. DISPATCHERFLAGS
  499. struct IClass *ObtainGIFAnimEngine( REGA6 struct ClassBase *cb )
  500. {
  501.     return( (cb -> cb_Lib . cl_Class) );
  502. }
  503.  
  504. /*****************************************************************************/
  505.  
  506. DISPATCHERFLAGS
  507. struct Library *LibInit( REGD0 struct ClassBase *cb, REGA0 BPTR seglist, REGA6 struct ExecBase *sysbase )
  508. {
  509.     cb -> cb_SegList = seglist;
  510.     cb -> cb_SysBase = sysbase;
  511.  
  512.     InitSemaphore( (&(cb -> cb_Lock)) );
  513.  
  514.     /* Kickstart V3.0 ? */
  515.     if( (cb -> cb_SysBase -> LibNode . lib_Version) >= 39UL )
  516.     {
  517.       /* Obtain ROM libs */
  518.       if( cb -> cb_UtilityBase = OpenLibrary( "utility.library", 39UL ) )
  519.       {
  520.         if( cb -> cb_DOSBase = OpenLibrary( "dos.library", 39UL ) )
  521.         {
  522.           if( cb -> cb_GfxBase = OpenLibrary( "graphics.library", 39UL ) )
  523.           {
  524.             cb -> cb_CyberGfxBase = OpenLibrary( CYBERGFXNAME, CYBERGFXVERSION );
  525.  
  526.             if( cb -> cb_IntuitionBase = OpenLibrary( "intuition.library", 39UL ) )
  527.             {
  528.               return( (&(cb -> cb_Lib . cl_Lib)) );
  529.  
  530. #ifdef COMMENTED_OUT
  531.               CloseLibrary( (cb -> cb_IntuitionBase) );
  532. #endif /* COMMENTED_OUT */
  533.             }
  534.  
  535.             CloseLibrary( (cb -> cb_CyberGfxBase) );
  536.             CloseLibrary( (cb -> cb_GfxBase) );
  537.           }
  538.  
  539.           CloseLibrary( (cb -> cb_DOSBase) );
  540.         }
  541.  
  542.         CloseLibrary( (cb -> cb_UtilityBase) );
  543.       }
  544.     }
  545.  
  546.     return( NULL );
  547. }
  548.  
  549. /*****************************************************************************/
  550.  
  551. DISPATCHERFLAGS
  552. LONG LibOpen( REGA6 struct ClassBase *cb )
  553. {
  554.     LONG retval = (LONG)cb;
  555.     BOOL success = TRUE;
  556.  
  557.     ObtainSemaphore( (&(cb -> cb_Lock)) );
  558.  
  559.     /* Use an internal use counter */
  560.     cb -> cb_Lib . cl_Lib . lib_OpenCnt++;
  561.     cb -> cb_Lib . cl_Lib . lib_Flags &= ~LIBF_DELEXP;
  562.  
  563.     if( (cb -> cb_Lib . cl_Lib . lib_OpenCnt) == 1U )
  564.     {
  565.       if( (cb -> cb_Lib . cl_Class) == NULL )
  566.       {
  567.         success = FALSE;
  568.  
  569.         if( cb -> cb_DataTypesBase = OpenLibrary( "datatypes.library", 39UL ) )
  570.         {
  571.           if( cb -> cb_SuperClassBase = OpenLibrary( "datatypes/animation.datatype", 41UL ) )
  572.           {
  573.             if( cb -> cb_Lib . cl_Class = initClass( cb ) )
  574.             {
  575.               success = TRUE;
  576.             }
  577.           }
  578.         }
  579.       }
  580.     }
  581.  
  582.     if( !success )
  583.     {
  584.       CloseLibrary( (cb -> cb_SuperClassBase) );
  585.       CloseLibrary( (cb -> cb_DataTypesBase) );
  586.  
  587.       cb -> cb_DataTypesBase = cb -> cb_SuperClassBase = NULL;
  588.  
  589.       (cb -> cb_Lib . cl_Lib . lib_OpenCnt)--;
  590.  
  591.       retval = 0L;
  592.     }
  593.  
  594.     ReleaseSemaphore( (&(cb -> cb_Lock)) );
  595.  
  596.     return( retval );
  597. }
  598.  
  599. /*****************************************************************************/
  600.  
  601. DISPATCHERFLAGS
  602. LONG LibClose( REGA6 struct ClassBase *cb )
  603. {
  604.     LONG retval = 0L;
  605.  
  606.     ObtainSemaphore( (&(cb -> cb_Lock)) );
  607.  
  608.     if( cb -> cb_Lib . cl_Lib . lib_OpenCnt )
  609.     {
  610.       (cb -> cb_Lib . cl_Lib . lib_OpenCnt)--;
  611.     }
  612.  
  613.     if( ((cb -> cb_Lib . cl_Lib . lib_OpenCnt) == 0U) && (cb -> cb_Lib . cl_Class) )
  614.     {
  615.       if( FreeClass( (cb -> cb_Lib . cl_Class) ) )
  616.       {
  617.         cb -> cb_Lib . cl_Class = NULL;
  618.  
  619.         CloseLibrary( (cb -> cb_SuperClassBase) );
  620.         CloseLibrary( (cb -> cb_DataTypesBase) );
  621.       }
  622.       else
  623.       {
  624.         cb -> cb_Lib . cl_Lib . lib_Flags |= LIBF_DELEXP;
  625.       }
  626.     }
  627.  
  628.     ReleaseSemaphore( (&(cb -> cb_Lock)) );
  629.  
  630.     if( (cb -> cb_Lib . cl_Lib . lib_Flags) & LIBF_DELEXP )
  631.     {
  632.       retval = LibExpunge( cb );
  633.     }
  634.  
  635.     return( retval );
  636. }
  637.  
  638. /*****************************************************************************/
  639.  
  640. DISPATCHERFLAGS
  641. LONG LibExpunge( REGA6 struct ClassBase *cb )
  642. {
  643.     BPTR seg;
  644.  
  645.     if( cb -> cb_Lib . cl_Lib . lib_OpenCnt )
  646.     {
  647.       cb -> cb_Lib . cl_Lib . lib_Flags |= LIBF_DELEXP;
  648.  
  649.       seg = NULL;
  650.     }
  651.     else
  652.     {
  653.       Remove( (&(cb -> cb_Lib . cl_Lib . lib_Node)) );
  654.  
  655.       seg = cb -> cb_SegList;
  656.  
  657.       CloseLibrary( (cb -> cb_IntuitionBase) );
  658.       CloseLibrary( (cb -> cb_CyberGfxBase) );
  659.       CloseLibrary( (cb -> cb_GfxBase) );
  660.       CloseLibrary( (cb -> cb_DOSBase) );
  661.       CloseLibrary( (cb -> cb_UtilityBase) );
  662.  
  663.       FreeMem( (APTR)((ULONG)(cb) - (ULONG)(cb -> cb_Lib . cl_Lib . lib_NegSize)), (ULONG)((cb -> cb_Lib . cl_Lib . lib_NegSize) + (cb -> cb_Lib . cl_Lib . lib_PosSize)) );
  664.     }
  665.  
  666.     return( (LONG)seg );
  667. }
  668.  
  669.  
  670.