1 /** ************************************************************************* */
2 /* *             For conditions of distribution and use,                    * */
3 /* *                see copyright notice in libmng.h                        * */
4 /* ************************************************************************** */
5 /* *                                                                        * */
6 /* * project   : libmng                                                     * */
7 /* * file      : libmng_chunk_io.c         copyright (c) 2000-2007 G.Juyn   * */
8 /* * version   : 1.0.10                                                     * */
9 /* *                                                                        * */
10 /* * purpose   : Chunk I/O routines (implementation)                        * */
11 /* *                                                                        * */
12 /* * author    : G.Juyn                                                     * */
13 /* *                                                                        * */
14 /* * comment   : implementation of chunk input/output routines              * */
15 /* *                                                                        * */
16 /* * changes   : 0.5.1 - 05/01/2000 - G.Juyn                                * */
17 /* *             - cleaned up left-over teststuff in the BACK chunk routine * */
18 /* *             0.5.1 - 05/04/2000 - G.Juyn                                * */
19 /* *             - changed CRC initialization to use dynamic structure      * */
20 /* *               (wasn't thread-safe the old way !)                       * */
21 /* *             0.5.1 - 05/06/2000 - G.Juyn                                * */
22 /* *             - filled in many missing sequence&length checks            * */
23 /* *             - filled in many missing chunk-store snippets              * */
24 /* *             0.5.1 - 05/08/2000 - G.Juyn                                * */
25 /* *             - added checks for running animations                      * */
26 /* *             - filled some write routines                               * */
27 /* *             - changed strict-ANSI stuff                                * */
28 /* *             0.5.1 - 05/10/2000 - G.Juyn                                * */
29 /* *             - filled some more write routines                          * */
30 /* *             0.5.1 - 05/11/2000 - G.Juyn                                * */
31 /* *             - filled remaining write routines                          * */
32 /* *             - fixed read_pplt with regard to deltatype                 * */
33 /* *             - added callback error-reporting support                   * */
34 /* *             - added pre-draft48 support (short MHDR, frame_mode, LOOP) * */
35 /* *             0.5.1 - 05/12/2000 - G.Juyn                                * */
36 /* *             - changed trace to macro for callback error-reporting      * */
37 /* *             - fixed chunk-storage bit in several routines              * */
38 /* *             0.5.1 - 05/13/2000 - G.Juyn                                * */
39 /* *             - added eMNGma hack (will be removed in 1.0.0 !!!)         * */
40 /* *             - added TERM animation object pointer (easier reference)   * */
41 /* *             - supplemented the SAVE & SEEK display processing          * */
42 /* *                                                                        * */
43 /* *             0.5.2 - 05/18/2000 - G.Juyn                                * */
44 /* *             - B004 - fixed problem with MNG_SUPPORT_WRITE not defined  * */
45 /* *               also for MNG_SUPPORT_WRITE without MNG_INCLUDE_JNG       * */
46 /* *             0.5.2 - 05/19/2000 - G.Juyn                                * */
47 /* *             - cleaned up some code regarding mixed support             * */
48 /* *             0.5.2 - 05/20/2000 - G.Juyn                                * */
49 /* *             - implemented JNG support                                  * */
50 /* *             0.5.2 - 05/24/2000 - G.Juyn                                * */
51 /* *             - added support for global color-chunks in animation       * */
52 /* *             - added support for global PLTE,tRNS,bKGD in animation     * */
53 /* *             - added support for SAVE & SEEK in animation               * */
54 /* *             0.5.2 - 05/29/2000 - G.Juyn                                * */
55 /* *             - changed ani_create calls not returning object pointer    * */
56 /* *             - create ani objects always (not just inside TERM/LOOP)    * */
57 /* *             0.5.2 - 05/30/2000 - G.Juyn                                * */
58 /* *             - added support for delta-image processing                 * */
59 /* *             0.5.2 - 05/31/2000 - G.Juyn                                * */
60 /* *             - fixed up punctuation (contributed by Tim Rowley)         * */
61 /* *             0.5.2 - 06/02/2000 - G.Juyn                                * */
62 /* *             - changed SWAP_ENDIAN to BIGENDIAN_SUPPORTED               * */
63 /* *             0.5.2 - 06/03/2000 - G.Juyn                                * */
64 /* *             - fixed makeup for Linux gcc compile                       * */
65 /* *                                                                        * */
66 /* *             0.5.3 - 06/12/2000 - G.Juyn                                * */
67 /* *             - added processing of color-info on delta-image            * */
68 /* *             0.5.3 - 06/13/2000 - G.Juyn                                * */
69 /* *             - fixed handling of empty SAVE chunk                       * */
70 /* *             0.5.3 - 06/17/2000 - G.Juyn                                * */
71 /* *             - changed to support delta-images                          * */
72 /* *             - added extra checks for delta-images                      * */
73 /* *             0.5.3 - 06/20/2000 - G.Juyn                                * */
74 /* *             - fixed possible trouble if IEND display-process got       * */
75 /* *               broken up                                                * */
76 /* *             0.5.3 - 06/21/2000 - G.Juyn                                * */
77 /* *             - added processing of PLTE & tRNS for delta-images         * */
78 /* *             - added administration of imagelevel parameter             * */
79 /* *             0.5.3 - 06/22/2000 - G.Juyn                                * */
80 /* *             - implemented support for PPLT chunk                       * */
81 /* *             0.5.3 - 06/26/2000 - G.Juyn                                * */
82 /* *             - added precaution against faulty iCCP chunks from PS      * */
83 /* *             0.5.3 - 06/29/2000 - G.Juyn                                * */
84 /* *             - fixed some 64-bit warnings                               * */
85 /* *                                                                        * */
86 /* *             0.9.1 - 07/14/2000 - G.Juyn                                * */
87 /* *             - changed pre-draft48 frame_mode=3 to frame_mode=1         * */
88 /* *             0.9.1 - 07/16/2000 - G.Juyn                                * */
89 /* *             - fixed storage of images during mng_read()                * */
90 /* *             - fixed support for mng_display() after mng_read()         * */
91 /* *             0.9.1 - 07/19/2000 - G.Juyn                                * */
92 /* *             - fixed several chunk-writing routines                     * */
93 /* *             0.9.1 - 07/24/2000 - G.Juyn                                * */
94 /* *             - fixed reading of still-images                            * */
95 /* *                                                                        * */
96 /* *             0.9.2 - 08/05/2000 - G.Juyn                                * */
97 /* *             - changed file-prefixes                                    * */
98 /* *                                                                        * */
99 /* *             0.9.3 - 08/07/2000 - G.Juyn                                * */
100 /* *             - B111300 - fixup for improved portability                 * */
101 /* *             0.9.3 - 08/08/2000 - G.Juyn                                * */
102 /* *             - fixed compiler-warnings from Mozilla                     * */
103 /* *             0.9.3 - 08/09/2000 - G.Juyn                                * */
104 /* *             - added check for simplicity-bits in MHDR                  * */
105 /* *             0.9.3 - 08/12/2000 - G.Juyn                                * */
106 /* *             - fixed check for simplicity-bits in MHDR (JNG)            * */
107 /* *             0.9.3 - 08/12/2000 - G.Juyn                                * */
108 /* *             - added workaround for faulty PhotoShop iCCP chunk         * */
109 /* *             0.9.3 - 08/22/2000 - G.Juyn                                * */
110 /* *             - fixed write-code for zTXt & iTXt                         * */
111 /* *             - fixed read-code for iTXt                                 * */
112 /* *             0.9.3 - 08/26/2000 - G.Juyn                                * */
113 /* *             - added MAGN chunk                                         * */
114 /* *             0.9.3 - 09/07/2000 - G.Juyn                                * */
115 /* *             - added support for new filter_types                       * */
116 /* *             0.9.3 - 09/10/2000 - G.Juyn                                * */
117 /* *             - fixed DEFI behavior                                      * */
118 /* *             0.9.3 - 10/02/2000 - G.Juyn                                * */
119 /* *             - fixed simplicity-check in compliance with draft 81/0.98a * */
120 /* *             0.9.3 - 10/10/2000 - G.Juyn                                * */
121 /* *             - added support for alpha-depth prediction                 * */
122 /* *             0.9.3 - 10/11/2000 - G.Juyn                                * */
123 /* *             - added support for nEED                                   * */
124 /* *             0.9.3 - 10/16/2000 - G.Juyn                                * */
125 /* *             - added support for JDAA                                   * */
126 /* *             0.9.3 - 10/17/2000 - G.Juyn                                * */
127 /* *             - fixed support for MAGN                                   * */
128 /* *             - implemented nEED "xxxx" (where "xxxx" is a chunkid)      * */
129 /* *             - added callback to process non-critical unknown chunks    * */
130 /* *             - fixed support for bKGD                                   * */
131 /* *             0.9.3 - 10/23/2000 - G.Juyn                                * */
132 /* *             - fixed bug in empty PLTE handling                         * */
133 /* *                                                                        * */
134 /* *             0.9.4 - 11/20/2000 - G.Juyn                                * */
135 /* *             - changed IHDR filter_method check for PNGs                * */
136 /* *             0.9.4 -  1/18/2001 - G.Juyn                                * */
137 /* *             - added errorchecking for MAGN methods                     * */
138 /* *             - removed test filter-methods 1 & 65                       * */
139 /* *                                                                        * */
140 /* *             0.9.5 -  1/25/2001 - G.Juyn                                * */
141 /* *             - fixed some small compiler warnings (thanks Nikki)        * */
142 /* *                                                                        * */
143 /* *             1.0.2 - 05/05/2000 - G.Juyn                                * */
144 /* *             - B421427 - writes wrong format in bKGD and tRNS           * */
145 /* *             1.0.2 - 06/20/2000 - G.Juyn                                * */
146 /* *             - B434583 - compiler-warning if MNG_STORE_CHUNKS undefined * */
147 /* *                                                                        * */
148 /* *             1.0.5 - 07/08/2002 - G.Juyn                                * */
149 /* *             - B578572 - removed eMNGma hack (thanks Dimitri!)          * */
150 /* *             1.0.5 - 08/07/2002 - G.Juyn                                * */
151 /* *             - added test-option for PNG filter method 193 (=no filter) * */
152 /* *             1.0.5 - 08/15/2002 - G.Juyn                                * */
153 /* *             - completed PROM support                                   * */
154 /* *             1.0.5 - 08/19/2002 - G.Juyn                                * */
155 /* *             - B597134 - libmng pollutes the linker namespace           * */
156 /* *             1.0.5 - 09/07/2002 - G.Juyn                                * */
157 /* *             - fixed reading of FRAM with just frame_mode and name      * */
158 /* *             1.0.5 - 09/13/2002 - G.Juyn                                * */
159 /* *             - fixed read/write of MAGN chunk                           * */
160 /* *             1.0.5 - 09/14/2002 - G.Juyn                                * */
161 /* *             - added event handling for dynamic MNG                     * */
162 /* *             1.0.5 - 09/15/2002 - G.Juyn                                * */
163 /* *             - fixed LOOP iteration=0 special case                      * */
164 /* *             1.0.5 - 09/19/2002 - G.Juyn                                * */
165 /* *             - misplaced TERM is now treated as warning                 * */
166 /* *             1.0.5 - 09/20/2002 - G.Juyn                                * */
167 /* *             - added support for PAST                                   * */
168 /* *             1.0.5 - 10/03/2002 - G.Juyn                                * */
169 /* *             - fixed chunk-storage for evNT chunk                       * */
170 /* *             1.0.5 - 10/07/2002 - G.Juyn                                * */
171 /* *             - fixed DISC support                                       * */
172 /* *             - added another fix for misplaced TERM chunk               * */
173 /* *             1.0.5 - 10/17/2002 - G.Juyn                                * */
174 /* *             - fixed initializtion of pIds in dISC read routine         * */
175 /* *             1.0.5 - 11/06/2002 - G.Juyn                                * */
176 /* *             - added support for nEED "MNG 1.1"                         * */
177 /* *             - added support for nEED "CACHEOFF"                        * */
178 /* *                                                                        * */
179 /* *             1.0.6 - 05/25/2003 - G.R-P                                 * */
180 /* *             - added MNG_SKIPCHUNK_cHNK footprint optimizations         * */
181 /* *             1.0.6 - 06/02/2003 - G.R-P                                 * */
182 /* *             - removed some redundant checks for iRawlen==0             * */
183 /* *             1.0.6 - 06/22/2003 - G.R-P                                 * */
184 /* *             - added MNG_NO_16BIT_SUPPORT, MNG_NO_DELTA_PNG reductions  * */
185 /* *             - optionally use zlib's crc32 function instead of          * */
186 /* *               local mng_update_crc                                     * */
187 /* *             1.0.6 - 07/14/2003 - G.R-P                                 * */
188 /* *             - added MNG_NO_LOOP_SIGNALS_SUPPORTED conditional          * */
189 /* *             1.0.6 - 07/29/2003 - G.R-P                                 * */
190 /* *             - added conditionals around PAST chunk support             * */
191 /* *             1.0.6 - 08/17/2003 - G.R-P                                 * */
192 /* *             - added conditionals around non-VLC chunk support          * */
193 /* *                                                                        * */
194 /* *             1.0.7 - 10/29/2003 - G.R-P                                 * */
195 /* *             - revised JDAA and JDAT readers to avoid compiler bug      * */
196 /* *             1.0.7 - 01/25/2004 - J.S                                   * */
197 /* *             - added premultiplied alpha canvas' for RGBA, ARGB, ABGR   * */
198 /* *             1.0.7 - 01/27/2004 - J.S                                   * */
199 /* *             - fixed inclusion of IJNG chunk for non-JNG use            * */
200 /* *             1.0.7 - 02/26/2004 - G.Juyn                                * */
201 /* *             - fixed bug in chunk-storage of SHOW chunk (from == to)    * */
202 /* *                                                                        * */
203 /* *             1.0.8 - 04/02/2004 - G.Juyn                                * */
204 /* *             - added CRC existence & checking flags                     * */
205 /* *             1.0.8 - 07/07/2004 - G.R-P                                 * */
206 /* *             - change worst-case iAlphadepth to 1 for standalone PNGs   * */
207 /* *                                                                        * */
208 /* *             1.0.9 - 09/28/2004 - G.R-P                                 * */
209 /* *             - improved handling of cheap transparency when 16-bit      * */
210 /* *               support is disabled                                      * */
211 /* *             1.0.9 - 10/04/2004 - G.Juyn                                * */
212 /* *             - fixed bug in writing sBIT for indexed color              * */
213 /* *             1.0.9 - 10/10/2004 - G.R-P.                                * */
214 /* *             - added MNG_NO_1_2_4BIT_SUPPORT                            * */
215 /* *             1.0.9 - 12/05/2004 - G.Juyn                                * */
216 /* *             - added conditional MNG_OPTIMIZE_CHUNKINITFREE             * */
217 /* *             1.0.9 - 12/06/2004 - G.Juyn                                * */
218 /* *             - added conditional MNG_OPTIMIZE_CHUNKASSIGN               * */
219 /* *             1.0.9 - 12/07/2004 - G.Juyn                                * */
220 /* *             - added conditional MNG_OPTIMIZE_CHUNKREADER               * */
221 /* *             1.0.9 - 12/11/2004 - G.Juyn                                * */
222 /* *             - added conditional MNG_OPTIMIZE_DISPLAYCALLS              * */
223 /* *             1.0.9 - 12/20/2004 - G.Juyn                                * */
224 /* *             - cleaned up macro-invocations (thanks to D. Airlie)       * */
225 /* *             1.0.9 - 01/17/2005 - G.Juyn                                * */
226 /* *             - fixed problem with global PLTE/tRNS                      * */
227 /* *                                                                        * */
228 /* *             1.0.10 - 02/07/2005 - G.Juyn                               * */
229 /* *             - fixed display routines called twice for FULL_MNG         * */
230 /* *               support in mozlibmngconf.h                               * */
231 /* *             1.0.10 - 12/04/2005 - G.R-P.                               * */
232 /* *             - #ifdef out use of mng_inflate_buffer when it is not      * */
233 /* *               available.                                               * */
234 /* *             1.0.10 - 04/08/2007 - G.Juyn                               * */
235 /* *             - added support for mPNG proposal                          * */
236 /* *             1.0.10 - 04/12/2007 - G.Juyn                               * */
237 /* *             - added support for ANG proposal                           * */
238 /* *             1.0.10 - 05/02/2007 - G.Juyn                               * */
239 /* *             - fixed inflate_buffer for extreme compression ratios      * */
240 /* *                                                                        * */
241 /* ************************************************************************** */
242 
243 #include "libmng.h"
244 #include "libmng_data.h"
245 #include "libmng_error.h"
246 #include "libmng_trace.h"
247 #ifdef __BORLANDC__
248 #pragma hdrstop
249 #endif
250 #include "libmng_objects.h"
251 #include "libmng_object_prc.h"
252 #include "libmng_chunks.h"
253 #ifdef MNG_CHECK_BAD_ICCP
254 #include "libmng_chunk_prc.h"
255 #endif
256 #include "libmng_memory.h"
257 #include "libmng_display.h"
258 #include "libmng_zlib.h"
259 #include "libmng_pixels.h"
260 #include "libmng_chunk_io.h"
261 
262 #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
263 #pragma option -A                      /* force ANSI-C */
264 #endif
265 
266 /* ************************************************************************** */
267 /* *                                                                        * */
268 /* * CRC - Cyclic Redundancy Check                                          * */
269 /* *                                                                        * */
270 /* * The code below is taken directly from the sample provided with the     * */
271 /* * PNG specification.                                                     * */
272 /* * (it is only adapted to the library's internal data-definitions)        * */
273 /* *                                                                        * */
274 /* ************************************************************************** */
275 /* Make the table for a fast CRC. */
276 #ifndef MNG_USE_ZLIB_CRC
make_crc_table(mng_datap pData)277 MNG_LOCAL void make_crc_table (mng_datap pData)
278 {
279   mng_uint32 iC;
280   mng_int32  iN, iK;
281 
282   for (iN = 0; iN < 256; iN++)
283   {
284     iC = (mng_uint32) iN;
285 
286     for (iK = 0; iK < 8; iK++)
287     {
288       if (iC & 1)
289         iC = 0xedb88320U ^ (iC >> 1);
290       else
291         iC = iC >> 1;
292     }
293 
294     pData->aCRCtable [iN] = iC;
295   }
296 
297   pData->bCRCcomputed = MNG_TRUE;
298 }
299 #endif
300 
301 /* Update a running CRC with the bytes buf[0..len-1]--the CRC
302    should be initialized to all 1's, and the transmitted value
303    is the 1's complement of the final running CRC (see the
304    crc() routine below). */
305 
update_crc(mng_datap pData,mng_uint32 iCrc,mng_uint8p pBuf,mng_int32 iLen)306 MNG_LOCAL mng_uint32 update_crc (mng_datap  pData,
307                                  mng_uint32 iCrc,
308                                  mng_uint8p pBuf,
309                                  mng_int32  iLen)
310 {
311 #ifdef MNG_USE_ZLIB_CRC
312   return crc32 (iCrc, pBuf, iLen);
313 #else
314   mng_uint32 iC = iCrc;
315   mng_int32 iN;
316 
317   if (!pData->bCRCcomputed)
318     make_crc_table (pData);
319 
320   for (iN = 0; iN < iLen; iN++)
321     iC = pData->aCRCtable [(iC ^ pBuf [iN]) & 0xff] ^ (iC >> 8);
322 
323   return iC;
324 #endif
325 }
326 
327 /* Return the CRC of the bytes buf[0..len-1]. */
mng_crc(mng_datap pData,mng_uint8p pBuf,mng_int32 iLen)328 mng_uint32 mng_crc (mng_datap  pData,
329                     mng_uint8p pBuf,
330                     mng_int32  iLen)
331 {
332 #ifdef MNG_USE_ZLIB_CRC
333   return update_crc (pData, 0, pBuf, iLen);
334 #else
335   return update_crc (pData, 0xffffffffU, pBuf, iLen) ^ 0xffffffffU;
336 #endif
337 }
338 
339 /* ************************************************************************** */
340 /* *                                                                        * */
341 /* * Routines for swapping byte-order from and to graphic files             * */
342 /* * (This code is adapted from the libpng package)                         * */
343 /* *                                                                        * */
344 /* ************************************************************************** */
345 
346 #ifndef MNG_BIGENDIAN_SUPPORTED
347 
348 /* ************************************************************************** */
349 
mng_get_uint32(mng_uint8p pBuf)350 mng_uint32 mng_get_uint32 (mng_uint8p pBuf)
351 {
352    mng_uint32 i = ((mng_uint32)(*pBuf)       << 24) +
353                   ((mng_uint32)(*(pBuf + 1)) << 16) +
354                   ((mng_uint32)(*(pBuf + 2)) <<  8) +
355                    (mng_uint32)(*(pBuf + 3));
356    return (i);
357 }
358 
359 /* ************************************************************************** */
360 
mng_get_int32(mng_uint8p pBuf)361 mng_int32 mng_get_int32 (mng_uint8p pBuf)
362 {
363    mng_int32 i = ((mng_int32)(*pBuf)       << 24) +
364                  ((mng_int32)(*(pBuf + 1)) << 16) +
365                  ((mng_int32)(*(pBuf + 2)) <<  8) +
366                   (mng_int32)(*(pBuf + 3));
367    return (i);
368 }
369 
370 /* ************************************************************************** */
371 
mng_get_uint16(mng_uint8p pBuf)372 mng_uint16 mng_get_uint16 (mng_uint8p pBuf)
373 {
374    mng_uint16 i = (mng_uint16)(((mng_uint16)(*pBuf) << 8) +
375                                 (mng_uint16)(*(pBuf + 1)));
376    return (i);
377 }
378 
379 /* ************************************************************************** */
380 
mng_put_uint32(mng_uint8p pBuf,mng_uint32 i)381 void mng_put_uint32 (mng_uint8p pBuf,
382                      mng_uint32 i)
383 {
384    *pBuf     = (mng_uint8)((i >> 24) & 0xff);
385    *(pBuf+1) = (mng_uint8)((i >> 16) & 0xff);
386    *(pBuf+2) = (mng_uint8)((i >> 8) & 0xff);
387    *(pBuf+3) = (mng_uint8)(i & 0xff);
388 }
389 
390 /* ************************************************************************** */
391 
mng_put_int32(mng_uint8p pBuf,mng_int32 i)392 void mng_put_int32 (mng_uint8p pBuf,
393                     mng_int32  i)
394 {
395    *pBuf     = (mng_uint8)((i >> 24) & 0xff);
396    *(pBuf+1) = (mng_uint8)((i >> 16) & 0xff);
397    *(pBuf+2) = (mng_uint8)((i >> 8) & 0xff);
398    *(pBuf+3) = (mng_uint8)(i & 0xff);
399 }
400 
401 /* ************************************************************************** */
402 
mng_put_uint16(mng_uint8p pBuf,mng_uint16 i)403 void mng_put_uint16 (mng_uint8p pBuf,
404                      mng_uint16 i)
405 {
406    *pBuf     = (mng_uint8)((i >> 8) & 0xff);
407    *(pBuf+1) = (mng_uint8)(i & 0xff);
408 }
409 
410 /* ************************************************************************** */
411 
412 #endif /* !MNG_BIGENDIAN_SUPPORTED */
413 
414 /* ************************************************************************** */
415 /* *                                                                        * */
416 /* * Helper routines to simplify chunk-data extraction                      * */
417 /* *                                                                        * */
418 /* ************************************************************************** */
419 
420 #ifdef MNG_INCLUDE_READ_PROCS
421 
422 /* ************************************************************************** */
423 
424 #ifndef MNG_OPTIMIZE_CHUNKREADER
find_null(mng_uint8p pIn)425 MNG_LOCAL mng_uint8p find_null (mng_uint8p pIn)
426 {
427   mng_uint8p pOut = pIn;
428   while (*pOut)                        /* the read_graphic routine has made sure there's */
429     pOut++;                            /* always at least 1 zero-byte in the buffer */
430   return pOut;
431 }
432 #endif
433 
434 /* ************************************************************************** */
435 
436 #if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || \
437     !defined(MNG_SKIPCHUNK_iTXt) || defined(MNG_INCLUDE_MPNG_PROPOSAL) || \
438     defined(MNG_INCLUDE_ANG_PROPOSAL)
mng_inflate_buffer(mng_datap pData,mng_uint8p pInbuf,mng_uint32 iInsize,mng_uint8p * pOutbuf,mng_uint32 * iOutsize,mng_uint32 * iRealsize)439 mng_retcode mng_inflate_buffer (mng_datap  pData,
440                                 mng_uint8p pInbuf,
441                                 mng_uint32 iInsize,
442                                 mng_uint8p *pOutbuf,
443                                 mng_uint32 *iOutsize,
444                                 mng_uint32 *iRealsize)
445 {
446   mng_retcode iRetcode = MNG_NOERROR;
447 
448 #ifdef MNG_SUPPORT_TRACE
449   MNG_TRACE (pData, MNG_FN_INFLATE_BUFFER, MNG_LC_START);
450 #endif
451 
452   if (iInsize)                         /* anything to do ? */
453   {
454     *iOutsize = iInsize * 3;           /* estimate uncompressed size */
455                                        /* and allocate a temporary buffer */
456     MNG_ALLOC (pData, *pOutbuf, *iOutsize);
457 
458     do
459     {
460       mngzlib_inflateinit (pData);     /* initialize zlib */
461                                        /* let zlib know where to store the output */
462       pData->sZlib.next_out  = *pOutbuf;
463                                        /* "size - 1" so we've got space for the
464                                           zero-termination of a possible string */
465       pData->sZlib.avail_out = *iOutsize - 1;
466                                        /* ok; let's inflate... */
467       iRetcode = mngzlib_inflatedata (pData, iInsize, pInbuf);
468                                        /* determine actual output size */
469       *iRealsize = (mng_uint32)pData->sZlib.total_out;
470 
471       mngzlib_inflatefree (pData);     /* zlib's done */
472 
473       if (iRetcode == MNG_BUFOVERFLOW) /* not enough space ? */
474       {                                /* then get some more */
475         MNG_FREEX (pData, *pOutbuf, *iOutsize);
476         *iOutsize = *iOutsize + *iOutsize;
477         MNG_ALLOC (pData, *pOutbuf, *iOutsize);
478       }
479     }                                  /* repeat if we didn't have enough space */
480     while ((iRetcode == MNG_BUFOVERFLOW) &&
481            (*iOutsize < 200 * iInsize));
482 
483     if (!iRetcode)                     /* if oke ? */
484       *((*pOutbuf) + *iRealsize) = 0;  /* then put terminator zero */
485 
486   }
487   else
488   {
489     *pOutbuf   = 0;                    /* nothing to do; then there's no output */
490     *iOutsize  = 0;
491     *iRealsize = 0;
492   }
493 
494 #ifdef MNG_SUPPORT_TRACE
495   MNG_TRACE (pData, MNG_FN_INFLATE_BUFFER, MNG_LC_END);
496 #endif
497 
498   return iRetcode;
499 }
500 #endif
501 
502 /* ************************************************************************** */
503 
504 #endif /* MNG_INCLUDE_READ_PROCS */
505 
506 /* ************************************************************************** */
507 /* *                                                                        * */
508 /* * Helper routines to simplify chunk writing                              * */
509 /* *                                                                        * */
510 /* ************************************************************************** */
511 #ifdef MNG_INCLUDE_WRITE_PROCS
512 /* ************************************************************************** */
513 
514 #if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || !defined(MNG_SKIPCHUNK_iTXt)
deflate_buffer(mng_datap pData,mng_uint8p pInbuf,mng_uint32 iInsize,mng_uint8p * pOutbuf,mng_uint32 * iOutsize,mng_uint32 * iRealsize)515 MNG_LOCAL mng_retcode deflate_buffer (mng_datap  pData,
516                                       mng_uint8p pInbuf,
517                                       mng_uint32 iInsize,
518                                       mng_uint8p *pOutbuf,
519                                       mng_uint32 *iOutsize,
520                                       mng_uint32 *iRealsize)
521 {
522   mng_retcode iRetcode = MNG_NOERROR;
523 
524 #ifdef MNG_SUPPORT_TRACE
525   MNG_TRACE (pData, MNG_FN_DEFLATE_BUFFER, MNG_LC_START);
526 #endif
527 
528   if (iInsize)                         /* anything to do ? */
529   {
530     *iOutsize = (iInsize * 5) >> 2;    /* estimate compressed size */
531                                        /* and allocate a temporary buffer */
532     MNG_ALLOC (pData, *pOutbuf, *iOutsize);
533 
534     do
535     {
536       mngzlib_deflateinit (pData);     /* initialize zlib */
537                                        /* let zlib know where to store the output */
538       pData->sZlib.next_out  = *pOutbuf;
539       pData->sZlib.avail_out = *iOutsize;
540                                        /* ok; let's deflate... */
541       iRetcode = mngzlib_deflatedata (pData, iInsize, pInbuf);
542                                        /* determine actual output size */
543       *iRealsize = pData->sZlib.total_out;
544 
545       mngzlib_deflatefree (pData);     /* zlib's done */
546 
547       if (iRetcode == MNG_BUFOVERFLOW) /* not enough space ? */
548       {                                /* then get some more */
549         MNG_FREEX (pData, *pOutbuf, *iOutsize);
550         *iOutsize = *iOutsize + (iInsize >> 1);
551         MNG_ALLOC (pData, *pOutbuf, *iOutsize);
552       }
553     }                                  /* repeat if we didn't have enough space */
554     while (iRetcode == MNG_BUFOVERFLOW);
555   }
556   else
557   {
558     *pOutbuf   = 0;                    /* nothing to do; then there's no output */
559     *iOutsize  = 0;
560     *iRealsize = 0;
561   }
562 
563 #ifdef MNG_SUPPORT_TRACE
564   MNG_TRACE (pData, MNG_FN_DEFLATE_BUFFER, MNG_LC_END);
565 #endif
566 
567   return iRetcode;
568 }
569 #endif
570 
571 /* ************************************************************************** */
572 
write_raw_chunk(mng_datap pData,mng_chunkid iChunkname,mng_uint32 iRawlen,mng_uint8p pRawdata)573 MNG_LOCAL mng_retcode write_raw_chunk (mng_datap   pData,
574                                        mng_chunkid iChunkname,
575                                        mng_uint32  iRawlen,
576                                        mng_uint8p  pRawdata)
577 {
578   mng_uint32 iCrc;
579   mng_uint32 iWritten;
580 
581 #ifdef MNG_SUPPORT_TRACE
582   MNG_TRACE (pData, MNG_FN_WRITE_RAW_CHUNK, MNG_LC_START);
583 #endif
584                                        /* temporary buffer ? */
585   if ((pRawdata != 0) && (pRawdata != pData->pWritebuf+8))
586   {                                    /* store length & chunktype in default buffer */
587     mng_put_uint32 (pData->pWritebuf,   iRawlen);
588     mng_put_uint32 (pData->pWritebuf+4, (mng_uint32)iChunkname);
589 
590     if (pData->iCrcmode & MNG_CRC_OUTPUT)
591     {
592       if ((pData->iCrcmode & MNG_CRC_OUTPUT) == MNG_CRC_OUTPUT_GENERATE)
593       {                                /* calculate the crc */
594         iCrc = update_crc (pData, 0xffffffffL, pData->pWritebuf+4, 4);
595         iCrc = update_crc (pData, iCrc, pRawdata, iRawlen) ^ 0xffffffffL;
596       } else {
597         iCrc = 0;                      /* dummy crc */
598       }                                /* store in default buffer */
599       mng_put_uint32 (pData->pWritebuf+8, iCrc);
600     }
601                                        /* write the length & chunktype */
602     if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, 8, &iWritten))
603       MNG_ERROR (pData, MNG_APPIOERROR);
604 
605     if (iWritten != 8)                 /* disk full ? */
606       MNG_ERROR (pData, MNG_OUTPUTERROR);
607                                        /* write the temporary buffer */
608     if (!pData->fWritedata ((mng_handle)pData, pRawdata, iRawlen, &iWritten))
609       MNG_ERROR (pData, MNG_APPIOERROR);
610 
611     if (iWritten != iRawlen)           /* disk full ? */
612       MNG_ERROR (pData, MNG_OUTPUTERROR);
613 
614     if (pData->iCrcmode & MNG_CRC_OUTPUT)
615     {                                  /* write the crc */
616       if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf+8, 4, &iWritten))
617         MNG_ERROR (pData, MNG_APPIOERROR);
618 
619       if (iWritten != 4)               /* disk full ? */
620         MNG_ERROR (pData, MNG_OUTPUTERROR);
621     }
622   }
623   else
624   {                                    /* prefix with length & chunktype */
625     mng_put_uint32 (pData->pWritebuf,   iRawlen);
626     mng_put_uint32 (pData->pWritebuf+4, (mng_uint32)iChunkname);
627 
628     if (pData->iCrcmode & MNG_CRC_OUTPUT)
629     {
630       if ((pData->iCrcmode & MNG_CRC_OUTPUT) == MNG_CRC_OUTPUT_GENERATE)
631                                        /* calculate the crc */
632         iCrc = mng_crc (pData, pData->pWritebuf+4, iRawlen + 4);
633       else
634         iCrc = 0;                      /* dummy crc */
635                                        /* add it to the buffer */
636       mng_put_uint32 (pData->pWritebuf + iRawlen + 8, iCrc);
637                                        /* write it in a single pass */
638       if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, iRawlen + 12, &iWritten))
639         MNG_ERROR (pData, MNG_APPIOERROR);
640 
641       if (iWritten != iRawlen + 12)    /* disk full ? */
642         MNG_ERROR (pData, MNG_OUTPUTERROR);
643     } else {
644       if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, iRawlen + 8, &iWritten))
645         MNG_ERROR (pData, MNG_APPIOERROR);
646 
647       if (iWritten != iRawlen + 8)     /* disk full ? */
648         MNG_ERROR (pData, MNG_OUTPUTERROR);
649     }
650   }
651 
652 #ifdef MNG_SUPPORT_TRACE
653   MNG_TRACE (pData, MNG_FN_WRITE_RAW_CHUNK, MNG_LC_END);
654 #endif
655 
656   return MNG_NOERROR;
657 }
658 
659 /* ************************************************************************** */
660 /* B004 */
661 #endif /* MNG_INCLUDE_WRITE_PROCS */
662 /* B004 */
663 /* ************************************************************************** */
664 /* *                                                                        * */
665 /* * chunk read functions                                                   * */
666 /* *                                                                        * */
667 /* ************************************************************************** */
668 
669 #ifdef MNG_INCLUDE_READ_PROCS
670 
671 /* ************************************************************************** */
672 
673 #ifdef MNG_OPTIMIZE_CHUNKREADER
674 
675 /* ************************************************************************** */
676 
create_chunk_storage(mng_datap pData,mng_chunkp pHeader,mng_uint32 iRawlen,mng_uint8p pRawdata,mng_field_descp pField,mng_uint16 iFields,mng_chunkp * ppChunk,mng_bool bWorkcopy)677 MNG_LOCAL mng_retcode create_chunk_storage (mng_datap       pData,
678                                             mng_chunkp      pHeader,
679                                             mng_uint32      iRawlen,
680                                             mng_uint8p      pRawdata,
681                                             mng_field_descp pField,
682                                             mng_uint16      iFields,
683                                             mng_chunkp*     ppChunk,
684                                             mng_bool        bWorkcopy)
685 {
686   mng_field_descp pTempfield  = pField;
687   mng_uint16      iFieldcount = iFields;
688   mng_uint8p      pTempdata   = pRawdata;
689   mng_uint32      iTemplen    = iRawlen;
690   mng_uint16      iLastgroup  = 0;
691   mng_uint8p      pChunkdata;
692   mng_uint32      iDatalen;
693   mng_uint8       iColortype;
694   mng_bool        bProcess;
695                                        /* initialize storage */
696   mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
697   if (iRetcode)                        /* on error bail out */
698     return iRetcode;
699 
700   if (((mng_chunk_headerp)(*ppChunk))->iChunkname == MNG_UINT_HUH)
701     ((mng_chunk_headerp)(*ppChunk))->iChunkname = pData->iChunkname;
702 
703   if ((!bWorkcopy) ||
704       ((((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_IDAT) &&
705        (((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_JDAT) &&
706        (((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_JDAA)   ))
707   {
708     pChunkdata = (mng_uint8p)(*ppChunk);
709 
710 #ifdef MNG_INCLUDE_JNG                 /* determine current colortype */
711     if (pData->bHasJHDR)
712       iColortype = (mng_uint8)(pData->iJHDRcolortype - 8);
713     else
714 #endif /* MNG_INCLUDE_JNG */
715     if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
716       iColortype = pData->iColortype;
717     else
718       iColortype = 6;
719 
720     if (iTemplen)                      /* not empty ? */
721     {                                  /* then go fill the fields */
722       while ((iFieldcount) && (iTemplen))
723       {
724         if (pTempfield->iOffsetchunk)
725         {
726           if (pTempfield->iFlags & MNG_FIELD_PUTIMGTYPE)
727           {
728             *(pChunkdata+pTempfield->iOffsetchunk) = iColortype;
729             bProcess = MNG_FALSE;
730           }
731           else
732           if (pTempfield->iFlags & MNG_FIELD_IFIMGTYPES)
733             bProcess = (mng_bool)(((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE0) && (iColortype == 0)) ||
734                                   ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE2) && (iColortype == 2)) ||
735                                   ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE3) && (iColortype == 3)) ||
736                                   ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE4) && (iColortype == 4)) ||
737                                   ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE6) && (iColortype == 6))   );
738           else
739             bProcess = MNG_TRUE;
740 
741           if (bProcess)
742           {
743             iLastgroup = (mng_uint16)(pTempfield->iFlags & MNG_FIELD_GROUPMASK);
744                                       /* numeric field ? */
745             if (pTempfield->iFlags & MNG_FIELD_INT)
746             {
747               if (iTemplen < pTempfield->iLengthmax)
748                 MNG_ERROR (pData, MNG_INVALIDLENGTH);
749 
750               switch (pTempfield->iLengthmax)
751               {
752                 case 1 : { mng_uint8 iNum = *pTempdata;
753                            if (((mng_uint16)iNum < pTempfield->iMinvalue) ||
754                                ((mng_uint16)iNum > pTempfield->iMaxvalue)    )
755                              MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
756                            *(pChunkdata+pTempfield->iOffsetchunk) = iNum;
757                            break; }
758                 case 2 : { mng_uint16 iNum = mng_get_uint16 (pTempdata);
759                            if ((iNum < pTempfield->iMinvalue) || (iNum > pTempfield->iMaxvalue))
760                              MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
761                            *((mng_uint16p)(pChunkdata+pTempfield->iOffsetchunk)) = iNum;
762                            break; }
763                 case 4 : { mng_uint32 iNum = mng_get_uint32 (pTempdata);
764                            if ((iNum < pTempfield->iMinvalue) ||
765                                ((pTempfield->iFlags & MNG_FIELD_NOHIGHBIT) && (iNum & 0x80000000)) )
766                              MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
767                            *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunk)) = iNum;
768                            break; }
769               }
770 
771               pTempdata += pTempfield->iLengthmax;
772               iTemplen  -= pTempfield->iLengthmax;
773 
774             } else {                   /* not numeric so it's a bunch of bytes */
775 
776               if (!pTempfield->iOffsetchunklen)    /* big fat NONO */
777                 MNG_ERROR (pData, MNG_INTERNALERROR);
778                                        /* with terminating 0 ? */
779               if (pTempfield->iFlags & MNG_FIELD_TERMINATOR)
780               {
781                 mng_uint8p pWork = pTempdata;
782                 while (*pWork)         /* find the zero */
783                   pWork++;
784                 iDatalen = (mng_uint32)(pWork - pTempdata);
785               } else {                 /* no terminator, so everything that's left ! */
786                 iDatalen = iTemplen;
787               }
788 
789               if ((pTempfield->iLengthmax) && (iDatalen > pTempfield->iLengthmax))
790                 MNG_ERROR (pData, MNG_INVALIDLENGTH);
791 #if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || \
792     !defined(MNG_SKIPCHUNK_iTXt) || defined(MNG_INCLUDE_MPNG_PROPOSAL) || \
793     defined(MNG_INCLUDE_ANG_PROPOSAL)
794                                        /* needs decompression ? */
795               if (pTempfield->iFlags & MNG_FIELD_DEFLATED)
796               {
797                 mng_uint8p pBuf = 0;
798                 mng_uint32 iBufsize = 0;
799                 mng_uint32 iRealsize;
800                 mng_ptr    pWork;
801 
802                 iRetcode = mng_inflate_buffer (pData, pTempdata, iDatalen,
803                                                &pBuf, &iBufsize, &iRealsize);
804 
805 #ifdef MNG_CHECK_BAD_ICCP              /* Check for bad iCCP chunk */
806                 if ((iRetcode) && (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_iCCP))
807                 {
808                   *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk))      = MNG_NULL;
809                   *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iDatalen;
810                 }
811                 else
812 #endif
813                 {
814                   if (iRetcode)
815                     return iRetcode;
816 
817 #if defined(MNG_INCLUDE_MPNG_PROPOSAL) || defined(MNG_INCLUDE_ANG_PROPOSAL)
818                   if ( (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_mpNG) ||
819                        (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_adAT)    )
820                   {
821                     MNG_ALLOC (pData, pWork, iRealsize);
822                   }
823                   else
824                   {
825 #endif
826                                        /* don't forget to generate null terminator */
827                     MNG_ALLOC (pData, pWork, iRealsize+1);
828 #if defined(MNG_INCLUDE_MPNG_PROPOSAL) || defined(MNG_INCLUDE_ANG_PROPOSAL)
829                   }
830 #endif
831                   MNG_COPY (pWork, pBuf, iRealsize);
832 
833                   *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk))      = pWork;
834                   *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iRealsize;
835                 }
836 
837                 if (pBuf)              /* free the temporary buffer */
838                   MNG_FREEX (pData, pBuf, iBufsize);
839 
840               } else
841 #endif
842                      {                 /* no decompression, so just copy */
843 
844                 mng_ptr pWork;
845                                        /* don't forget to generate null terminator */
846                 MNG_ALLOC (pData, pWork, iDatalen+1);
847                 MNG_COPY (pWork, pTempdata, iDatalen);
848 
849                 *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk))      = pWork;
850                 *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iDatalen;
851               }
852 
853               if (pTempfield->iFlags & MNG_FIELD_TERMINATOR)
854                 iDatalen++;            /* skip the terminating zero as well !!! */
855 
856               iTemplen  -= iDatalen;
857               pTempdata += iDatalen;
858             }
859                                        /* need to set an indicator ? */
860             if (pTempfield->iOffsetchunkind)
861               *((mng_uint8p)(pChunkdata+pTempfield->iOffsetchunkind)) = MNG_TRUE;
862           }
863         }
864 
865         if (pTempfield->pSpecialfunc)  /* special function required ? */
866         {
867           iRetcode = pTempfield->pSpecialfunc(pData, *ppChunk, &iTemplen, &pTempdata);
868           if (iRetcode)                /* on error bail out */
869             return iRetcode;
870         }
871 
872         pTempfield++;                  /* Neeeeeeexxxtt */
873         iFieldcount--;
874       }
875 
876       if (iTemplen)                    /* extra data ??? */
877         MNG_ERROR (pData, MNG_INVALIDLENGTH);
878 
879       while (iFieldcount)              /* not enough data ??? */
880       {
881         if (pTempfield->iFlags & MNG_FIELD_IFIMGTYPES)
882           bProcess = (mng_bool)(((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE0) && (iColortype == 0)) ||
883                                 ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE2) && (iColortype == 2)) ||
884                                 ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE3) && (iColortype == 3)) ||
885                                 ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE4) && (iColortype == 4)) ||
886                                 ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE6) && (iColortype == 6))   );
887         else
888           bProcess = MNG_TRUE;
889 
890         if (bProcess)
891         {
892           if (!(pTempfield->iFlags & MNG_FIELD_OPTIONAL))
893             MNG_ERROR (pData, MNG_INVALIDLENGTH);
894           if ((pTempfield->iFlags & MNG_FIELD_GROUPMASK) &&
895               ((mng_uint16)(pTempfield->iFlags & MNG_FIELD_GROUPMASK) == iLastgroup))
896             MNG_ERROR (pData, MNG_INVALIDLENGTH);
897         }
898 
899         pTempfield++;
900         iFieldcount--;
901       }
902     }
903   }
904 
905   return MNG_NOERROR;
906 }
907 
908 /* ************************************************************************** */
909 
READ_CHUNK(mng_read_general)910 READ_CHUNK (mng_read_general)
911 {
912   mng_retcode     iRetcode = MNG_NOERROR;
913   mng_chunk_descp pDescr   = ((mng_chunk_headerp)pHeader)->pChunkdescr;
914   mng_field_descp pField;
915   mng_uint16      iFields;
916 
917   if (!pDescr)                         /* this is a bad booboo !!! */
918     MNG_ERROR (pData, MNG_INTERNALERROR);
919 
920   pField  = pDescr->pFielddesc;
921   iFields = pDescr->iFielddesc;
922                                        /* check chunk against signature */
923   if ((pDescr->eImgtype == mng_it_mng) && (pData->eSigtype != mng_it_mng))
924     MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
925 
926   if ((pDescr->eImgtype == mng_it_jng) && (pData->eSigtype == mng_it_png))
927     MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
928                                        /* empties allowed ? */
929   if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTY)))
930     MNG_ERROR (pData, MNG_INVALIDLENGTH);
931 
932   if ((pData->eImagetype != mng_it_mng) || (!(pDescr->iAllowed & MNG_DESCR_GLOBAL)))
933   {                                    /* *a* header required ? */
934     if ((pDescr->iMusthaves & MNG_DESCR_GenHDR) &&
935 #ifdef MNG_INCLUDE_JNG
936         (!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
937 #else
938         (!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR))
939 #endif
940       MNG_ERROR (pData, MNG_SEQUENCEERROR);
941 
942 #ifdef MNG_INCLUDE_JNG
943     if ((pDescr->iMusthaves & MNG_DESCR_JngHDR) &&
944         (!pData->bHasDHDR) && (!pData->bHasJHDR))
945       MNG_ERROR (pData, MNG_SEQUENCEERROR);
946 #endif
947   }
948                                        /* specific chunk pre-requisite ? */
949   if (((pDescr->iMusthaves & MNG_DESCR_IHDR) && (!pData->bHasIHDR)) ||
950 #ifdef MNG_INCLUDE_JNG
951       ((pDescr->iMusthaves & MNG_DESCR_JHDR) && (!pData->bHasJHDR)) ||
952 #endif
953       ((pDescr->iMusthaves & MNG_DESCR_DHDR) && (!pData->bHasDHDR)) ||
954       ((pDescr->iMusthaves & MNG_DESCR_LOOP) && (!pData->bHasLOOP)) ||
955       ((pDescr->iMusthaves & MNG_DESCR_PLTE) && (!pData->bHasPLTE)) ||
956       ((pDescr->iMusthaves & MNG_DESCR_MHDR) && (!pData->bHasMHDR)) ||
957       ((pDescr->iMusthaves & MNG_DESCR_SAVE) && (!pData->bHasSAVE))   )
958     MNG_ERROR (pData, MNG_SEQUENCEERROR);
959                                        /* specific chunk undesired ? */
960   if (((pDescr->iMustNOThaves & MNG_DESCR_NOIHDR) && (pData->bHasIHDR)) ||
961       ((pDescr->iMustNOThaves & MNG_DESCR_NOBASI) && (pData->bHasBASI)) ||
962       ((pDescr->iMustNOThaves & MNG_DESCR_NODHDR) && (pData->bHasDHDR)) ||
963       ((pDescr->iMustNOThaves & MNG_DESCR_NOIDAT) && (pData->bHasIDAT)) ||
964       ((pDescr->iMustNOThaves & MNG_DESCR_NOPLTE) && (pData->bHasPLTE)) ||
965 #ifdef MNG_INCLUDE_JNG
966       ((pDescr->iMustNOThaves & MNG_DESCR_NOJHDR) && (pData->bHasJHDR)) ||
967       ((pDescr->iMustNOThaves & MNG_DESCR_NOJDAT) && (pData->bHasJDAT)) ||
968       ((pDescr->iMustNOThaves & MNG_DESCR_NOJDAA) && (pData->bHasJDAA)) ||
969       ((pDescr->iMustNOThaves & MNG_DESCR_NOJSEP) && (pData->bHasJSEP)) ||
970 #endif
971       ((pDescr->iMustNOThaves & MNG_DESCR_NOMHDR) && (pData->bHasMHDR)) ||
972       ((pDescr->iMustNOThaves & MNG_DESCR_NOLOOP) && (pData->bHasLOOP)) ||
973       ((pDescr->iMustNOThaves & MNG_DESCR_NOTERM) && (pData->bHasTERM)) ||
974       ((pDescr->iMustNOThaves & MNG_DESCR_NOSAVE) && (pData->bHasSAVE))   )
975     MNG_ERROR (pData, MNG_SEQUENCEERROR);
976 
977   if (pData->eSigtype == mng_it_mng)   /* check global and embedded empty chunks */
978   {
979 #ifdef MNG_INCLUDE_JNG
980     if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
981 #else
982     if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
983 #endif
984     {
985       if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTYEMBED)))
986         MNG_ERROR (pData, MNG_INVALIDLENGTH);
987     } else {
988       if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTYGLOBAL)))
989         MNG_ERROR (pData, MNG_INVALIDLENGTH);
990     }
991   }
992 
993   if (pDescr->pSpecialfunc)            /* need special processing ? */
994   {
995     iRetcode = create_chunk_storage (pData, pHeader, iRawlen, pRawdata,
996                                      pField, iFields, ppChunk, MNG_TRUE);
997     if (iRetcode)                      /* on error bail out */
998       return iRetcode;
999                                        /* empty indicator ? */
1000     if ((!iRawlen) && (pDescr->iOffsetempty))
1001       *(((mng_uint8p)*ppChunk)+pDescr->iOffsetempty) = MNG_TRUE;
1002 
1003     iRetcode = pDescr->pSpecialfunc(pData, *ppChunk);
1004     if (iRetcode)                      /* on error bail out */
1005       return iRetcode;
1006 
1007     if ((((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT) ||
1008         (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT) ||
1009         (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA)    )
1010     {
1011       iRetcode = ((mng_chunk_headerp)*ppChunk)->fCleanup (pData, *ppChunk);
1012       if (iRetcode)                    /* on error bail out */
1013         return iRetcode;
1014       *ppChunk = MNG_NULL;
1015     } else {
1016 #ifdef MNG_STORE_CHUNKS
1017       if (!pData->bStorechunks)
1018 #endif
1019       {
1020         iRetcode = ((mng_chunk_headerp)*ppChunk)->fCleanup (pData, *ppChunk);
1021         if (iRetcode)                  /* on error bail out */
1022           return iRetcode;
1023         *ppChunk = MNG_NULL;
1024       }
1025     }
1026   }
1027 
1028 #ifdef MNG_SUPPORT_DISPLAY
1029   if (iRawlen)
1030   {
1031 #ifdef MNG_OPTIMIZE_DISPLAYCALLS
1032     pData->iRawlen  = iRawlen;
1033     pData->pRawdata = pRawdata;
1034 #endif
1035 
1036                                        /* display processing */
1037 #ifndef MNG_OPTIMIZE_DISPLAYCALLS
1038     if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT)
1039       iRetcode = mng_process_display_idat (pData, iRawlen, pRawdata);
1040 #ifdef MNG_INCLUDE_JNG
1041     else
1042     if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT)
1043       iRetcode = mng_process_display_jdat (pData, iRawlen, pRawdata);
1044     else
1045     if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA)
1046       iRetcode = mng_process_display_jdaa (pData, iRawlen, pRawdata);
1047 #endif
1048 #else
1049     if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT)
1050       iRetcode = mng_process_display_idat (pData);
1051 #ifdef MNG_INCLUDE_JNG
1052     else
1053     if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT)
1054       iRetcode = mng_process_display_jdat (pData);
1055     else
1056     if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA)
1057       iRetcode = mng_process_display_jdaa (pData);
1058 #endif
1059 #endif
1060 
1061     if (iRetcode)
1062       return iRetcode;
1063   }
1064 #endif /* MNG_SUPPORT_DISPLAY */
1065 
1066 #ifdef MNG_STORE_CHUNKS
1067   if ((pData->bStorechunks) && (!(*ppChunk)))
1068   {
1069     iRetcode = create_chunk_storage (pData, pHeader, iRawlen, pRawdata,
1070                                      pField, iFields, ppChunk, MNG_FALSE);
1071     if (iRetcode)                      /* on error bail out */
1072       return iRetcode;
1073                                        /* empty indicator ? */
1074     if ((!iRawlen) && (pDescr->iOffsetempty))
1075       *(((mng_uint8p)*ppChunk)+pDescr->iOffsetempty) = MNG_TRUE;
1076   }
1077 #endif /* MNG_STORE_CHUNKS */
1078 
1079   return MNG_NOERROR;
1080 }
1081 
1082 /* ************************************************************************** */
1083 
1084 #endif /* MNG_OPTIMIZE_CHUNKREADER */
1085 
1086 /* ************************************************************************** */
1087 
1088 #ifndef MNG_OPTIMIZE_CHUNKREADER
READ_CHUNK(mng_read_ihdr)1089 READ_CHUNK (mng_read_ihdr)
1090 {
1091 #ifdef MNG_SUPPORT_TRACE
1092   MNG_TRACE (pData, MNG_FN_READ_IHDR, MNG_LC_START);
1093 #endif
1094 
1095   if (iRawlen != 13)                   /* length oke ? */
1096     MNG_ERROR (pData, MNG_INVALIDLENGTH);
1097                                        /* only allowed inside PNG or MNG */
1098   if ((pData->eSigtype != mng_it_png) && (pData->eSigtype != mng_it_mng))
1099     MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
1100                                        /* sequence checks */
1101   if ((pData->eSigtype == mng_it_png) && (pData->iChunkseq > 1))
1102     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1103 
1104 #ifdef MNG_INCLUDE_JNG
1105   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasIDAT) || (pData->bHasJHDR))
1106 #else
1107   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasIDAT))
1108 #endif
1109     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1110 
1111   pData->bHasIHDR      = MNG_TRUE;     /* indicate IHDR is present */
1112                                        /* and store interesting fields */
1113   if ((!pData->bHasDHDR) || (pData->iDeltatype == MNG_DELTATYPE_NOCHANGE))
1114   {
1115     pData->iDatawidth  = mng_get_uint32 (pRawdata);
1116     pData->iDataheight = mng_get_uint32 (pRawdata+4);
1117   }
1118 
1119   pData->iBitdepth     = *(pRawdata+8);
1120   pData->iColortype    = *(pRawdata+9);
1121   pData->iCompression  = *(pRawdata+10);
1122   pData->iFilter       = *(pRawdata+11);
1123   pData->iInterlace    = *(pRawdata+12);
1124 
1125 #if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
1126   pData->iPNGmult = 1;
1127   pData->iPNGdepth = pData->iBitdepth;
1128 #endif
1129 
1130 #ifdef MNG_NO_1_2_4BIT_SUPPORT
1131   if (pData->iBitdepth < 8)
1132       pData->iBitdepth = 8;
1133 #endif
1134 
1135 #ifdef MNG_NO_16BIT_SUPPORT
1136   if (pData->iBitdepth > 8)
1137     {
1138       pData->iBitdepth = 8;
1139       pData->iPNGmult = 2;
1140     }
1141 #endif
1142 
1143   if ((pData->iBitdepth !=  8)      /* parameter validity checks */
1144 #ifndef MNG_NO_1_2_4BIT_SUPPORT
1145       && (pData->iBitdepth !=  1) &&
1146       (pData->iBitdepth !=  2) &&
1147       (pData->iBitdepth !=  4)
1148 #endif
1149 #ifndef MNG_NO_16BIT_SUPPORT
1150       && (pData->iBitdepth != 16)
1151 #endif
1152       )
1153     MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
1154 
1155   if ((pData->iColortype != MNG_COLORTYPE_GRAY   ) &&
1156       (pData->iColortype != MNG_COLORTYPE_RGB    ) &&
1157       (pData->iColortype != MNG_COLORTYPE_INDEXED) &&
1158       (pData->iColortype != MNG_COLORTYPE_GRAYA  ) &&
1159       (pData->iColortype != MNG_COLORTYPE_RGBA   )    )
1160     MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
1161 
1162   if ((pData->iColortype == MNG_COLORTYPE_INDEXED) && (pData->iBitdepth > 8))
1163     MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
1164 
1165   if (((pData->iColortype == MNG_COLORTYPE_RGB    ) ||
1166        (pData->iColortype == MNG_COLORTYPE_GRAYA  ) ||
1167        (pData->iColortype == MNG_COLORTYPE_RGBA   )    ) &&
1168       (pData->iBitdepth < 8                            )    )
1169     MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
1170 
1171   if (pData->iCompression != MNG_COMPRESSION_DEFLATE)
1172     MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
1173 
1174 #if defined(FILTER192) || defined(FILTER193)
1175   if ((pData->iFilter != MNG_FILTER_ADAPTIVE ) &&
1176 #if defined(FILTER192) && defined(FILTER193)
1177       (pData->iFilter != MNG_FILTER_DIFFERING) &&
1178       (pData->iFilter != MNG_FILTER_NOFILTER )    )
1179 #else
1180 #ifdef FILTER192
1181       (pData->iFilter != MNG_FILTER_DIFFERING)    )
1182 #else
1183       (pData->iFilter != MNG_FILTER_NOFILTER )    )
1184 #endif
1185 #endif
1186     MNG_ERROR (pData, MNG_INVALIDFILTER);
1187 #else
1188   if (pData->iFilter)
1189     MNG_ERROR (pData, MNG_INVALIDFILTER);
1190 #endif
1191 
1192   if ((pData->iInterlace != MNG_INTERLACE_NONE ) &&
1193       (pData->iInterlace != MNG_INTERLACE_ADAM7)    )
1194     MNG_ERROR (pData, MNG_INVALIDINTERLACE);
1195 
1196 #ifdef MNG_SUPPORT_DISPLAY
1197 #ifndef MNG_NO_DELTA_PNG
1198   if (pData->bHasDHDR)                 /* check the colortype for delta-images ! */
1199   {
1200     mng_imagedatap pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
1201 
1202     if (pData->iColortype != pBuf->iColortype)
1203     {
1204       if ( ( (pData->iColortype != MNG_COLORTYPE_INDEXED) ||
1205              (pBuf->iColortype  == MNG_COLORTYPE_GRAY   )    ) &&
1206            ( (pData->iColortype != MNG_COLORTYPE_GRAY   ) ||
1207              (pBuf->iColortype  == MNG_COLORTYPE_INDEXED)    )    )
1208         MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
1209     }
1210   }
1211 #endif
1212 #endif
1213 
1214   if (!pData->bHasheader)              /* first chunk ? */
1215   {
1216     pData->bHasheader = MNG_TRUE;      /* we've got a header */
1217     pData->eImagetype = mng_it_png;    /* then this must be a PNG */
1218     pData->iWidth     = pData->iDatawidth;
1219     pData->iHeight    = pData->iDataheight;
1220                                        /* predict alpha-depth ! */
1221     if ((pData->iColortype == MNG_COLORTYPE_GRAYA  ) ||
1222         (pData->iColortype == MNG_COLORTYPE_RGBA   )    )
1223       pData->iAlphadepth = pData->iBitdepth;
1224     else
1225     if (pData->iColortype == MNG_COLORTYPE_INDEXED)
1226       pData->iAlphadepth = 8;          /* worst case scenario */
1227     else
1228       pData->iAlphadepth = 1;  /* Possible tRNS cheap binary transparency */
1229                                        /* fits on maximum canvas ? */
1230     if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
1231       MNG_WARNING (pData, MNG_IMAGETOOLARGE);
1232 
1233 #if !defined(MNG_INCLUDE_MPNG_PROPOSAL) || !defined(MNG_SUPPORT_DISPLAY)
1234     if (pData->fProcessheader)         /* inform the app ? */
1235       if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
1236         MNG_ERROR (pData, MNG_APPMISCERROR);
1237 #endif
1238   }
1239 
1240   if (!pData->bHasDHDR)
1241     pData->iImagelevel++;              /* one level deeper */
1242 
1243 #ifdef MNG_SUPPORT_DISPLAY
1244   {
1245     mng_retcode iRetcode = mng_process_display_ihdr (pData);
1246 
1247     if (iRetcode)                      /* on error bail out */
1248       return iRetcode;
1249   }
1250 #endif /* MNG_SUPPORT_DISPLAY */
1251 
1252 #ifdef MNG_STORE_CHUNKS
1253   if (pData->bStorechunks)
1254   {                                    /* initialize storage */
1255     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
1256 
1257     if (iRetcode)                      /* on error bail out */
1258       return iRetcode;
1259                                        /* fill the fields */
1260     ((mng_ihdrp)*ppChunk)->iWidth       = mng_get_uint32 (pRawdata);
1261     ((mng_ihdrp)*ppChunk)->iHeight      = mng_get_uint32 (pRawdata+4);
1262     ((mng_ihdrp)*ppChunk)->iBitdepth    = pData->iBitdepth;
1263     ((mng_ihdrp)*ppChunk)->iColortype   = pData->iColortype;
1264     ((mng_ihdrp)*ppChunk)->iCompression = pData->iCompression;
1265     ((mng_ihdrp)*ppChunk)->iFilter      = pData->iFilter;
1266     ((mng_ihdrp)*ppChunk)->iInterlace   = pData->iInterlace;
1267   }
1268 #endif /* MNG_STORE_CHUNKS */
1269 
1270 #ifdef MNG_SUPPORT_TRACE
1271   MNG_TRACE (pData, MNG_FN_READ_IHDR, MNG_LC_END);
1272 #endif
1273 
1274   return MNG_NOERROR;                  /* done */
1275 }
1276 #endif /* MNG_OPTIMIZE_CHUNKREADER */
1277 
1278 /* ************************************************************************** */
1279 
1280 #ifndef MNG_OPTIMIZE_CHUNKREADER
READ_CHUNK(mng_read_plte)1281 READ_CHUNK (mng_read_plte)
1282 {
1283 #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
1284   mng_uint32  iX;
1285   mng_uint8p  pRawdata2;
1286 #endif
1287 #ifdef MNG_SUPPORT_DISPLAY
1288   mng_uint32  iRawlen2;
1289 #endif
1290 
1291 #ifdef MNG_SUPPORT_TRACE
1292   MNG_TRACE (pData, MNG_FN_READ_PLTE, MNG_LC_START);
1293 #endif
1294                                        /* sequence checks */
1295   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
1296       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
1297     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1298 
1299 #ifdef MNG_INCLUDE_JNG
1300   if ((pData->bHasIDAT) || (pData->bHasJHDR))
1301 #else
1302   if (pData->bHasIDAT)
1303 #endif
1304     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1305                                        /* multiple PLTE only inside BASI */
1306   if ((pData->bHasPLTE) && (!pData->bHasBASI))
1307     MNG_ERROR (pData, MNG_MULTIPLEERROR);
1308                                        /* length must be multiple of 3 */
1309   if (((iRawlen % 3) != 0) || (iRawlen > 768))
1310     MNG_ERROR (pData, MNG_INVALIDLENGTH);
1311 
1312   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
1313   {                                    /* only allowed for indexed-color or
1314                                           rgb(a)-color! */
1315     if ((pData->iColortype != 2) && (pData->iColortype != 3) && (pData->iColortype != 6))
1316       MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
1317                                        /* empty only allowed if global present */
1318     if ((iRawlen == 0) && (!pData->bHasglobalPLTE))
1319         MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
1320   }
1321   else
1322   {
1323     if (iRawlen == 0)                  /* cannot be empty as global! */
1324       MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
1325   }
1326 
1327   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
1328     pData->bHasPLTE = MNG_TRUE;        /* got it! */
1329   else
1330     pData->bHasglobalPLTE = MNG_TRUE;
1331 
1332   pData->iPLTEcount = iRawlen / 3;
1333 
1334 #ifdef MNG_SUPPORT_DISPLAY
1335   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
1336   {
1337     mng_imagep     pImage;
1338     mng_imagedatap pBuf;
1339 
1340 #ifndef MNG_NO_DELTA_PNG
1341     if (pData->bHasDHDR)               /* processing delta-image ? */
1342     {                                  /* store in object 0 !!! */
1343       pImage           = (mng_imagep)pData->pObjzero;
1344       pBuf             = pImage->pImgbuf;
1345       pBuf->bHasPLTE   = MNG_TRUE;     /* it's definitely got a PLTE now */
1346       pBuf->iPLTEcount = iRawlen / 3;  /* this is the exact length */
1347       pRawdata2        = pRawdata;     /* copy the entries */
1348 
1349       for (iX = 0; iX < iRawlen / 3; iX++)
1350       {
1351         pBuf->aPLTEentries[iX].iRed   = *pRawdata2;
1352         pBuf->aPLTEentries[iX].iGreen = *(pRawdata2+1);
1353         pBuf->aPLTEentries[iX].iBlue  = *(pRawdata2+2);
1354 
1355         pRawdata2 += 3;
1356       }
1357     }
1358     else
1359 #endif
1360     {                                  /* get the current object */
1361       pImage = (mng_imagep)pData->pCurrentobj;
1362 
1363       if (!pImage)                     /* no object then dump it in obj 0 */
1364         pImage = (mng_imagep)pData->pObjzero;
1365 
1366       pBuf = pImage->pImgbuf;          /* address the object buffer */
1367       pBuf->bHasPLTE = MNG_TRUE;       /* and tell it it's got a PLTE now */
1368 
1369       if (!iRawlen)                    /* if empty, inherit from global */
1370       {
1371         pBuf->iPLTEcount = pData->iGlobalPLTEcount;
1372         MNG_COPY (pBuf->aPLTEentries, pData->aGlobalPLTEentries,
1373                   sizeof (pBuf->aPLTEentries));
1374 
1375         if (pData->bHasglobalTRNS)     /* also copy global tRNS ? */
1376         {                              /* indicate tRNS available */
1377           pBuf->bHasTRNS = MNG_TRUE;
1378 
1379           iRawlen2  = pData->iGlobalTRNSrawlen;
1380           pRawdata2 = (mng_uint8p)(pData->aGlobalTRNSrawdata);
1381                                        /* global length oke ? */
1382           if ((iRawlen2 == 0) || (iRawlen2 > pBuf->iPLTEcount))
1383             MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
1384                                        /* copy it */
1385           pBuf->iTRNScount = iRawlen2;
1386           MNG_COPY (pBuf->aTRNSentries, pRawdata2, iRawlen2);
1387         }
1388       }
1389       else
1390       {                                /* store fields for future reference */
1391         pBuf->iPLTEcount = iRawlen / 3;
1392         pRawdata2        = pRawdata;
1393 
1394         for (iX = 0; iX < pBuf->iPLTEcount; iX++)
1395         {
1396           pBuf->aPLTEentries[iX].iRed   = *pRawdata2;
1397           pBuf->aPLTEentries[iX].iGreen = *(pRawdata2+1);
1398           pBuf->aPLTEentries[iX].iBlue  = *(pRawdata2+2);
1399 
1400           pRawdata2 += 3;
1401         }
1402       }
1403     }
1404   }
1405   else                                 /* store as global */
1406   {
1407     pData->iGlobalPLTEcount = iRawlen / 3;
1408     pRawdata2               = pRawdata;
1409 
1410     for (iX = 0; iX < pData->iGlobalPLTEcount; iX++)
1411     {
1412       pData->aGlobalPLTEentries[iX].iRed   = *pRawdata2;
1413       pData->aGlobalPLTEentries[iX].iGreen = *(pRawdata2+1);
1414       pData->aGlobalPLTEentries[iX].iBlue  = *(pRawdata2+2);
1415 
1416       pRawdata2 += 3;
1417     }
1418 
1419     {                                  /* create an animation object */
1420       mng_retcode iRetcode = mng_create_ani_plte (pData, pData->iGlobalPLTEcount,
1421                                                   pData->aGlobalPLTEentries);
1422       if (iRetcode)                    /* on error bail out */
1423         return iRetcode;
1424     }
1425   }
1426 #endif /* MNG_SUPPORT_DISPLAY */
1427 
1428 #ifdef MNG_STORE_CHUNKS
1429   if (pData->bStorechunks)
1430   {                                    /* initialize storage */
1431     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
1432 
1433     if (iRetcode)                      /* on error bail out */
1434       return iRetcode;
1435                                        /* store the fields */
1436     ((mng_pltep)*ppChunk)->bEmpty      = (mng_bool)(iRawlen == 0);
1437     ((mng_pltep)*ppChunk)->iEntrycount = iRawlen / 3;
1438     pRawdata2                          = pRawdata;
1439 
1440     for (iX = 0; iX < ((mng_pltep)*ppChunk)->iEntrycount; iX++)
1441     {
1442       ((mng_pltep)*ppChunk)->aEntries[iX].iRed   = *pRawdata2;
1443       ((mng_pltep)*ppChunk)->aEntries[iX].iGreen = *(pRawdata2+1);
1444       ((mng_pltep)*ppChunk)->aEntries[iX].iBlue  = *(pRawdata2+2);
1445 
1446       pRawdata2 += 3;
1447     }
1448   }
1449 #endif /* MNG_STORE_CHUNKS */
1450 
1451 #ifdef MNG_SUPPORT_TRACE
1452   MNG_TRACE (pData, MNG_FN_READ_PLTE, MNG_LC_END);
1453 #endif
1454 
1455   return MNG_NOERROR;                  /* done */
1456 }
1457 #endif /* MNG_OPTIMIZE_CHUNKREADER */
1458 
1459 /* ************************************************************************** */
1460 
1461 #ifndef MNG_OPTIMIZE_CHUNKREADER
READ_CHUNK(mng_read_idat)1462 READ_CHUNK (mng_read_idat)
1463 {
1464 #ifdef MNG_SUPPORT_TRACE
1465   MNG_TRACE (pData, MNG_FN_READ_IDAT, MNG_LC_START);
1466 #endif
1467 
1468 #ifdef MNG_INCLUDE_JNG                 /* sequence checks */
1469   if ((!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
1470 #else
1471   if ((!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR))
1472 #endif
1473     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1474 
1475 #ifdef MNG_INCLUDE_JNG
1476   if ((pData->bHasJHDR) &&
1477       (pData->iJHDRalphacompression != MNG_COMPRESSION_DEFLATE))
1478     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1479 
1480   if (pData->bHasJSEP)
1481     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1482 #endif
1483                                        /* not allowed for deltatype NO_CHANGE */
1484 #ifndef MNG_NO_DELTA_PNG
1485   if ((pData->bHasDHDR) && ((pData->iDeltatype == MNG_DELTATYPE_NOCHANGE)))
1486     MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
1487 #endif
1488                                        /* can only be empty in BASI-block! */
1489   if ((iRawlen == 0) && (!pData->bHasBASI))
1490     MNG_ERROR (pData, MNG_INVALIDLENGTH);
1491                                        /* indexed-color requires PLTE */
1492   if ((pData->bHasIHDR) && (pData->iColortype == 3) && (!pData->bHasPLTE))
1493     MNG_ERROR (pData, MNG_PLTEMISSING);
1494 
1495   pData->bHasIDAT = MNG_TRUE;          /* got some IDAT now, don't we */
1496 
1497 #ifdef MNG_SUPPORT_DISPLAY
1498   if (iRawlen)
1499   {                                    /* display processing */
1500     mng_retcode iRetcode = mng_process_display_idat (pData, iRawlen, pRawdata);
1501 
1502     if (iRetcode)                      /* on error bail out */
1503       return iRetcode;
1504   }
1505 #endif /* MNG_SUPPORT_DISPLAY */
1506 
1507 #ifdef MNG_STORE_CHUNKS
1508   if (pData->bStorechunks)
1509   {                                    /* initialize storage */
1510     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
1511 
1512     if (iRetcode)                      /* on error bail out */
1513       return iRetcode;
1514                                        /* store the fields */
1515     ((mng_idatp)*ppChunk)->bEmpty    = (mng_bool)(iRawlen == 0);
1516     ((mng_idatp)*ppChunk)->iDatasize = iRawlen;
1517 
1518     if (iRawlen != 0)                  /* is there any data ? */
1519     {
1520       MNG_ALLOC (pData, ((mng_idatp)*ppChunk)->pData, iRawlen);
1521       MNG_COPY  (((mng_idatp)*ppChunk)->pData, pRawdata, iRawlen);
1522     }
1523   }
1524 #endif /* MNG_STORE_CHUNKS */
1525 
1526 #ifdef MNG_SUPPORT_TRACE
1527   MNG_TRACE (pData, MNG_FN_READ_IDAT, MNG_LC_END);
1528 #endif
1529 
1530   return MNG_NOERROR;                  /* done */
1531 }
1532 #endif
1533 
1534 /* ************************************************************************** */
1535 
1536 #ifndef MNG_OPTIMIZE_CHUNKREADER
READ_CHUNK(mng_read_iend)1537 READ_CHUNK (mng_read_iend)
1538 {
1539 #ifdef MNG_SUPPORT_TRACE
1540   MNG_TRACE (pData, MNG_FN_READ_IEND, MNG_LC_START);
1541 #endif
1542 
1543   if (iRawlen > 0)                     /* must not contain data! */
1544     MNG_ERROR (pData, MNG_INVALIDLENGTH);
1545 
1546 #ifdef MNG_INCLUDE_JNG                 /* sequence checks */
1547   if ((!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
1548 #else
1549   if ((!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR))
1550 #endif
1551     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1552                                        /* IHDR-block requires IDAT */
1553   if ((pData->bHasIHDR) && (!pData->bHasIDAT))
1554     MNG_ERROR (pData, MNG_IDATMISSING);
1555 
1556   pData->iImagelevel--;                /* one level up */
1557 
1558 #ifdef MNG_SUPPORT_DISPLAY
1559   {                                    /* create an animation object */
1560     mng_retcode iRetcode = mng_create_ani_image (pData);
1561     if (iRetcode)                      /* on error bail out */
1562       return iRetcode;
1563                                        /* display processing */
1564     iRetcode = mng_process_display_iend (pData);
1565     if (iRetcode)                      /* on error bail out */
1566       return iRetcode;
1567   }
1568 #endif /* MNG_SUPPORT_DISPLAY */
1569 
1570 #ifdef MNG_SUPPORT_DISPLAY
1571   if (!pData->bTimerset)               /* reset only if not broken !!! */
1572   {
1573 #endif
1574                                        /* IEND signals the end for most ... */
1575     pData->bHasIHDR         = MNG_FALSE;
1576     pData->bHasBASI         = MNG_FALSE;
1577     pData->bHasDHDR         = MNG_FALSE;
1578 #ifdef MNG_INCLUDE_JNG
1579     pData->bHasJHDR         = MNG_FALSE;
1580     pData->bHasJSEP         = MNG_FALSE;
1581     pData->bHasJDAA         = MNG_FALSE;
1582     pData->bHasJDAT         = MNG_FALSE;
1583 #endif
1584     pData->bHasPLTE         = MNG_FALSE;
1585     pData->bHasTRNS         = MNG_FALSE;
1586     pData->bHasGAMA         = MNG_FALSE;
1587     pData->bHasCHRM         = MNG_FALSE;
1588     pData->bHasSRGB         = MNG_FALSE;
1589     pData->bHasICCP         = MNG_FALSE;
1590     pData->bHasBKGD         = MNG_FALSE;
1591     pData->bHasIDAT         = MNG_FALSE;
1592 #ifdef MNG_SUPPORT_DISPLAY
1593   }
1594 #endif
1595 
1596 #ifdef MNG_STORE_CHUNKS
1597   if (pData->bStorechunks)
1598   {                                    /* initialize storage */
1599     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
1600 
1601     if (iRetcode)                      /* on error bail out */
1602       return iRetcode;
1603   }
1604 #endif /* MNG_STORE_CHUNKS */
1605 
1606 #ifdef MNG_SUPPORT_TRACE
1607   MNG_TRACE (pData, MNG_FN_READ_IEND, MNG_LC_END);
1608 #endif
1609 
1610   return MNG_NOERROR;                  /* done */
1611 }
1612 #endif
1613 
1614 /* ************************************************************************** */
1615 
1616 #ifndef MNG_OPTIMIZE_CHUNKREADER
READ_CHUNK(mng_read_trns)1617 READ_CHUNK (mng_read_trns)
1618 {
1619 #ifdef MNG_SUPPORT_TRACE
1620   MNG_TRACE (pData, MNG_FN_READ_TRNS, MNG_LC_START);
1621 #endif
1622                                        /* sequence checks */
1623   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
1624       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
1625     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1626 
1627 #ifdef MNG_INCLUDE_JNG
1628   if ((pData->bHasIDAT) || (pData->bHasJHDR))
1629 #else
1630   if (pData->bHasIDAT)
1631 #endif
1632     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1633                                        /* multiple tRNS only inside BASI */
1634   if ((pData->bHasTRNS) && (!pData->bHasBASI))
1635     MNG_ERROR (pData, MNG_MULTIPLEERROR);
1636 
1637   if (iRawlen > 256)                   /* it just can't be bigger than that! */
1638     MNG_ERROR (pData, MNG_INVALIDLENGTH);
1639 
1640   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
1641   {                                    /* not allowed with full alpha-channel */
1642     if ((pData->iColortype == 4) || (pData->iColortype == 6))
1643       MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
1644 
1645     if (iRawlen != 0)                  /* filled ? */
1646     {                                  /* length checks */
1647       if ((pData->iColortype == 0) && (iRawlen != 2))
1648         MNG_ERROR (pData, MNG_INVALIDLENGTH);
1649 
1650       if ((pData->iColortype == 2) && (iRawlen != 6))
1651         MNG_ERROR (pData, MNG_INVALIDLENGTH);
1652 
1653 #ifdef MNG_SUPPORT_DISPLAY
1654       if (pData->iColortype == 3)
1655       {
1656         mng_imagep     pImage = (mng_imagep)pData->pCurrentobj;
1657         mng_imagedatap pBuf;
1658 
1659         if (!pImage)                   /* no object then check obj 0 */
1660           pImage = (mng_imagep)pData->pObjzero;
1661 
1662         pBuf = pImage->pImgbuf;        /* address object buffer */
1663 
1664         if (iRawlen > pBuf->iPLTEcount)
1665           MNG_ERROR (pData, MNG_INVALIDLENGTH);
1666       }
1667 #endif
1668     }
1669     else                               /* if empty there must be global stuff! */
1670     {
1671       if (!pData->bHasglobalTRNS)
1672         MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
1673     }
1674   }
1675 
1676   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
1677     pData->bHasTRNS = MNG_TRUE;        /* indicate tRNS available */
1678   else
1679     pData->bHasglobalTRNS = MNG_TRUE;
1680 
1681 #ifdef MNG_SUPPORT_DISPLAY
1682   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
1683   {
1684     mng_imagep     pImage;
1685     mng_imagedatap pBuf;
1686     mng_uint8p     pRawdata2;
1687     mng_uint32     iRawlen2;
1688 
1689 #ifndef MNG_NO_DELTA_PNG
1690     if (pData->bHasDHDR)               /* processing delta-image ? */
1691     {                                  /* store in object 0 !!! */
1692       pImage = (mng_imagep)pData->pObjzero;
1693       pBuf   = pImage->pImgbuf;        /* address object buffer */
1694 
1695       switch (pData->iColortype)       /* store fields for future reference */
1696       {
1697         case 0: {                      /* gray */
1698 #if defined(MNG_NO_1_2_4BIT_SUPPORT)
1699                   mng_uint8 multiplier[]={0,255,85,0,17,0,0,0,1,
1700                                           0,0,0,0,0,0,0,1};
1701 #endif
1702                   pBuf->iTRNSgray  = mng_get_uint16 (pRawdata);
1703                   pBuf->iTRNSred   = 0;
1704                   pBuf->iTRNSgreen = 0;
1705                   pBuf->iTRNSblue  = 0;
1706                   pBuf->iTRNScount = 0;
1707 #if defined(MNG_NO_1_2_4BIT_SUPPORT)
1708                   pBuf->iTRNSgray *= multiplier[pData->iPNGdepth];
1709 #endif
1710 #if defined(MNG_NO_16BIT_SUPPORT)
1711                   if (pData->iPNGmult == 2)
1712                      pBuf->iTRNSgray >>= 8;
1713 #endif
1714                   break;
1715                 }
1716         case 2: {                      /* rgb */
1717                   pBuf->iTRNSgray  = 0;
1718                   pBuf->iTRNSred   = mng_get_uint16 (pRawdata);
1719                   pBuf->iTRNSgreen = mng_get_uint16 (pRawdata+2);
1720                   pBuf->iTRNSblue  = mng_get_uint16 (pRawdata+4);
1721                   pBuf->iTRNScount = 0;
1722 #if defined(MNG_NO_16BIT_SUPPORT)
1723                   if (pData->iPNGmult == 2)
1724                   {
1725                      pBuf->iTRNSred   >>= 8;
1726                      pBuf->iTRNSgreen >>= 8;
1727                      pBuf->iTRNSblue  >>= 8;
1728                   }
1729 #endif
1730                   break;
1731                 }
1732         case 3: {                      /* indexed */
1733                   pBuf->iTRNSgray  = 0;
1734                   pBuf->iTRNSred   = 0;
1735                   pBuf->iTRNSgreen = 0;
1736                   pBuf->iTRNSblue  = 0;
1737                   pBuf->iTRNScount = iRawlen;
1738                   MNG_COPY (pBuf->aTRNSentries, pRawdata, iRawlen);
1739                   break;
1740                 }
1741       }
1742 
1743       pBuf->bHasTRNS = MNG_TRUE;       /* tell it it's got a tRNS now */
1744     }
1745     else
1746 #endif
1747     {                                  /* address current object */
1748       pImage = (mng_imagep)pData->pCurrentobj;
1749 
1750       if (!pImage)                     /* no object then dump it in obj 0 */
1751         pImage = (mng_imagep)pData->pObjzero;
1752 
1753       pBuf = pImage->pImgbuf;          /* address object buffer */
1754       pBuf->bHasTRNS = MNG_TRUE;       /* and tell it it's got a tRNS now */
1755 
1756       if (iRawlen == 0)                /* if empty, inherit from global */
1757       {
1758         iRawlen2  = pData->iGlobalTRNSrawlen;
1759         pRawdata2 = (mng_ptr)(pData->aGlobalTRNSrawdata);
1760                                          /* global length oke ? */
1761         if ((pData->iColortype == 0) && (iRawlen2 != 2))
1762           MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
1763 
1764         if ((pData->iColortype == 2) && (iRawlen2 != 6))
1765           MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
1766 
1767         if ((pData->iColortype == 3) && ((iRawlen2 == 0) || (iRawlen2 > pBuf->iPLTEcount)))
1768           MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
1769       }
1770       else
1771       {
1772         iRawlen2  = iRawlen;
1773         pRawdata2 = pRawdata;
1774       }
1775 
1776       switch (pData->iColortype)        /* store fields for future reference */
1777       {
1778         case 0: {                      /* gray */
1779                   pBuf->iTRNSgray  = mng_get_uint16 (pRawdata2);
1780                   pBuf->iTRNSred   = 0;
1781                   pBuf->iTRNSgreen = 0;
1782                   pBuf->iTRNSblue  = 0;
1783                   pBuf->iTRNScount = 0;
1784 #if defined(MNG_NO_16BIT_SUPPORT)
1785                   if (pData->iPNGmult == 2)
1786                      pBuf->iTRNSgray >>= 8;
1787 #endif
1788                   break;
1789                 }
1790         case 2: {                      /* rgb */
1791                   pBuf->iTRNSgray  = 0;
1792                   pBuf->iTRNSred   = mng_get_uint16 (pRawdata2);
1793                   pBuf->iTRNSgreen = mng_get_uint16 (pRawdata2+2);
1794                   pBuf->iTRNSblue  = mng_get_uint16 (pRawdata2+4);
1795                   pBuf->iTRNScount = 0;
1796 #if defined(MNG_NO_16BIT_SUPPORT)
1797                   if (pData->iPNGmult == 2)
1798                   {
1799                      pBuf->iTRNSred   >>= 8;
1800                      pBuf->iTRNSgreen >>= 8;
1801                      pBuf->iTRNSblue  >>= 8;
1802                   }
1803 #endif
1804                   break;
1805                 }
1806         case 3: {                      /* indexed */
1807                   pBuf->iTRNSgray  = 0;
1808                   pBuf->iTRNSred   = 0;
1809                   pBuf->iTRNSgreen = 0;
1810                   pBuf->iTRNSblue  = 0;
1811                   pBuf->iTRNScount = iRawlen2;
1812                   MNG_COPY (pBuf->aTRNSentries, pRawdata2, iRawlen2);
1813                   break;
1814                 }
1815       }
1816     }
1817   }
1818   else                                 /* store as global */
1819   {
1820     pData->iGlobalTRNSrawlen = iRawlen;
1821     MNG_COPY (pData->aGlobalTRNSrawdata, pRawdata, iRawlen);
1822 
1823     {                                  /* create an animation object */
1824       mng_retcode iRetcode = mng_create_ani_trns (pData, pData->iGlobalTRNSrawlen,
1825                                                   pData->aGlobalTRNSrawdata);
1826 
1827       if (iRetcode)                    /* on error bail out */
1828         return iRetcode;
1829     }
1830   }
1831 #endif /* MNG_SUPPORT_DISPLAY */
1832 
1833 #ifdef MNG_STORE_CHUNKS
1834   if (pData->bStorechunks)
1835   {                                    /* initialize storage */
1836     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
1837 
1838     if (iRetcode)                      /* on error bail out */
1839       return iRetcode;
1840 
1841     if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
1842     {                                  /* not global! */
1843       ((mng_trnsp)*ppChunk)->bGlobal  = MNG_FALSE;
1844       ((mng_trnsp)*ppChunk)->iType    = pData->iColortype;
1845 
1846       if (iRawlen == 0)                /* if empty, indicate so */
1847         ((mng_trnsp)*ppChunk)->bEmpty = MNG_TRUE;
1848       else
1849       {
1850         ((mng_trnsp)*ppChunk)->bEmpty = MNG_FALSE;
1851 
1852         switch (pData->iColortype)     /* store fields */
1853         {
1854           case 0: {                    /* gray */
1855                     ((mng_trnsp)*ppChunk)->iGray  = mng_get_uint16 (pRawdata);
1856                     break;
1857                   }
1858           case 2: {                    /* rgb */
1859                     ((mng_trnsp)*ppChunk)->iRed   = mng_get_uint16 (pRawdata);
1860                     ((mng_trnsp)*ppChunk)->iGreen = mng_get_uint16 (pRawdata+2);
1861                     ((mng_trnsp)*ppChunk)->iBlue  = mng_get_uint16 (pRawdata+4);
1862                     break;
1863                   }
1864           case 3: {                    /* indexed */
1865                     ((mng_trnsp)*ppChunk)->iCount = iRawlen;
1866                     MNG_COPY (((mng_trnsp)*ppChunk)->aEntries, pRawdata, iRawlen);
1867                     break;
1868                   }
1869         }
1870       }
1871     }
1872     else                               /* it's global! */
1873     {
1874       ((mng_trnsp)*ppChunk)->bEmpty  = (mng_bool)(iRawlen == 0);
1875       ((mng_trnsp)*ppChunk)->bGlobal = MNG_TRUE;
1876       ((mng_trnsp)*ppChunk)->iType   = 0;
1877       ((mng_trnsp)*ppChunk)->iRawlen = iRawlen;
1878 
1879       MNG_COPY (((mng_trnsp)*ppChunk)->aRawdata, pRawdata, iRawlen);
1880     }
1881   }
1882 #endif /* MNG_STORE_CHUNKS */
1883 
1884 #ifdef MNG_SUPPORT_TRACE
1885   MNG_TRACE (pData, MNG_FN_READ_TRNS, MNG_LC_END);
1886 #endif
1887 
1888   return MNG_NOERROR;                  /* done */
1889 }
1890 #endif
1891 
1892 /* ************************************************************************** */
1893 
1894 #ifndef MNG_OPTIMIZE_CHUNKREADER
READ_CHUNK(mng_read_gama)1895 READ_CHUNK (mng_read_gama)
1896 {
1897 #ifdef MNG_SUPPORT_TRACE
1898   MNG_TRACE (pData, MNG_FN_READ_GAMA, MNG_LC_START);
1899 #endif
1900                                        /* sequence checks */
1901 #ifdef MNG_INCLUDE_JNG
1902   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
1903       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
1904 #else
1905   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
1906       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
1907 #endif
1908     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1909 
1910 #ifdef MNG_INCLUDE_JNG
1911   if ((pData->bHasIDAT) || (pData->bHasPLTE) || (pData->bHasJDAT) || (pData->bHasJDAA))
1912 #else
1913   if ((pData->bHasIDAT) || (pData->bHasPLTE))
1914 #endif
1915     MNG_ERROR (pData, MNG_SEQUENCEERROR);
1916 
1917 #ifdef MNG_INCLUDE_JNG
1918   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
1919 #else
1920   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
1921 #endif
1922   {                                    /* length must be exactly 4 */
1923     if (iRawlen != 4)
1924       MNG_ERROR (pData, MNG_INVALIDLENGTH);
1925   }
1926   else
1927   {                                    /* length must be empty or exactly 4 */
1928     if ((iRawlen != 0) && (iRawlen != 4))
1929       MNG_ERROR (pData, MNG_INVALIDLENGTH);
1930   }
1931 
1932 #ifdef MNG_INCLUDE_JNG
1933   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
1934 #else
1935   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
1936 #endif
1937     pData->bHasGAMA = MNG_TRUE;        /* indicate we've got it */
1938   else
1939     pData->bHasglobalGAMA = (mng_bool)(iRawlen != 0);
1940 
1941 #ifdef MNG_SUPPORT_DISPLAY
1942 #ifdef MNG_INCLUDE_JNG
1943   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
1944 #else
1945   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
1946 #endif
1947   {
1948     mng_imagep pImage;
1949 
1950 #ifndef MNG_NO_DELTA_PNG
1951     if (pData->bHasDHDR)               /* update delta image ? */
1952     {                                  /* store in object 0 ! */
1953       pImage = (mng_imagep)pData->pObjzero;
1954                                        /* store for color-processing routines */
1955       pImage->pImgbuf->iGamma   = mng_get_uint32 (pRawdata);
1956       pImage->pImgbuf->bHasGAMA = MNG_TRUE;
1957     }
1958     else
1959 #endif
1960     {
1961       pImage = (mng_imagep)pData->pCurrentobj;
1962 
1963       if (!pImage)                     /* no object then dump it in obj 0 */
1964         pImage = (mng_imagep)pData->pObjzero;
1965                                        /* store for color-processing routines */
1966       pImage->pImgbuf->iGamma   = mng_get_uint32 (pRawdata);
1967       pImage->pImgbuf->bHasGAMA = MNG_TRUE;
1968     }
1969   }
1970   else
1971   {                                    /* store as global */
1972     if (iRawlen != 0)
1973       pData->iGlobalGamma = mng_get_uint32 (pRawdata);
1974 
1975     {                                  /* create an animation object */
1976       mng_retcode iRetcode = mng_create_ani_gama (pData, (mng_bool)(iRawlen == 0),
1977                                                   pData->iGlobalGamma);
1978 
1979       if (iRetcode)                    /* on error bail out */
1980         return iRetcode;
1981     }
1982   }
1983 #endif /* MNG_SUPPORT_DISPLAY */
1984 
1985 #ifdef MNG_STORE_CHUNKS
1986   if (pData->bStorechunks)
1987   {                                    /* initialize storage */
1988     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
1989 
1990     if (iRetcode)                      /* on error bail out */
1991       return iRetcode;
1992                                        /* store the fields */
1993     ((mng_gamap)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
1994 
1995     if (iRawlen)
1996       ((mng_gamap)*ppChunk)->iGamma = mng_get_uint32 (pRawdata);
1997 
1998   }
1999 #endif /* MNG_STORE_CHUNKS */
2000 
2001 #ifdef MNG_SUPPORT_TRACE
2002   MNG_TRACE (pData, MNG_FN_READ_GAMA, MNG_LC_END);
2003 #endif
2004 
2005   return MNG_NOERROR;                  /* done */
2006 }
2007 #endif
2008 
2009 /* ************************************************************************** */
2010 
2011 #ifndef MNG_OPTIMIZE_CHUNKREADER
2012 #ifndef MNG_SKIPCHUNK_cHRM
READ_CHUNK(mng_read_chrm)2013 READ_CHUNK (mng_read_chrm)
2014 {
2015 #ifdef MNG_SUPPORT_TRACE
2016   MNG_TRACE (pData, MNG_FN_READ_CHRM, MNG_LC_START);
2017 #endif
2018                                        /* sequence checks */
2019 #ifdef MNG_INCLUDE_JNG
2020   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2021       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
2022 #else
2023   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2024       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
2025 #endif
2026     MNG_ERROR (pData, MNG_SEQUENCEERROR);
2027 
2028 #ifdef MNG_INCLUDE_JNG
2029   if ((pData->bHasIDAT) || (pData->bHasPLTE) || (pData->bHasJDAT) || (pData->bHasJDAA))
2030 #else
2031   if ((pData->bHasIDAT) || (pData->bHasPLTE))
2032 #endif
2033     MNG_ERROR (pData, MNG_SEQUENCEERROR);
2034 
2035 #ifdef MNG_INCLUDE_JNG
2036   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
2037 #else
2038   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
2039 #endif
2040   {                                    /* length must be exactly 32 */
2041     if (iRawlen != 32)
2042       MNG_ERROR (pData, MNG_INVALIDLENGTH);
2043   }
2044   else
2045   {                                    /* length must be empty or exactly 32 */
2046     if ((iRawlen != 0) && (iRawlen != 32))
2047       MNG_ERROR (pData, MNG_INVALIDLENGTH);
2048   }
2049 
2050 #ifdef MNG_INCLUDE_JNG
2051   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
2052 #else
2053   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
2054 #endif
2055     pData->bHasCHRM = MNG_TRUE;        /* indicate we've got it */
2056   else
2057     pData->bHasglobalCHRM = (mng_bool)(iRawlen != 0);
2058 
2059 #ifdef MNG_SUPPORT_DISPLAY
2060   {
2061     mng_uint32 iWhitepointx,   iWhitepointy;
2062     mng_uint32 iPrimaryredx,   iPrimaryredy;
2063     mng_uint32 iPrimarygreenx, iPrimarygreeny;
2064     mng_uint32 iPrimarybluex,  iPrimarybluey;
2065 
2066     iWhitepointx   = mng_get_uint32 (pRawdata);
2067     iWhitepointy   = mng_get_uint32 (pRawdata+4);
2068     iPrimaryredx   = mng_get_uint32 (pRawdata+8);
2069     iPrimaryredy   = mng_get_uint32 (pRawdata+12);
2070     iPrimarygreenx = mng_get_uint32 (pRawdata+16);
2071     iPrimarygreeny = mng_get_uint32 (pRawdata+20);
2072     iPrimarybluex  = mng_get_uint32 (pRawdata+24);
2073     iPrimarybluey  = mng_get_uint32 (pRawdata+28);
2074 
2075 #ifdef MNG_INCLUDE_JNG
2076     if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
2077 #else
2078     if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
2079 #endif
2080     {
2081       mng_imagep     pImage;
2082       mng_imagedatap pBuf;
2083 
2084 #ifndef MNG_NO_DELTA_PNG
2085       if (pData->bHasDHDR)             /* update delta image ? */
2086       {                                /* store it in object 0 ! */
2087         pImage = (mng_imagep)pData->pObjzero;
2088 
2089         pBuf = pImage->pImgbuf;        /* address object buffer */
2090         pBuf->bHasCHRM = MNG_TRUE;     /* and tell it it's got a CHRM now */
2091                                        /* store for color-processing routines */
2092         pBuf->iWhitepointx   = iWhitepointx;
2093         pBuf->iWhitepointy   = iWhitepointy;
2094         pBuf->iPrimaryredx   = iPrimaryredx;
2095         pBuf->iPrimaryredy   = iPrimaryredy;
2096         pBuf->iPrimarygreenx = iPrimarygreenx;
2097         pBuf->iPrimarygreeny = iPrimarygreeny;
2098         pBuf->iPrimarybluex  = iPrimarybluex;
2099         pBuf->iPrimarybluey  = iPrimarybluey;
2100       }
2101       else
2102 #endif
2103       {
2104         pImage = (mng_imagep)pData->pCurrentobj;
2105 
2106         if (!pImage)                   /* no object then dump it in obj 0 */
2107           pImage = (mng_imagep)pData->pObjzero;
2108 
2109         pBuf = pImage->pImgbuf;        /* address object buffer */
2110         pBuf->bHasCHRM = MNG_TRUE;     /* and tell it it's got a CHRM now */
2111                                        /* store for color-processing routines */
2112         pBuf->iWhitepointx   = iWhitepointx;
2113         pBuf->iWhitepointy   = iWhitepointy;
2114         pBuf->iPrimaryredx   = iPrimaryredx;
2115         pBuf->iPrimaryredy   = iPrimaryredy;
2116         pBuf->iPrimarygreenx = iPrimarygreenx;
2117         pBuf->iPrimarygreeny = iPrimarygreeny;
2118         pBuf->iPrimarybluex  = iPrimarybluex;
2119         pBuf->iPrimarybluey  = iPrimarybluey;
2120       }
2121     }
2122     else
2123     {                                  /* store as global */
2124       if (iRawlen != 0)
2125       {
2126         pData->iGlobalWhitepointx   = iWhitepointx;
2127         pData->iGlobalWhitepointy   = iWhitepointy;
2128         pData->iGlobalPrimaryredx   = iPrimaryredx;
2129         pData->iGlobalPrimaryredy   = iPrimaryredy;
2130         pData->iGlobalPrimarygreenx = iPrimarygreenx;
2131         pData->iGlobalPrimarygreeny = iPrimarygreeny;
2132         pData->iGlobalPrimarybluex  = iPrimarybluex;
2133         pData->iGlobalPrimarybluey  = iPrimarybluey;
2134       }
2135 
2136       {                                /* create an animation object */
2137         mng_retcode iRetcode = mng_create_ani_chrm (pData, (mng_bool)(iRawlen == 0),
2138                                                     iWhitepointx,   iWhitepointy,
2139                                                     iPrimaryredx,   iPrimaryredy,
2140                                                     iPrimarygreenx, iPrimarygreeny,
2141                                                     iPrimarybluex,  iPrimarybluey);
2142 
2143         if (iRetcode)                  /* on error bail out */
2144           return iRetcode;
2145       }
2146     }
2147   }
2148 #endif /* MNG_SUPPORT_DISPLAY */
2149 
2150 #ifdef MNG_STORE_CHUNKS
2151   if (pData->bStorechunks)
2152   {                                    /* initialize storage */
2153     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
2154 
2155     if (iRetcode)                      /* on error bail out */
2156       return iRetcode;
2157                                        /* store the fields */
2158     ((mng_chrmp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
2159 
2160     if (iRawlen)
2161     {
2162       ((mng_chrmp)*ppChunk)->iWhitepointx = mng_get_uint32 (pRawdata);
2163       ((mng_chrmp)*ppChunk)->iWhitepointy = mng_get_uint32 (pRawdata+4);
2164       ((mng_chrmp)*ppChunk)->iRedx        = mng_get_uint32 (pRawdata+8);
2165       ((mng_chrmp)*ppChunk)->iRedy        = mng_get_uint32 (pRawdata+12);
2166       ((mng_chrmp)*ppChunk)->iGreenx      = mng_get_uint32 (pRawdata+16);
2167       ((mng_chrmp)*ppChunk)->iGreeny      = mng_get_uint32 (pRawdata+20);
2168       ((mng_chrmp)*ppChunk)->iBluex       = mng_get_uint32 (pRawdata+24);
2169       ((mng_chrmp)*ppChunk)->iBluey       = mng_get_uint32 (pRawdata+28);
2170     }
2171   }
2172 #endif /* MNG_STORE_CHUNKS */
2173 
2174 #ifdef MNG_SUPPORT_TRACE
2175   MNG_TRACE (pData, MNG_FN_READ_CHRM, MNG_LC_END);
2176 #endif
2177 
2178   return MNG_NOERROR;                  /* done */
2179 }
2180 #endif
2181 #endif
2182 
2183 /* ************************************************************************** */
2184 
2185 #ifndef MNG_OPTIMIZE_CHUNKREADER
READ_CHUNK(mng_read_srgb)2186 READ_CHUNK (mng_read_srgb)
2187 {
2188 #ifdef MNG_SUPPORT_TRACE
2189   MNG_TRACE (pData, MNG_FN_READ_SRGB, MNG_LC_START);
2190 #endif
2191                                        /* sequence checks */
2192 #ifdef MNG_INCLUDE_JNG
2193   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2194       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
2195 #else
2196   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2197       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
2198 #endif
2199     MNG_ERROR (pData, MNG_SEQUENCEERROR);
2200 
2201 #ifdef MNG_INCLUDE_JNG
2202   if ((pData->bHasIDAT) || (pData->bHasPLTE) || (pData->bHasJDAT) || (pData->bHasJDAA))
2203 #else
2204   if ((pData->bHasIDAT) || (pData->bHasPLTE))
2205 #endif
2206     MNG_ERROR (pData, MNG_SEQUENCEERROR);
2207 
2208 #ifdef MNG_INCLUDE_JNG
2209   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
2210 #else
2211   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
2212 #endif
2213   {                                    /* length must be exactly 1 */
2214     if (iRawlen != 1)
2215       MNG_ERROR (pData, MNG_INVALIDLENGTH);
2216   }
2217   else
2218   {                                    /* length must be empty or exactly 1 */
2219     if ((iRawlen != 0) && (iRawlen != 1))
2220       MNG_ERROR (pData, MNG_INVALIDLENGTH);
2221   }
2222 
2223 #ifdef MNG_INCLUDE_JNG
2224   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
2225 #else
2226   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
2227 #endif
2228     pData->bHasSRGB = MNG_TRUE;        /* indicate we've got it */
2229   else
2230     pData->bHasglobalSRGB = (mng_bool)(iRawlen != 0);
2231 
2232 #ifdef MNG_SUPPORT_DISPLAY
2233 #ifdef MNG_INCLUDE_JNG
2234   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
2235 #else
2236   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
2237 #endif
2238   {
2239     mng_imagep pImage;
2240 
2241 #ifndef MNG_NO_DELTA_PNG
2242     if (pData->bHasDHDR)               /* update delta image ? */
2243     {                                  /* store in object 0 ! */
2244       pImage = (mng_imagep)pData->pObjzero;
2245                                        /* store for color-processing routines */
2246       pImage->pImgbuf->iRenderingintent = *pRawdata;
2247       pImage->pImgbuf->bHasSRGB         = MNG_TRUE;
2248     }
2249     else
2250 #endif
2251     {
2252       pImage = (mng_imagep)pData->pCurrentobj;
2253 
2254       if (!pImage)                     /* no object then dump it in obj 0 */
2255         pImage = (mng_imagep)pData->pObjzero;
2256                                        /* store for color-processing routines */
2257       pImage->pImgbuf->iRenderingintent = *pRawdata;
2258       pImage->pImgbuf->bHasSRGB         = MNG_TRUE;
2259     }
2260   }
2261   else
2262   {                                    /* store as global */
2263     if (iRawlen != 0)
2264       pData->iGlobalRendintent = *pRawdata;
2265 
2266     {                                  /* create an animation object */
2267       mng_retcode iRetcode = mng_create_ani_srgb (pData, (mng_bool)(iRawlen == 0),
2268                                                   pData->iGlobalRendintent);
2269 
2270       if (iRetcode)                    /* on error bail out */
2271         return iRetcode;
2272     }
2273   }
2274 #endif /* MNG_SUPPORT_DISPLAY */
2275 
2276 #ifdef MNG_STORE_CHUNKS
2277   if (pData->bStorechunks)
2278   {                                    /* initialize storage */
2279     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
2280 
2281     if (iRetcode)                      /* on error bail out */
2282       return iRetcode;
2283                                        /* store the fields */
2284     ((mng_srgbp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
2285 
2286     if (iRawlen)
2287       ((mng_srgbp)*ppChunk)->iRenderingintent = *pRawdata;
2288 
2289   }
2290 #endif /* MNG_STORE_CHUNKS */
2291 
2292 #ifdef MNG_SUPPORT_TRACE
2293   MNG_TRACE (pData, MNG_FN_READ_SRGB, MNG_LC_END);
2294 #endif
2295 
2296   return MNG_NOERROR;                  /* done */
2297 }
2298 #endif
2299 
2300 /* ************************************************************************** */
2301 
2302 #ifndef MNG_OPTIMIZE_CHUNKREADER
2303 #ifndef MNG_SKIPCHUNK_iCCP
READ_CHUNK(mng_read_iccp)2304 READ_CHUNK (mng_read_iccp)
2305 {
2306   mng_retcode iRetcode;
2307   mng_uint8p  pTemp;
2308   mng_uint32  iCompressedsize;
2309   mng_uint32  iProfilesize;
2310   mng_uint32  iBufsize = 0;
2311   mng_uint8p  pBuf = 0;
2312 
2313 #ifdef MNG_SUPPORT_TRACE
2314   MNG_TRACE (pData, MNG_FN_READ_ICCP, MNG_LC_START);
2315 #endif
2316                                        /* sequence checks */
2317 #ifdef MNG_INCLUDE_JNG
2318   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2319       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
2320 #else
2321   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2322       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
2323 #endif
2324     MNG_ERROR (pData, MNG_SEQUENCEERROR);
2325 
2326 #ifdef MNG_INCLUDE_JNG
2327   if ((pData->bHasIDAT) || (pData->bHasPLTE) || (pData->bHasJDAT) || (pData->bHasJDAA))
2328 #else
2329   if ((pData->bHasIDAT) || (pData->bHasPLTE))
2330 #endif
2331     MNG_ERROR (pData, MNG_SEQUENCEERROR);
2332 
2333 #ifdef MNG_INCLUDE_JNG
2334   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
2335 #else
2336   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
2337 #endif
2338   {                                    /* length must be at least 2 */
2339     if (iRawlen < 2)
2340       MNG_ERROR (pData, MNG_INVALIDLENGTH);
2341   }
2342   else
2343   {                                    /* length must be empty or at least 2 */
2344     if ((iRawlen != 0) && (iRawlen < 2))
2345       MNG_ERROR (pData, MNG_INVALIDLENGTH);
2346   }
2347 
2348   pTemp = find_null (pRawdata);        /* find null-separator */
2349                                        /* not found inside input-data ? */
2350   if ((pTemp - pRawdata) > (mng_int32)iRawlen)
2351     MNG_ERROR (pData, MNG_NULLNOTFOUND);
2352                                        /* determine size of compressed profile */
2353   iCompressedsize = (mng_uint32)(iRawlen - (pTemp - pRawdata) - 2);
2354                                        /* decompress the profile */
2355   iRetcode = mng_inflate_buffer (pData, pTemp+2, iCompressedsize,
2356                                  &pBuf, &iBufsize, &iProfilesize);
2357 
2358 #ifdef MNG_CHECK_BAD_ICCP              /* Check for bad iCCP chunk */
2359   if ((iRetcode) && (!strncmp ((char *)pRawdata, "Photoshop ICC profile", 21)))
2360   {
2361     if (iRawlen == 2615)               /* is it the sRGB profile ? */
2362     {
2363       mng_chunk_header chunk_srgb =
2364 #ifdef MNG_OPTIMIZE_CHUNKINITFREE
2365         {MNG_UINT_sRGB, mng_init_general, mng_free_general, mng_read_srgb, mng_write_srgb, mng_assign_general, 0, 0, sizeof(mng_srgb)};
2366 #else
2367         {MNG_UINT_sRGB, mng_init_srgb, mng_free_srgb, mng_read_srgb, mng_write_srgb, mng_assign_srgb, 0, 0};
2368 #endif
2369                                        /* pretend it's an sRGB chunk then ! */
2370       iRetcode = mng_read_srgb (pData, &chunk_srgb, 1, (mng_ptr)"0", ppChunk);
2371 
2372       if (iRetcode)                    /* on error bail out */
2373       {                                /* don't forget to drop the temp buffer */
2374         MNG_FREEX (pData, pBuf, iBufsize);
2375         return iRetcode;
2376       }
2377     }
2378   }
2379   else
2380   {
2381 #endif /* MNG_CHECK_BAD_ICCP */
2382 
2383     if (iRetcode)                      /* on error bail out */
2384     {                                  /* don't forget to drop the temp buffer */
2385       MNG_FREEX (pData, pBuf, iBufsize);
2386       return iRetcode;
2387     }
2388 
2389 #ifdef MNG_INCLUDE_JNG
2390     if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
2391 #else
2392     if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
2393 #endif
2394       pData->bHasICCP = MNG_TRUE;      /* indicate we've got it */
2395     else
2396       pData->bHasglobalICCP = (mng_bool)(iRawlen != 0);
2397 
2398 #ifdef MNG_SUPPORT_DISPLAY
2399 #ifdef MNG_INCLUDE_JNG
2400     if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
2401 #else
2402     if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
2403 #endif
2404     {
2405       mng_imagep pImage;
2406 
2407 #ifndef MNG_NO_DELTA_PNG
2408       if (pData->bHasDHDR)             /* update delta image ? */
2409       {                                /* store in object 0 ! */
2410         pImage = (mng_imagep)pData->pObjzero;
2411 
2412         if (pImage->pImgbuf->pProfile) /* profile existed ? */
2413           MNG_FREEX (pData, pImage->pImgbuf->pProfile, pImage->pImgbuf->iProfilesize);
2414                                        /* allocate a buffer & copy it */
2415         MNG_ALLOC (pData, pImage->pImgbuf->pProfile, iProfilesize);
2416         MNG_COPY  (pImage->pImgbuf->pProfile, pBuf, iProfilesize);
2417                                        /* store its length as well */
2418         pImage->pImgbuf->iProfilesize = iProfilesize;
2419         pImage->pImgbuf->bHasICCP     = MNG_TRUE;
2420       }
2421       else
2422 #endif
2423       {
2424         pImage = (mng_imagep)pData->pCurrentobj;
2425 
2426         if (!pImage)                   /* no object then dump it in obj 0 */
2427           pImage = (mng_imagep)pData->pObjzero;
2428 
2429         if (pImage->pImgbuf->pProfile) /* profile existed ? */
2430           MNG_FREEX (pData, pImage->pImgbuf->pProfile, pImage->pImgbuf->iProfilesize);
2431                                        /* allocate a buffer & copy it */
2432         MNG_ALLOC (pData, pImage->pImgbuf->pProfile, iProfilesize);
2433         MNG_COPY  (pImage->pImgbuf->pProfile, pBuf, iProfilesize);
2434                                        /* store its length as well */
2435         pImage->pImgbuf->iProfilesize = iProfilesize;
2436         pImage->pImgbuf->bHasICCP     = MNG_TRUE;
2437       }
2438     }
2439     else
2440     {                                  /* store as global */
2441       if (iRawlen == 0)                /* empty chunk ? */
2442       {
2443         if (pData->pGlobalProfile)     /* did we have a global profile ? */
2444           MNG_FREEX (pData, pData->pGlobalProfile, pData->iGlobalProfilesize);
2445 
2446         pData->iGlobalProfilesize = 0; /* reset to null */
2447         pData->pGlobalProfile     = MNG_NULL;
2448       }
2449       else
2450       {                                /* allocate a global buffer & copy it */
2451         MNG_ALLOC (pData, pData->pGlobalProfile, iProfilesize);
2452         MNG_COPY  (pData->pGlobalProfile, pBuf, iProfilesize);
2453                                        /* store its length as well */
2454         pData->iGlobalProfilesize = iProfilesize;
2455       }
2456 
2457                                        /* create an animation object */
2458       iRetcode = mng_create_ani_iccp (pData, (mng_bool)(iRawlen == 0),
2459                                       pData->iGlobalProfilesize,
2460                                       pData->pGlobalProfile);
2461 
2462       if (iRetcode)                    /* on error bail out */
2463         return iRetcode;
2464     }
2465 #endif /* MNG_SUPPORT_DISPLAY */
2466 
2467 #ifdef MNG_STORE_CHUNKS
2468     if (pData->bStorechunks)
2469     {                                  /* initialize storage */
2470       iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
2471 
2472       if (iRetcode)                    /* on error bail out */
2473       {                                /* don't forget to drop the temp buffer */
2474         MNG_FREEX (pData, pBuf, iBufsize);
2475         return iRetcode;
2476       }
2477                                        /* store the fields */
2478       ((mng_iccpp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
2479 
2480       if (iRawlen)                     /* not empty ? */
2481       {
2482         if (!pBuf)                     /* hasn't been unpuzzled it yet ? */
2483         {                              /* find null-separator */
2484           pTemp = find_null (pRawdata);
2485                                        /* not found inside input-data ? */
2486           if ((pTemp - pRawdata) > (mng_int32)iRawlen)
2487             MNG_ERROR (pData, MNG_NULLNOTFOUND);
2488                                        /* determine size of compressed profile */
2489           iCompressedsize = iRawlen - (pTemp - pRawdata) - 2;
2490                                        /* decompress the profile */
2491           iRetcode = mng_inflate_buffer (pData, pTemp+2, iCompressedsize,
2492                                          &pBuf, &iBufsize, &iProfilesize);
2493 
2494           if (iRetcode)                /* on error bail out */
2495           {                            /* don't forget to drop the temp buffer */
2496             MNG_FREEX (pData, pBuf, iBufsize);
2497             return iRetcode;
2498           }
2499         }
2500 
2501         ((mng_iccpp)*ppChunk)->iNamesize = (mng_uint32)(pTemp - pRawdata);
2502 
2503         if (((mng_iccpp)*ppChunk)->iNamesize)
2504         {
2505           MNG_ALLOC (pData, ((mng_iccpp)*ppChunk)->zName,
2506                             ((mng_iccpp)*ppChunk)->iNamesize + 1);
2507           MNG_COPY  (((mng_iccpp)*ppChunk)->zName, pRawdata,
2508                      ((mng_iccpp)*ppChunk)->iNamesize);
2509         }
2510 
2511         ((mng_iccpp)*ppChunk)->iCompression = *(pTemp+1);
2512         ((mng_iccpp)*ppChunk)->iProfilesize = iProfilesize;
2513 
2514         MNG_ALLOC (pData, ((mng_iccpp)*ppChunk)->pProfile, iProfilesize);
2515         MNG_COPY  (((mng_iccpp)*ppChunk)->pProfile, pBuf, iProfilesize);
2516       }
2517     }
2518 #endif /* MNG_STORE_CHUNKS */
2519 
2520     if (pBuf)                          /* free the temporary buffer */
2521       MNG_FREEX (pData, pBuf, iBufsize);
2522 
2523 #ifdef MNG_CHECK_BAD_ICCP
2524   }
2525 #endif
2526 
2527 #ifdef MNG_SUPPORT_TRACE
2528   MNG_TRACE (pData, MNG_FN_READ_ICCP, MNG_LC_END);
2529 #endif
2530 
2531   return MNG_NOERROR;                  /* done */
2532 }
2533 #endif
2534 #endif
2535 
2536 /* ************************************************************************** */
2537 
2538 #ifndef MNG_OPTIMIZE_CHUNKREADER
2539 #ifndef MNG_SKIPCHUNK_tEXt
READ_CHUNK(mng_read_text)2540 READ_CHUNK (mng_read_text)
2541 {
2542   mng_uint32 iKeywordlen, iTextlen;
2543   mng_pchar  zKeyword, zText;
2544   mng_uint8p pTemp;
2545 
2546 #ifdef MNG_SUPPORT_TRACE
2547   MNG_TRACE (pData, MNG_FN_READ_TEXT, MNG_LC_START);
2548 #endif
2549                                        /* sequence checks */
2550 #ifdef MNG_INCLUDE_JNG
2551   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2552       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
2553 #else
2554   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2555       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
2556 #endif
2557     MNG_ERROR (pData, MNG_SEQUENCEERROR);
2558 
2559   if (iRawlen < 2)                     /* length must be at least 2 */
2560     MNG_ERROR (pData, MNG_INVALIDLENGTH);
2561 
2562   pTemp = find_null (pRawdata);        /* find the null separator */
2563                                        /* not found inside input-data ? */
2564   if ((pTemp - pRawdata) > (mng_int32)iRawlen)
2565     MNG_ERROR (pData, MNG_NULLNOTFOUND);
2566 
2567   if (pTemp == pRawdata)               /* there must be at least 1 char for keyword */
2568     MNG_ERROR (pData, MNG_KEYWORDNULL);
2569 
2570   iKeywordlen = (mng_uint32)(pTemp - pRawdata);
2571   iTextlen    = iRawlen - iKeywordlen - 1;
2572 
2573   if (pData->fProcesstext)             /* inform the application ? */
2574   {
2575     mng_bool bOke;
2576 
2577     MNG_ALLOC (pData, zKeyword, iKeywordlen + 1);
2578     MNG_COPY  (zKeyword, pRawdata, iKeywordlen);
2579 
2580     MNG_ALLOCX (pData, zText, iTextlen + 1);
2581 
2582     if (!zText)                        /* on error bail out */
2583     {
2584       MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
2585       MNG_ERROR (pData, MNG_OUTOFMEMORY);
2586     }
2587 
2588     if (iTextlen)
2589       MNG_COPY (zText, pTemp+1, iTextlen);
2590 
2591     bOke = pData->fProcesstext ((mng_handle)pData, MNG_TYPE_TEXT, zKeyword, zText, 0, 0);
2592 
2593     MNG_FREEX (pData, zText, iTextlen + 1);
2594     MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
2595 
2596     if (!bOke)
2597       MNG_ERROR (pData, MNG_APPMISCERROR);
2598 
2599   }
2600 
2601 #ifdef MNG_STORE_CHUNKS
2602   if (pData->bStorechunks)
2603   {                                    /* initialize storage */
2604     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
2605 
2606     if (iRetcode)                      /* on error bail out */
2607       return iRetcode;
2608                                        /* store the fields */
2609     ((mng_textp)*ppChunk)->iKeywordsize = iKeywordlen;
2610     ((mng_textp)*ppChunk)->iTextsize    = iTextlen;
2611 
2612     if (iKeywordlen)
2613     {
2614       MNG_ALLOC (pData, ((mng_textp)*ppChunk)->zKeyword, iKeywordlen+1);
2615       MNG_COPY  (((mng_textp)*ppChunk)->zKeyword, pRawdata, iKeywordlen);
2616     }
2617 
2618     if (iTextlen)
2619     {
2620       MNG_ALLOC (pData, ((mng_textp)*ppChunk)->zText, iTextlen+1);
2621       MNG_COPY  (((mng_textp)*ppChunk)->zText, pTemp+1, iTextlen);
2622     }
2623   }
2624 #endif /* MNG_STORE_CHUNKS */
2625 
2626 #ifdef MNG_SUPPORT_TRACE
2627   MNG_TRACE (pData, MNG_FN_READ_TEXT, MNG_LC_END);
2628 #endif
2629 
2630   return MNG_NOERROR;                  /* done */
2631 }
2632 #endif
2633 #endif
2634 
2635 /* ************************************************************************** */
2636 
2637 #ifndef MNG_OPTIMIZE_CHUNKREADER
2638 #ifndef MNG_SKIPCHUNK_zTXt
READ_CHUNK(mng_read_ztxt)2639 READ_CHUNK (mng_read_ztxt)
2640 {
2641   mng_retcode iRetcode;
2642   mng_uint32  iKeywordlen, iTextlen;
2643   mng_pchar   zKeyword;
2644   mng_uint8p  pTemp;
2645   mng_uint32  iCompressedsize;
2646   mng_uint32  iBufsize;
2647   mng_uint8p  pBuf;
2648 
2649 #ifdef MNG_SUPPORT_TRACE
2650   MNG_TRACE (pData, MNG_FN_READ_ZTXT, MNG_LC_START);
2651 #endif
2652                                        /* sequence checks */
2653 #ifdef MNG_INCLUDE_JNG
2654   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2655       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
2656 #else
2657   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2658       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
2659 #endif
2660     MNG_ERROR (pData, MNG_SEQUENCEERROR);
2661 
2662   if (iRawlen < 3)                     /* length must be at least 3 */
2663     MNG_ERROR (pData, MNG_INVALIDLENGTH);
2664 
2665   pTemp = find_null (pRawdata);        /* find the null separator */
2666                                        /* not found inside input-data ? */
2667   if ((pTemp - pRawdata) > (mng_int32)iRawlen)
2668     MNG_ERROR (pData, MNG_NULLNOTFOUND);
2669 
2670   if (pTemp == pRawdata)               /* there must be at least 1 char for keyword */
2671     MNG_ERROR (pData, MNG_KEYWORDNULL);
2672 
2673   if (*(pTemp+1) != 0)                 /* only deflate compression-method allowed */
2674     MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
2675 
2676   iKeywordlen     = (mng_uint32)(pTemp - pRawdata);
2677   iCompressedsize = (mng_uint32)(iRawlen - iKeywordlen - 2);
2678 
2679   zKeyword        = 0;                 /* there's no keyword buffer yet */
2680   pBuf            = 0;                 /* or a temporary buffer ! */
2681 
2682   if (pData->fProcesstext)             /* inform the application ? */
2683   {                                    /* decompress the text */
2684     iRetcode = mng_inflate_buffer (pData, pTemp+2, iCompressedsize,
2685                                    &pBuf, &iBufsize, &iTextlen);
2686 
2687     if (iRetcode)                      /* on error bail out */
2688     {                                  /* don't forget to drop the temp buffers */
2689       MNG_FREEX (pData, pBuf, iBufsize);
2690       return iRetcode;
2691     }
2692 
2693     MNG_ALLOCX (pData, zKeyword, iKeywordlen+1);
2694 
2695     if (!zKeyword)                     /* on error bail out */
2696     {                                  /* don't forget to drop the temp buffers */
2697       MNG_FREEX (pData, pBuf, iBufsize);
2698       MNG_ERROR (pData, MNG_OUTOFMEMORY);
2699     }
2700 
2701     MNG_COPY (zKeyword, pRawdata, iKeywordlen);
2702 
2703     if (!pData->fProcesstext ((mng_handle)pData, MNG_TYPE_ZTXT, zKeyword, (mng_pchar)pBuf, 0, 0))
2704     {                                  /* don't forget to drop the temp buffers */
2705       MNG_FREEX (pData, pBuf, iBufsize);
2706       MNG_FREEX (pData, zKeyword, iKeywordlen+1);
2707       MNG_ERROR (pData, MNG_APPMISCERROR);
2708     }
2709   }
2710 
2711 #ifdef MNG_STORE_CHUNKS
2712   if (pData->bStorechunks)
2713   {                                    /* initialize storage */
2714     iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
2715 
2716     if (iRetcode)                      /* on error bail out */
2717     {                                  /* don't forget to drop the temp buffers */
2718       MNG_FREEX (pData, pBuf, iBufsize);
2719       MNG_FREEX (pData, zKeyword, iKeywordlen+1);
2720       return iRetcode;
2721     }
2722                                        /* store the fields */
2723     ((mng_ztxtp)*ppChunk)->iKeywordsize = iKeywordlen;
2724     ((mng_ztxtp)*ppChunk)->iCompression = *(pTemp+1);
2725 
2726     if ((!pBuf) && (iCompressedsize))  /* did we not get a text-buffer yet ? */
2727     {                                  /* decompress the text */
2728       iRetcode = mng_inflate_buffer (pData, pTemp+2, iCompressedsize,
2729                                      &pBuf, &iBufsize, &iTextlen);
2730 
2731       if (iRetcode)                    /* on error bail out */
2732       {                                /* don't forget to drop the temp buffers */
2733         MNG_FREEX (pData, pBuf, iBufsize);
2734         MNG_FREEX (pData, zKeyword, iKeywordlen+1);
2735         return iRetcode;
2736       }
2737     }
2738 
2739     MNG_ALLOCX (pData, ((mng_ztxtp)*ppChunk)->zKeyword, iKeywordlen + 1);
2740                                        /* on error bail out */
2741     if (!((mng_ztxtp)*ppChunk)->zKeyword)
2742     {                                  /* don't forget to drop the temp buffers */
2743       MNG_FREEX (pData, pBuf, iBufsize);
2744       MNG_FREEX (pData, zKeyword, iKeywordlen+1);
2745       MNG_ERROR (pData, MNG_OUTOFMEMORY);
2746     }
2747 
2748     MNG_COPY (((mng_ztxtp)*ppChunk)->zKeyword, pRawdata, iKeywordlen);
2749 
2750     ((mng_ztxtp)*ppChunk)->iTextsize = iTextlen;
2751 
2752     if (iCompressedsize)
2753     {
2754       MNG_ALLOCX (pData, ((mng_ztxtp)*ppChunk)->zText, iTextlen + 1);
2755                                        /* on error bail out */
2756       if (!((mng_ztxtp)*ppChunk)->zText)
2757       {                                /* don't forget to drop the temp buffers */
2758         MNG_FREEX (pData, pBuf, iBufsize);
2759         MNG_FREEX (pData, zKeyword, iKeywordlen+1);
2760         MNG_ERROR (pData, MNG_OUTOFMEMORY);
2761       }
2762 
2763       MNG_COPY (((mng_ztxtp)*ppChunk)->zText, pBuf, iTextlen);
2764     }
2765   }
2766 #endif /* MNG_STORE_CHUNKS */
2767 
2768   MNG_FREEX (pData, pBuf, iBufsize);   /* free the temporary buffers */
2769   MNG_FREEX (pData, zKeyword, iKeywordlen+1);
2770 
2771 #ifdef MNG_SUPPORT_TRACE
2772   MNG_TRACE (pData, MNG_FN_READ_ZTXT, MNG_LC_END);
2773 #endif
2774 
2775   return MNG_NOERROR;                  /* done */
2776 }
2777 #endif
2778 #endif
2779 
2780 /* ************************************************************************** */
2781 
2782 #ifndef MNG_OPTIMIZE_CHUNKREADER
2783 #ifndef MNG_SKIPCHUNK_iTXt
READ_CHUNK(mng_read_itxt)2784 READ_CHUNK (mng_read_itxt)
2785 {
2786   mng_retcode iRetcode;
2787   mng_uint32  iKeywordlen, iTextlen, iLanguagelen, iTranslationlen;
2788   mng_pchar   zKeyword, zLanguage, zTranslation;
2789   mng_uint8p  pNull1, pNull2, pNull3;
2790   mng_uint32  iCompressedsize;
2791   mng_uint8   iCompressionflag;
2792   mng_uint32  iBufsize;
2793   mng_uint8p  pBuf;
2794 
2795 #ifdef MNG_SUPPORT_TRACE
2796   MNG_TRACE (pData, MNG_FN_READ_ITXT, MNG_LC_START);
2797 #endif
2798                                        /* sequence checks */
2799 #ifdef MNG_INCLUDE_JNG
2800   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2801       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
2802 #else
2803   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
2804       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
2805 #endif
2806     MNG_ERROR (pData, MNG_SEQUENCEERROR);
2807 
2808   if (iRawlen < 6)                     /* length must be at least 6 */
2809     MNG_ERROR (pData, MNG_INVALIDLENGTH);
2810 
2811   pNull1 = find_null (pRawdata);       /* find the null separators */
2812   pNull2 = find_null (pNull1+3);
2813   pNull3 = find_null (pNull2+1);
2814                                        /* not found inside input-data ? */
2815   if (((pNull1 - pRawdata) > (mng_int32)iRawlen) ||
2816       ((pNull2 - pRawdata) > (mng_int32)iRawlen) ||
2817       ((pNull3 - pRawdata) > (mng_int32)iRawlen)    )
2818     MNG_ERROR (pData, MNG_NULLNOTFOUND);
2819 
2820   if (pNull1 == pRawdata)              /* there must be at least 1 char for keyword */
2821     MNG_ERROR (pData, MNG_KEYWORDNULL);
2822                                        /* compression or not ? */
2823   if ((*(pNull1+1) != 0) && (*(pNull1+1) != 1))
2824     MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
2825 
2826   if (*(pNull1+2) != 0)                /* only deflate compression-method allowed */
2827     MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
2828 
2829   iKeywordlen      = (mng_uint32)(pNull1 - pRawdata);
2830   iLanguagelen     = (mng_uint32)(pNull2 - pNull1 - 3);
2831   iTranslationlen  = (mng_uint32)(pNull3 - pNull2 - 1);
2832   iCompressedsize  = (mng_uint32)(iRawlen - iKeywordlen - iLanguagelen - iTranslationlen - 5);
2833   iCompressionflag = *(pNull1+1);
2834 
2835   zKeyword     = 0;                    /* no buffers acquired yet */
2836   zLanguage    = 0;
2837   zTranslation = 0;
2838   pBuf         = 0;
2839   iTextlen     = 0;
2840 
2841   if (pData->fProcesstext)             /* inform the application ? */
2842   {
2843     if (iCompressionflag)              /* decompress the text ? */
2844     {
2845       iRetcode = mng_inflate_buffer (pData, pNull3+1, iCompressedsize,
2846                                      &pBuf, &iBufsize, &iTextlen);
2847 
2848       if (iRetcode)                    /* on error bail out */
2849       {                                /* don't forget to drop the temp buffer */
2850         MNG_FREEX (pData, pBuf, iBufsize);
2851         return iRetcode;
2852       }
2853     }
2854     else
2855     {
2856       iTextlen = iCompressedsize;
2857       iBufsize = iTextlen+1;           /* plus 1 for terminator byte!!! */
2858 
2859       MNG_ALLOC (pData, pBuf, iBufsize);
2860       MNG_COPY  (pBuf, pNull3+1, iTextlen);
2861     }
2862 
2863     MNG_ALLOCX (pData, zKeyword,     iKeywordlen     + 1);
2864     MNG_ALLOCX (pData, zLanguage,    iLanguagelen    + 1);
2865     MNG_ALLOCX (pData, zTranslation, iTranslationlen + 1);
2866                                        /* on error bail out */
2867     if ((!zKeyword) || (!zLanguage) || (!zTranslation))
2868     {                                  /* don't forget to drop the temp buffers */
2869       MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
2870       MNG_FREEX (pData, zLanguage,    iLanguagelen    + 1);
2871       MNG_FREEX (pData, zKeyword,     iKeywordlen     + 1);
2872       MNG_FREEX (pData, pBuf, iBufsize);
2873       MNG_ERROR (pData, MNG_OUTOFMEMORY);
2874     }
2875 
2876     MNG_COPY (zKeyword,     pRawdata, iKeywordlen);
2877     MNG_COPY (zLanguage,    pNull1+3, iLanguagelen);
2878     MNG_COPY (zTranslation, pNull2+1, iTranslationlen);
2879 
2880     if (!pData->fProcesstext ((mng_handle)pData, MNG_TYPE_ITXT, zKeyword, (mng_pchar)pBuf,
2881                                                                 zLanguage, zTranslation))
2882     {                                  /* don't forget to drop the temp buffers */
2883       MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
2884       MNG_FREEX (pData, zLanguage,    iLanguagelen    + 1);
2885       MNG_FREEX (pData, zKeyword,     iKeywordlen     + 1);
2886       MNG_FREEX (pData, pBuf,         iBufsize);
2887 
2888       MNG_ERROR (pData, MNG_APPMISCERROR);
2889     }
2890   }
2891 
2892 #ifdef MNG_STORE_CHUNKS
2893   if (pData->bStorechunks)
2894   {                                    /* initialize storage */
2895     iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
2896 
2897     if (iRetcode)                      /* on error bail out */
2898     {                                  /* don't forget to drop the temp buffers */
2899       MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
2900       MNG_FREEX (pData, zLanguage,    iLanguagelen    + 1);
2901       MNG_FREEX (pData, zKeyword,     iKeywordlen     + 1);
2902       MNG_FREEX (pData, pBuf,         iBufsize);
2903       return iRetcode;
2904     }
2905                                        /* store the fields */
2906     ((mng_itxtp)*ppChunk)->iKeywordsize       = iKeywordlen;
2907     ((mng_itxtp)*ppChunk)->iLanguagesize      = iLanguagelen;
2908     ((mng_itxtp)*ppChunk)->iTranslationsize   = iTranslationlen;
2909     ((mng_itxtp)*ppChunk)->iCompressionflag   = *(pNull1+1);
2910     ((mng_itxtp)*ppChunk)->iCompressionmethod = *(pNull1+2);
2911 
2912     if ((!pBuf) && (iCompressedsize))  /* did we not get a text-buffer yet ? */
2913     {
2914       if (iCompressionflag)            /* decompress the text ? */
2915       {
2916         iRetcode = mng_inflate_buffer (pData, pNull3+1, iCompressedsize,
2917                                        &pBuf, &iBufsize, &iTextlen);
2918 
2919         if (iRetcode)                  /* on error bail out */
2920         {                              /* don't forget to drop the temp buffers */
2921           MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
2922           MNG_FREEX (pData, zLanguage,    iLanguagelen    + 1);
2923           MNG_FREEX (pData, zKeyword,     iKeywordlen     + 1);
2924           MNG_FREEX (pData, pBuf,         iBufsize);
2925           return iRetcode;
2926         }
2927       }
2928       else
2929       {
2930         iTextlen = iCompressedsize;
2931         iBufsize = iTextlen+1;         /* plus 1 for terminator byte!!! */
2932 
2933         MNG_ALLOC (pData, pBuf, iBufsize);
2934         MNG_COPY  (pBuf, pNull3+1, iTextlen);
2935       }
2936     }
2937 
2938     MNG_ALLOCX (pData, ((mng_itxtp)*ppChunk)->zKeyword,     iKeywordlen     + 1);
2939     MNG_ALLOCX (pData, ((mng_itxtp)*ppChunk)->zLanguage,    iLanguagelen    + 1);
2940     MNG_ALLOCX (pData, ((mng_itxtp)*ppChunk)->zTranslation, iTranslationlen + 1);
2941                                        /* on error bail out */
2942     if ((!((mng_itxtp)*ppChunk)->zKeyword    ) ||
2943         (!((mng_itxtp)*ppChunk)->zLanguage   ) ||
2944         (!((mng_itxtp)*ppChunk)->zTranslation)    )
2945     {                                  /* don't forget to drop the temp buffers */
2946       MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
2947       MNG_FREEX (pData, zLanguage,    iLanguagelen    + 1);
2948       MNG_FREEX (pData, zKeyword,     iKeywordlen     + 1);
2949       MNG_FREEX (pData, pBuf,         iBufsize);
2950       MNG_ERROR (pData, MNG_OUTOFMEMORY);
2951     }
2952 
2953     MNG_COPY (((mng_itxtp)*ppChunk)->zKeyword,     pRawdata, iKeywordlen);
2954     MNG_COPY (((mng_itxtp)*ppChunk)->zLanguage,    pNull1+3, iLanguagelen);
2955     MNG_COPY (((mng_itxtp)*ppChunk)->zTranslation, pNull2+1, iTranslationlen);
2956 
2957     ((mng_itxtp)*ppChunk)->iTextsize = iTextlen;
2958 
2959     if (iTextlen)
2960     {
2961       MNG_ALLOCX (pData, ((mng_itxtp)*ppChunk)->zText, iTextlen + 1);
2962 
2963       if (!((mng_itxtp)*ppChunk)->zText)
2964       {                                /* don't forget to drop the temp buffers */
2965         MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
2966         MNG_FREEX (pData, zLanguage,    iLanguagelen    + 1);
2967         MNG_FREEX (pData, zKeyword,     iKeywordlen     + 1);
2968         MNG_FREEX (pData, pBuf,         iBufsize);
2969         MNG_ERROR (pData, MNG_OUTOFMEMORY);
2970       }
2971 
2972       MNG_COPY  (((mng_itxtp)*ppChunk)->zText, pBuf, iTextlen);
2973     }
2974   }
2975 #endif /* MNG_STORE_CHUNKS */
2976                                        /* free the temporary buffers */
2977   MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
2978   MNG_FREEX (pData, zLanguage,    iLanguagelen    + 1);
2979   MNG_FREEX (pData, zKeyword,     iKeywordlen     + 1);
2980   MNG_FREEX (pData, pBuf,         iBufsize);
2981 
2982 #ifdef MNG_SUPPORT_TRACE
2983   MNG_TRACE (pData, MNG_FN_READ_ITXT, MNG_LC_END);
2984 #endif
2985 
2986   return MNG_NOERROR;                  /* done */
2987 }
2988 #endif
2989 #endif
2990 
2991 /* ************************************************************************** */
2992 
2993 #ifndef MNG_OPTIMIZE_CHUNKREADER
2994 #ifndef MNG_SKIPCHUNK_bKGD
READ_CHUNK(mng_read_bkgd)2995 READ_CHUNK (mng_read_bkgd)
2996 {
2997 #ifdef MNG_SUPPORT_DISPLAY
2998   mng_imagep     pImage = (mng_imagep)pData->pCurrentobj;
2999   mng_imagedatap pBuf;
3000 #endif
3001 
3002 #ifdef MNG_SUPPORT_TRACE
3003   MNG_TRACE (pData, MNG_FN_READ_BKGD, MNG_LC_START);
3004 #endif
3005                                        /* sequence checks */
3006 #ifdef MNG_INCLUDE_JNG
3007   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
3008       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
3009 #else
3010   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
3011       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
3012 #endif
3013     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3014 
3015 #ifdef MNG_INCLUDE_JNG
3016   if ((pData->bHasIDAT) || (pData->bHasJDAT) || (pData->bHasJDAA))
3017 #else
3018   if (pData->bHasIDAT)
3019 #endif
3020     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3021 
3022   if (iRawlen > 6)                     /* it just can't be bigger than that! */
3023     MNG_ERROR (pData, MNG_INVALIDLENGTH);
3024 
3025 #ifdef MNG_INCLUDE_JNG                 /* length checks */
3026   if (pData->bHasJHDR)
3027   {
3028     if (((pData->iJHDRcolortype == 8) || (pData->iJHDRcolortype == 12)) && (iRawlen != 2))
3029       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3030 
3031     if (((pData->iJHDRcolortype == 10) || (pData->iJHDRcolortype == 14)) && (iRawlen != 6))
3032       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3033   }
3034   else
3035 #endif /* MNG_INCLUDE_JNG */
3036   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
3037   {
3038     if (((pData->iColortype == 0) || (pData->iColortype == 4)) && (iRawlen != 2))
3039       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3040 
3041     if (((pData->iColortype == 2) || (pData->iColortype == 6)) && (iRawlen != 6))
3042       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3043 
3044     if ((pData->iColortype == 3) && (iRawlen != 1))
3045       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3046   }
3047   else
3048   {
3049     if (iRawlen != 6)                  /* global is always 16-bit RGB ! */
3050       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3051   }
3052 
3053 #ifdef MNG_INCLUDE_JNG
3054   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
3055 #else
3056   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
3057 #endif
3058     pData->bHasBKGD = MNG_TRUE;        /* indicate bKGD available */
3059   else
3060     pData->bHasglobalBKGD = (mng_bool)(iRawlen != 0);
3061 
3062 #ifdef MNG_SUPPORT_DISPLAY
3063   if (!pImage)                         /* if no object dump it in obj 0 */
3064     pImage = (mng_imagep)pData->pObjzero;
3065 
3066   pBuf = pImage->pImgbuf;              /* address object buffer */
3067 
3068 #ifdef MNG_INCLUDE_JNG
3069   if (pData->bHasJHDR)
3070   {
3071     pBuf->bHasBKGD = MNG_TRUE;         /* tell the object it's got bKGD now */
3072 
3073     switch (pData->iJHDRcolortype)     /* store fields for future reference */
3074     {
3075       case  8 : ;                      /* gray */
3076       case 12 : {                      /* graya */
3077                   pBuf->iBKGDgray  = mng_get_uint16 (pRawdata);
3078                   break;
3079                 }
3080       case 10 : ;                      /* rgb */
3081       case 14 : {                      /* rgba */
3082                   pBuf->iBKGDred   = mng_get_uint16 (pRawdata);
3083                   pBuf->iBKGDgreen = mng_get_uint16 (pRawdata+2);
3084                   pBuf->iBKGDblue  = mng_get_uint16 (pRawdata+4);
3085                   break;
3086                 }
3087     }
3088   }
3089   else
3090 #endif /* MNG_INCLUDE_JNG */
3091   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
3092   {
3093     pBuf->bHasBKGD = MNG_TRUE;         /* tell the object it's got bKGD now */
3094 
3095     switch (pData->iColortype)         /* store fields for future reference */
3096     {
3097       case 0 : ;                        /* gray */
3098       case 4 : {                        /* graya */
3099                  pBuf->iBKGDgray  = mng_get_uint16 (pRawdata);
3100                  break;
3101                }
3102       case 2 : ;                        /* rgb */
3103       case 6 : {                        /* rgba */
3104                  pBuf->iBKGDred   = mng_get_uint16 (pRawdata);
3105                  pBuf->iBKGDgreen = mng_get_uint16 (pRawdata+2);
3106                  pBuf->iBKGDblue  = mng_get_uint16 (pRawdata+4);
3107                  break;
3108                }
3109       case 3 : {                        /* indexed */
3110                  pBuf->iBKGDindex = *pRawdata;
3111                  break;
3112                }
3113     }
3114   }
3115   else                                 /* store as global */
3116   {
3117     if (iRawlen)
3118     {
3119       pData->iGlobalBKGDred   = mng_get_uint16 (pRawdata);
3120       pData->iGlobalBKGDgreen = mng_get_uint16 (pRawdata+2);
3121       pData->iGlobalBKGDblue  = mng_get_uint16 (pRawdata+4);
3122     }
3123 
3124     {                                  /* create an animation object */
3125       mng_retcode iRetcode = mng_create_ani_bkgd (pData, pData->iGlobalBKGDred,
3126                                                   pData->iGlobalBKGDgreen,
3127                                                   pData->iGlobalBKGDblue);
3128 
3129       if (iRetcode)                    /* on error bail out */
3130         return iRetcode;
3131     }
3132   }
3133 #endif /* MNG_SUPPORT_DISPLAY */
3134 
3135 #ifdef MNG_STORE_CHUNKS
3136   if (pData->bStorechunks)
3137   {                                    /* initialize storage */
3138     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
3139 
3140     if (iRetcode)                      /* on error bail out */
3141       return iRetcode;
3142                                        /* store the fields */
3143     ((mng_bkgdp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
3144     ((mng_bkgdp)*ppChunk)->iType  = pData->iColortype;
3145 
3146     if (iRawlen)
3147     {
3148       switch (iRawlen)                 /* guess from length */
3149       {
3150         case 1 : {                     /* indexed */
3151                    ((mng_bkgdp)*ppChunk)->iType  = 3;
3152                    ((mng_bkgdp)*ppChunk)->iIndex = *pRawdata;
3153                    break;
3154                  }
3155         case 2 : {                     /* gray */
3156                    ((mng_bkgdp)*ppChunk)->iType  = 0;
3157                    ((mng_bkgdp)*ppChunk)->iGray  = mng_get_uint16 (pRawdata);
3158                    break;
3159                  }
3160         case 6 : {                     /* rgb */
3161                    ((mng_bkgdp)*ppChunk)->iType  = 2;
3162                    ((mng_bkgdp)*ppChunk)->iRed   = mng_get_uint16 (pRawdata);
3163                    ((mng_bkgdp)*ppChunk)->iGreen = mng_get_uint16 (pRawdata+2);
3164                    ((mng_bkgdp)*ppChunk)->iBlue  = mng_get_uint16 (pRawdata+4);
3165                    break;
3166                  }
3167       }
3168     }
3169   }
3170 #endif /* MNG_STORE_CHUNKS */
3171 
3172 #ifdef MNG_SUPPORT_TRACE
3173   MNG_TRACE (pData, MNG_FN_READ_BKGD, MNG_LC_END);
3174 #endif
3175 
3176   return MNG_NOERROR;                  /* done */
3177 }
3178 #endif
3179 #endif
3180 
3181 /* ************************************************************************** */
3182 
3183 #ifndef MNG_OPTIMIZE_CHUNKREADER
3184 #ifndef MNG_SKIPCHUNK_pHYs
READ_CHUNK(mng_read_phys)3185 READ_CHUNK (mng_read_phys)
3186 {
3187 #ifdef MNG_SUPPORT_TRACE
3188   MNG_TRACE (pData, MNG_FN_READ_PHYS, MNG_LC_START);
3189 #endif
3190                                        /* sequence checks */
3191 #ifdef MNG_INCLUDE_JNG
3192   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
3193       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
3194 #else
3195   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
3196       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
3197 #endif
3198     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3199 
3200 #ifdef MNG_INCLUDE_JNG
3201   if ((pData->bHasIDAT) || (pData->bHasJDAT) || (pData->bHasJDAA))
3202 #else
3203   if (pData->bHasIDAT)
3204 #endif
3205     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3206                                        /* it's 9 bytes or empty; no more, no less! */
3207   if ((iRawlen != 9) && (iRawlen != 0))
3208     MNG_ERROR (pData, MNG_INVALIDLENGTH);
3209 
3210 #ifdef MNG_SUPPORT_DISPLAY
3211   {
3212 
3213 
3214     /* TODO: something !!! */
3215 
3216 
3217   }
3218 #endif /* MNG_SUPPORT_DISPLAY */
3219 
3220 #ifdef MNG_STORE_CHUNKS
3221   if (pData->bStorechunks)
3222   {                                    /* initialize storage */
3223     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
3224 
3225     if (iRetcode)                      /* on error bail out */
3226       return iRetcode;
3227                                        /* store the fields */
3228     ((mng_physp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
3229 
3230     if (iRawlen)
3231     {
3232       ((mng_physp)*ppChunk)->iSizex = mng_get_uint32 (pRawdata);
3233       ((mng_physp)*ppChunk)->iSizey = mng_get_uint32 (pRawdata+4);
3234       ((mng_physp)*ppChunk)->iUnit  = *(pRawdata+8);
3235     }
3236   }
3237 #endif /* MNG_STORE_CHUNKS */
3238 
3239 #ifdef MNG_SUPPORT_TRACE
3240   MNG_TRACE (pData, MNG_FN_READ_PHYS, MNG_LC_END);
3241 #endif
3242 
3243   return MNG_NOERROR;                  /* done */
3244 }
3245 #endif
3246 #endif
3247 
3248 /* ************************************************************************** */
3249 
3250 #ifndef MNG_OPTIMIZE_CHUNKREADER
3251 #ifndef MNG_SKIPCHUNK_sBIT
READ_CHUNK(mng_read_sbit)3252 READ_CHUNK (mng_read_sbit)
3253 {
3254 #ifdef MNG_SUPPORT_TRACE
3255   MNG_TRACE (pData, MNG_FN_READ_SBIT, MNG_LC_START);
3256 #endif
3257                                        /* sequence checks */
3258 #ifdef MNG_INCLUDE_JNG
3259   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
3260       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
3261 #else
3262   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
3263       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
3264 #endif
3265     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3266 
3267 #ifdef MNG_INCLUDE_JNG
3268   if ((pData->bHasPLTE) || (pData->bHasIDAT) || (pData->bHasJDAT) || (pData->bHasJDAA))
3269 #else
3270   if ((pData->bHasPLTE) || (pData->bHasIDAT))
3271 #endif
3272     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3273 
3274   if (iRawlen > 4)                     /* it just can't be bigger than that! */
3275     MNG_ERROR (pData, MNG_INVALIDLENGTH);
3276 
3277 #ifdef MNG_INCLUDE_JNG                 /* length checks */
3278   if (pData->bHasJHDR)
3279   {
3280     if ((pData->iJHDRcolortype ==  8) && (iRawlen != 1))
3281       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3282 
3283     if ((pData->iJHDRcolortype == 10) && (iRawlen != 3))
3284       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3285 
3286     if ((pData->iJHDRcolortype == 12) && (iRawlen != 2))
3287       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3288 
3289     if ((pData->iJHDRcolortype == 14) && (iRawlen != 4))
3290       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3291   }
3292   else
3293 #endif /* MNG_INCLUDE_JNG */
3294   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
3295   {
3296     if ((pData->iColortype == 0) && (iRawlen != 1))
3297       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3298 
3299     if ((pData->iColortype == 2) && (iRawlen != 3))
3300       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3301 
3302     if ((pData->iColortype == 3) && (iRawlen != 3))
3303       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3304 
3305     if ((pData->iColortype == 4) && (iRawlen != 2))
3306       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3307 
3308     if ((pData->iColortype == 6) && (iRawlen != 4))
3309       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3310   }
3311   else
3312   {                                    /* global = empty or RGBA */
3313     if ((iRawlen != 0) && (iRawlen != 4))
3314       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3315   }
3316 
3317 #ifdef MNG_SUPPORT_DISPLAY
3318   {
3319 
3320 
3321     /* TODO: something !!! */
3322 
3323 
3324   }
3325 #endif /* MNG_SUPPORT_DISPLAY */
3326 
3327 #ifdef MNG_STORE_CHUNKS
3328   if (pData->bStorechunks)
3329   {                                    /* initialize storage */
3330     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
3331 
3332     if (iRetcode)                      /* on error bail out */
3333       return iRetcode;
3334                                        /* store the fields */
3335     ((mng_sbitp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
3336 
3337     if (iRawlen)
3338     {
3339 #ifdef MNG_INCLUDE_JNG
3340       if (pData->bHasJHDR)
3341         ((mng_sbitp)*ppChunk)->iType = pData->iJHDRcolortype;
3342       else
3343 #endif
3344       if (pData->bHasIHDR)
3345         ((mng_sbitp)*ppChunk)->iType = pData->iColortype;
3346       else                             /* global ! */
3347         ((mng_sbitp)*ppChunk)->iType = 6;
3348 
3349       if (iRawlen > 0)
3350         ((mng_sbitp)*ppChunk)->aBits [0] = *pRawdata;
3351       if (iRawlen > 1)
3352         ((mng_sbitp)*ppChunk)->aBits [1] = *(pRawdata+1);
3353       if (iRawlen > 2)
3354         ((mng_sbitp)*ppChunk)->aBits [2] = *(pRawdata+2);
3355       if (iRawlen > 3)
3356         ((mng_sbitp)*ppChunk)->aBits [3] = *(pRawdata+3);
3357 
3358     }
3359   }
3360 #endif /* MNG_STORE_CHUNKS */
3361 
3362 #ifdef MNG_SUPPORT_TRACE
3363   MNG_TRACE (pData, MNG_FN_READ_SBIT, MNG_LC_END);
3364 #endif
3365 
3366   return MNG_NOERROR;                  /* done */
3367 }
3368 #endif
3369 #endif
3370 
3371 /* ************************************************************************** */
3372 
3373 #ifndef MNG_OPTIMIZE_CHUNKREADER
3374 #ifndef MNG_SKIPCHUNK_sPLT
READ_CHUNK(mng_read_splt)3375 READ_CHUNK (mng_read_splt)
3376 {
3377   mng_uint8p pTemp;
3378   mng_uint32 iNamelen;
3379   mng_uint8  iSampledepth;
3380   mng_uint32 iRemain;
3381 
3382 #ifdef MNG_SUPPORT_TRACE
3383   MNG_TRACE (pData, MNG_FN_READ_SPLT, MNG_LC_START);
3384 #endif
3385                                        /* sequence checks */
3386   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
3387       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
3388     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3389 
3390   if (pData->bHasIDAT)
3391     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3392 
3393   if (iRawlen)
3394   {
3395     pTemp = find_null (pRawdata);      /* find null-separator */
3396                                        /* not found inside input-data ? */
3397     if ((pTemp - pRawdata) > (mng_int32)iRawlen)
3398       MNG_ERROR (pData, MNG_NULLNOTFOUND);
3399 
3400     iNamelen     = (mng_uint32)(pTemp - pRawdata);
3401     iSampledepth = *(pTemp+1);
3402     iRemain      = (iRawlen - 2 - iNamelen);
3403 
3404     if ((iSampledepth != 1) && (iSampledepth != 2))
3405       MNG_ERROR (pData, MNG_INVSAMPLEDEPTH);
3406                                        /* check remaining length */
3407     if ( ((iSampledepth == 1) && (iRemain %  6 != 0)) ||
3408          ((iSampledepth == 2) && (iRemain % 10 != 0))    )
3409       MNG_ERROR (pData, MNG_INVALIDLENGTH);
3410 
3411   }
3412   else
3413   {
3414     pTemp        = MNG_NULL;
3415     iNamelen     = 0;
3416     iSampledepth = 0;
3417     iRemain      = 0;
3418   }
3419 
3420 #ifdef MNG_SUPPORT_DISPLAY
3421   {
3422 
3423 
3424     /* TODO: something !!! */
3425 
3426 
3427   }
3428 #endif /* MNG_SUPPORT_DISPLAY */
3429 
3430 #ifdef MNG_STORE_CHUNKS
3431   if (pData->bStorechunks)
3432   {                                    /* initialize storage */
3433     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
3434 
3435     if (iRetcode)                      /* on error bail out */
3436       return iRetcode;
3437                                        /* store the fields */
3438     ((mng_spltp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
3439 
3440     if (iRawlen)
3441     {
3442       ((mng_spltp)*ppChunk)->iNamesize    = iNamelen;
3443       ((mng_spltp)*ppChunk)->iSampledepth = iSampledepth;
3444 
3445       if (iSampledepth == 1)
3446         ((mng_spltp)*ppChunk)->iEntrycount = iRemain / 6;
3447       else
3448         ((mng_spltp)*ppChunk)->iEntrycount = iRemain / 10;
3449 
3450       if (iNamelen)
3451       {
3452         MNG_ALLOC (pData, ((mng_spltp)*ppChunk)->zName, iNamelen+1);
3453         MNG_COPY (((mng_spltp)*ppChunk)->zName, pRawdata, iNamelen);
3454       }
3455 
3456       if (iRemain)
3457       {
3458         MNG_ALLOC (pData, ((mng_spltp)*ppChunk)->pEntries, iRemain);
3459         MNG_COPY (((mng_spltp)*ppChunk)->pEntries, pTemp+2, iRemain);
3460       }
3461     }
3462   }
3463 #endif /* MNG_STORE_CHUNKS */
3464 
3465 #ifdef MNG_SUPPORT_TRACE
3466   MNG_TRACE (pData, MNG_FN_READ_SPLT, MNG_LC_END);
3467 #endif
3468 
3469   return MNG_NOERROR;                  /* done */
3470 }
3471 #endif
3472 #endif
3473 
3474 /* ************************************************************************** */
3475 
3476 #ifndef MNG_OPTIMIZE_CHUNKREADER
3477 #ifndef MNG_SKIPCHUNK_hIST
READ_CHUNK(mng_read_hist)3478 READ_CHUNK (mng_read_hist)
3479 {
3480 #ifdef MNG_SUPPORT_TRACE
3481   MNG_TRACE (pData, MNG_FN_READ_HIST, MNG_LC_START);
3482 #endif
3483                                        /* sequence checks */
3484   if ((!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR)    )
3485     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3486 
3487   if ((!pData->bHasPLTE) || (pData->bHasIDAT))
3488     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3489                                        /* length oke ? */
3490   if ( ((iRawlen & 0x01) != 0) || ((iRawlen >> 1) != pData->iPLTEcount) )
3491     MNG_ERROR (pData, MNG_INVALIDLENGTH);
3492 
3493 #ifdef MNG_SUPPORT_DISPLAY
3494   {
3495 
3496 
3497     /* TODO: something !!! */
3498 
3499 
3500   }
3501 #endif /* MNG_SUPPORT_DISPLAY */
3502 
3503 #ifdef MNG_STORE_CHUNKS
3504   if (pData->bStorechunks)
3505   {
3506     mng_uint32 iX;
3507                                        /* initialize storage */
3508     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
3509 
3510     if (iRetcode)                      /* on error bail out */
3511       return iRetcode;
3512                                        /* store the fields */
3513     ((mng_histp)*ppChunk)->iEntrycount = iRawlen >> 1;
3514 
3515     for (iX = 0; iX < (iRawlen >> 1); iX++)
3516     {
3517       ((mng_histp)*ppChunk)->aEntries [iX] = mng_get_uint16 (pRawdata);
3518       pRawdata += 2;
3519     }
3520   }
3521 #endif /* MNG_STORE_CHUNKS */
3522 
3523 #ifdef MNG_SUPPORT_TRACE
3524   MNG_TRACE (pData, MNG_FN_READ_HIST, MNG_LC_END);
3525 #endif
3526 
3527   return MNG_NOERROR;                  /* done */
3528 }
3529 #endif
3530 #endif
3531 
3532 /* ************************************************************************** */
3533 
3534 #ifndef MNG_OPTIMIZE_CHUNKREADER
3535 #ifndef MNG_SKIPCHUNK_tIME
READ_CHUNK(mng_read_time)3536 READ_CHUNK (mng_read_time)
3537 {
3538 #ifdef MNG_SUPPORT_TRACE
3539   MNG_TRACE (pData, MNG_FN_READ_TIME, MNG_LC_START);
3540 #endif
3541                                        /* sequence checks */
3542 #ifdef MNG_INCLUDE_JNG
3543   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
3544       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
3545 #else
3546   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
3547       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
3548 #endif
3549     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3550 
3551   if (iRawlen != 7)                    /* length must be exactly 7 */
3552     MNG_ERROR (pData, MNG_INVALIDLENGTH);
3553 
3554 /*  if (pData->fProcesstime) */            /* inform the application ? */
3555 /*  {
3556 
3557     pData->fProcesstime ((mng_handle)pData, );
3558   } */
3559 
3560 #ifdef MNG_STORE_CHUNKS
3561   if (pData->bStorechunks)
3562   {                                    /* initialize storage */
3563     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
3564 
3565     if (iRetcode)                      /* on error bail out */
3566       return iRetcode;
3567                                        /* store the fields */
3568     ((mng_timep)*ppChunk)->iYear   = mng_get_uint16 (pRawdata);
3569     ((mng_timep)*ppChunk)->iMonth  = *(pRawdata+2);
3570     ((mng_timep)*ppChunk)->iDay    = *(pRawdata+3);
3571     ((mng_timep)*ppChunk)->iHour   = *(pRawdata+4);
3572     ((mng_timep)*ppChunk)->iMinute = *(pRawdata+5);
3573     ((mng_timep)*ppChunk)->iSecond = *(pRawdata+6);
3574   }
3575 #endif /* MNG_STORE_CHUNKS */
3576 
3577 #ifdef MNG_SUPPORT_TRACE
3578   MNG_TRACE (pData, MNG_FN_READ_TIME, MNG_LC_END);
3579 #endif
3580 
3581   return MNG_NOERROR;                  /* done */
3582 }
3583 #endif
3584 #endif
3585 
3586 /* ************************************************************************** */
3587 
3588 #ifndef MNG_OPTIMIZE_CHUNKREADER
READ_CHUNK(mng_read_mhdr)3589 READ_CHUNK (mng_read_mhdr)
3590 {
3591 #ifdef MNG_SUPPORT_TRACE
3592   MNG_TRACE (pData, MNG_FN_READ_MHDR, MNG_LC_START);
3593 #endif
3594 
3595   if (pData->eSigtype != mng_it_mng)   /* sequence checks */
3596     MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
3597 
3598   if (pData->bHasheader)               /* can only be the first chunk! */
3599     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3600                                        /* correct length ? */
3601 #ifndef MNG_NO_OLD_VERSIONS
3602   if ((iRawlen != 28) && (iRawlen != 12))
3603 #else
3604   if ((iRawlen != 28))
3605 #endif
3606     MNG_ERROR (pData, MNG_INVALIDLENGTH);
3607 
3608   pData->bHasMHDR       = MNG_TRUE;    /* oh boy, a real MNG */
3609   pData->bHasheader     = MNG_TRUE;    /* we've got a header */
3610   pData->eImagetype     = mng_it_mng;  /* fill header fields */
3611   pData->iWidth         = mng_get_uint32 (pRawdata);
3612   pData->iHeight        = mng_get_uint32 (pRawdata+4);
3613   pData->iTicks         = mng_get_uint32 (pRawdata+8);
3614 
3615 #ifndef MNG_NO_OLD_VERSIONS
3616   if (iRawlen == 28)                   /* proper MHDR ? */
3617   {
3618 #endif
3619     pData->iLayercount  = mng_get_uint32 (pRawdata+12);
3620     pData->iFramecount  = mng_get_uint32 (pRawdata+16);
3621     pData->iPlaytime    = mng_get_uint32 (pRawdata+20);
3622     pData->iSimplicity  = mng_get_uint32 (pRawdata+24);
3623 
3624 #ifndef MNG_NO_OLD_VERSIONS
3625     pData->bPreDraft48  = MNG_FALSE;
3626   }
3627   else                                 /* probably pre-draft48 then */
3628   {
3629     pData->iLayercount  = 0;
3630     pData->iFramecount  = 0;
3631     pData->iPlaytime    = 0;
3632     pData->iSimplicity  = 0;
3633 
3634     pData->bPreDraft48  = MNG_TRUE;
3635   }
3636 #endif
3637                                        /* predict alpha-depth */
3638   if ((pData->iSimplicity & 0x00000001) == 0)
3639 #ifndef MNG_NO_16BIT_SUPPORT
3640     pData->iAlphadepth = 16;           /* no indicators = assume the worst */
3641 #else
3642     pData->iAlphadepth = 8;            /* anything else = assume the worst */
3643 #endif
3644   else
3645   if ((pData->iSimplicity & 0x00000008) == 0)
3646     pData->iAlphadepth = 0;            /* no transparency at all */
3647   else
3648   if ((pData->iSimplicity & 0x00000140) == 0x00000040)
3649     pData->iAlphadepth = 1;            /* no semi-transparency guaranteed */
3650   else
3651 #ifndef MNG_NO_16BIT_SUPPORT
3652     pData->iAlphadepth = 16;           /* anything else = assume the worst */
3653 #else
3654     pData->iAlphadepth = 8;            /* anything else = assume the worst */
3655 #endif
3656 
3657 #ifdef MNG_INCLUDE_JNG                 /* can we handle the complexity ? */
3658   if (pData->iSimplicity & 0x0000FC00)
3659 #else
3660   if (pData->iSimplicity & 0x0000FC10)
3661 #endif
3662     MNG_ERROR (pData, MNG_MNGTOOCOMPLEX);
3663                                        /* fits on maximum canvas ? */
3664   if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
3665     MNG_WARNING (pData, MNG_IMAGETOOLARGE);
3666 
3667   if (pData->fProcessheader)           /* inform the app ? */
3668     if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
3669       MNG_ERROR (pData, MNG_APPMISCERROR);
3670 
3671   pData->iImagelevel++;                /* one level deeper */
3672 
3673 #ifdef MNG_STORE_CHUNKS
3674   if (pData->bStorechunks)
3675   {                                    /* initialize storage */
3676     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
3677 
3678     if (iRetcode)                      /* on error bail out */
3679       return iRetcode;
3680                                        /* store the fields */
3681     ((mng_mhdrp)*ppChunk)->iWidth      = pData->iWidth;
3682     ((mng_mhdrp)*ppChunk)->iHeight     = pData->iHeight;
3683     ((mng_mhdrp)*ppChunk)->iTicks      = pData->iTicks;
3684     ((mng_mhdrp)*ppChunk)->iLayercount = pData->iLayercount;
3685     ((mng_mhdrp)*ppChunk)->iFramecount = pData->iFramecount;
3686     ((mng_mhdrp)*ppChunk)->iPlaytime   = pData->iPlaytime;
3687     ((mng_mhdrp)*ppChunk)->iSimplicity = pData->iSimplicity;
3688   }
3689 #endif /* MNG_STORE_CHUNKS */
3690 
3691 #ifdef MNG_SUPPORT_TRACE
3692   MNG_TRACE (pData, MNG_FN_READ_MHDR, MNG_LC_END);
3693 #endif
3694 
3695   return MNG_NOERROR;                  /* done */
3696 }
3697 #endif
3698 
3699 /* ************************************************************************** */
3700 
3701 #ifndef MNG_OPTIMIZE_CHUNKREADER
READ_CHUNK(mng_read_mend)3702 READ_CHUNK (mng_read_mend)
3703 {
3704 #ifdef MNG_SUPPORT_TRACE
3705   MNG_TRACE (pData, MNG_FN_READ_MEND, MNG_LC_START);
3706 #endif
3707 
3708   if (!pData->bHasMHDR)                /* sequence checks */
3709     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3710 
3711   if (iRawlen > 0)                     /* must not contain data! */
3712     MNG_ERROR (pData, MNG_INVALIDLENGTH);
3713 
3714 #ifdef MNG_SUPPORT_DISPLAY
3715   {                                    /* do something */
3716     mng_retcode iRetcode = mng_process_display_mend (pData);
3717 
3718     if (iRetcode)                      /* on error bail out */
3719       return iRetcode;
3720 
3721     if (!pData->iTotalframes)          /* save totals */
3722       pData->iTotalframes   = pData->iFrameseq;
3723     if (!pData->iTotallayers)
3724       pData->iTotallayers   = pData->iLayerseq;
3725     if (!pData->iTotalplaytime)
3726       pData->iTotalplaytime = pData->iFrametime;
3727   }
3728 #endif /* MNG_SUPPORT_DISPLAY */
3729 
3730   pData->bHasMHDR = MNG_FALSE;         /* end of the line, bro! */
3731 
3732 #ifdef MNG_STORE_CHUNKS
3733   if (pData->bStorechunks)
3734   {                                    /* initialize storage */
3735     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
3736 
3737     if (iRetcode)                      /* on error bail out */
3738       return iRetcode;
3739   }
3740 #endif /* MNG_STORE_CHUNKS */
3741 
3742 #ifdef MNG_SUPPORT_TRACE
3743   MNG_TRACE (pData, MNG_FN_READ_MEND, MNG_LC_END);
3744 #endif
3745 
3746   return MNG_NOERROR;                  /* done */
3747 }
3748 #endif
3749 
3750 /* ************************************************************************** */
3751 
3752 #ifndef MNG_OPTIMIZE_CHUNKREADER
3753 #ifndef MNG_SKIPCHUNK_LOOP
READ_CHUNK(mng_read_loop)3754 READ_CHUNK (mng_read_loop)
3755 {
3756 #ifdef MNG_SUPPORT_TRACE
3757   MNG_TRACE (pData, MNG_FN_READ_LOOP, MNG_LC_START);
3758 #endif
3759 
3760   if (!pData->bHasMHDR)                /* sequence checks */
3761     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3762 
3763   if (!pData->bCacheplayback)          /* must store playback info to work!! */
3764     MNG_ERROR (pData, MNG_LOOPWITHCACHEOFF);
3765 
3766 #ifdef MNG_INCLUDE_JNG
3767   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
3768 #else
3769   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
3770 #endif
3771     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3772 
3773   if (iRawlen >= 5)                    /* length checks */
3774   {
3775     if (iRawlen >= 6)
3776     {
3777       if ((iRawlen - 6) % 4 != 0)
3778         MNG_ERROR (pData, MNG_INVALIDLENGTH);
3779     }
3780   }
3781   else
3782     MNG_ERROR (pData, MNG_INVALIDLENGTH);
3783 
3784 #ifdef MNG_SUPPORT_DISPLAY
3785   {
3786     mng_uint8   iLevel;
3787     mng_uint32  iRepeat;
3788     mng_uint8   iTermination = 0;
3789     mng_uint32  iItermin     = 1;
3790     mng_uint32  iItermax     = 0x7fffffffL;
3791     mng_retcode iRetcode;
3792 
3793     pData->bHasLOOP = MNG_TRUE;        /* indicate we're inside a loop */
3794 
3795     iLevel = *pRawdata;                /* determine the fields for processing */
3796 
3797 #ifndef MNG_NO_OLD_VERSIONS
3798     if (pData->bPreDraft48)
3799     {
3800       iTermination = *(pRawdata+1);
3801 
3802       iRepeat = mng_get_uint32 (pRawdata+2);
3803     }
3804     else
3805 #endif
3806       iRepeat = mng_get_uint32 (pRawdata+1);
3807 
3808     if (iRawlen >= 6)
3809     {
3810 #ifndef MNG_NO_OLD_VERSIONS
3811       if (!pData->bPreDraft48)
3812 #endif
3813         iTermination = *(pRawdata+5);
3814 
3815       if (iRawlen >= 10)
3816       {
3817         iItermin = mng_get_uint32 (pRawdata+6);
3818 
3819         if (iRawlen >= 14)
3820         {
3821           iItermax = mng_get_uint32 (pRawdata+10);
3822 
3823           /* TODO: process signals */
3824 
3825         }
3826       }
3827     }
3828                                        /* create the LOOP ani-object */
3829     iRetcode = mng_create_ani_loop (pData, iLevel, iRepeat, iTermination,
3830                                            iItermin, iItermax, 0, 0);
3831 
3832     if (iRetcode)                      /* on error bail out */
3833       return iRetcode;
3834                                        /* skip till matching ENDL if iteration=0 */
3835     if ((!pData->bSkipping) && (iRepeat == 0))
3836       pData->bSkipping = MNG_TRUE;
3837   }
3838 #endif /* MNG_SUPPORT_DISPLAY */
3839 
3840 #ifdef MNG_STORE_CHUNKS
3841   if (pData->bStorechunks)
3842   {                                    /* initialize storage */
3843     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
3844 
3845     if (iRetcode)                      /* on error bail out */
3846       return iRetcode;
3847 
3848     if (iRawlen >= 5)                  /* store the fields */
3849     {
3850       ((mng_loopp)*ppChunk)->iLevel  = *pRawdata;
3851 
3852 #ifndef MNG_NO_OLD_VERSIONS
3853       if (pData->bPreDraft48)
3854       {
3855         ((mng_loopp)*ppChunk)->iTermination = *(pRawdata+1);
3856         ((mng_loopp)*ppChunk)->iRepeat = mng_get_uint32 (pRawdata+2);
3857       }
3858       else
3859 #endif
3860       {
3861         ((mng_loopp)*ppChunk)->iRepeat = mng_get_uint32 (pRawdata+1);
3862       }
3863 
3864       if (iRawlen >= 6)
3865       {
3866 #ifndef MNG_NO_OLD_VERSIONS
3867         if (!pData->bPreDraft48)
3868 #endif
3869           ((mng_loopp)*ppChunk)->iTermination = *(pRawdata+5);
3870 
3871         if (iRawlen >= 10)
3872         {
3873           ((mng_loopp)*ppChunk)->iItermin = mng_get_uint32 (pRawdata+6);
3874 
3875 #ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
3876           if (iRawlen >= 14)
3877           {
3878             ((mng_loopp)*ppChunk)->iItermax = mng_get_uint32 (pRawdata+10);
3879             ((mng_loopp)*ppChunk)->iCount   = (iRawlen - 14) / 4;
3880 
3881             if (((mng_loopp)*ppChunk)->iCount)
3882             {
3883               MNG_ALLOC (pData, ((mng_loopp)*ppChunk)->pSignals,
3884                                 ((mng_loopp)*ppChunk)->iCount << 2);
3885 
3886 #ifndef MNG_BIGENDIAN_SUPPORTED
3887               {
3888                 mng_uint32  iX;
3889                 mng_uint8p  pIn  = pRawdata + 14;
3890                 mng_uint32p pOut = (mng_uint32p)((mng_loopp)*ppChunk)->pSignals;
3891 
3892                 for (iX = 0; iX < ((mng_loopp)*ppChunk)->iCount; iX++)
3893                 {
3894                   *pOut++ = mng_get_uint32 (pIn);
3895                   pIn += 4;
3896                 }
3897               }
3898 #else
3899               MNG_COPY (((mng_loopp)*ppChunk)->pSignals, pRawdata + 14,
3900                         ((mng_loopp)*ppChunk)->iCount << 2);
3901 #endif /* !MNG_BIGENDIAN_SUPPORTED */
3902             }
3903           }
3904 #endif
3905         }
3906       }
3907     }
3908   }
3909 #endif /* MNG_STORE_CHUNKS */
3910 
3911 #ifdef MNG_SUPPORT_TRACE
3912   MNG_TRACE (pData, MNG_FN_READ_LOOP, MNG_LC_END);
3913 #endif
3914 
3915   return MNG_NOERROR;                  /* done */
3916 }
3917 #endif
3918 #endif
3919 
3920 /* ************************************************************************** */
3921 
3922 #ifndef MNG_OPTIMIZE_CHUNKREADER
3923 #ifndef MNG_SKIPCHUNK_LOOP
READ_CHUNK(mng_read_endl)3924 READ_CHUNK (mng_read_endl)
3925 {
3926 #ifdef MNG_SUPPORT_TRACE
3927   MNG_TRACE (pData, MNG_FN_READ_ENDL, MNG_LC_START);
3928 #endif
3929 
3930   if (!pData->bHasMHDR)                /* sequence checks */
3931     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3932 
3933 #ifdef MNG_INCLUDE_JNG
3934   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
3935 #else
3936   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
3937 #endif
3938     MNG_ERROR (pData, MNG_SEQUENCEERROR);
3939 
3940   if (iRawlen != 1)                    /* length must be exactly 1 */
3941     MNG_ERROR (pData, MNG_INVALIDLENGTH);
3942 
3943 #ifdef MNG_SUPPORT_DISPLAY
3944   {
3945     if (pData->bHasLOOP)               /* are we really processing a loop ? */
3946     {
3947       mng_uint8 iLevel = *pRawdata;    /* get the nest level */
3948                                        /* create an ENDL animation object */
3949       mng_retcode iRetcode = mng_create_ani_endl (pData, iLevel);
3950 
3951       if (iRetcode)                    /* on error bail out */
3952         return iRetcode;
3953 
3954 /*      {
3955         mng_ani_endlp pENDL = (mng_ani_endlp)pData->pLastaniobj;
3956 
3957         iRetcode = pENDL->sHeader.fProcess (pData, pENDL);
3958 
3959         if (iRetcode)
3960           return iRetcode;
3961       } */
3962     }
3963     else
3964       MNG_ERROR (pData, MNG_NOMATCHINGLOOP);
3965 
3966   }
3967 #endif /* MNG_SUPPORT_DISPLAY */
3968 
3969 #ifdef MNG_STORE_CHUNKS
3970   if (pData->bStorechunks)
3971   {                                    /* initialize storage */
3972     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
3973 
3974     if (iRetcode)                      /* on error bail out */
3975       return iRetcode;
3976                                        /* store the fields */
3977     ((mng_endlp)*ppChunk)->iLevel = *pRawdata;
3978   }
3979 #endif /* MNG_STORE_CHUNKS */
3980 
3981 #ifdef MNG_SUPPORT_TRACE
3982   MNG_TRACE (pData, MNG_FN_READ_ENDL, MNG_LC_END);
3983 #endif
3984 
3985   return MNG_NOERROR;                  /* done */
3986 }
3987 #endif
3988 #endif
3989 
3990 /* ************************************************************************** */
3991 
3992 #ifndef MNG_OPTIMIZE_CHUNKREADER
3993 #ifndef MNG_SKIPCHUNK_DEFI
READ_CHUNK(mng_read_defi)3994 READ_CHUNK (mng_read_defi)
3995 {
3996 #ifdef MNG_SUPPORT_TRACE
3997   MNG_TRACE (pData, MNG_FN_READ_DEFI, MNG_LC_START);
3998 #endif
3999 
4000   if (!pData->bHasMHDR)                /* sequence checks */
4001     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4002 
4003 #ifdef MNG_INCLUDE_JNG
4004   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
4005 #else
4006   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
4007 #endif
4008     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4009                                        /* check the length */
4010   if ((iRawlen != 2) && (iRawlen != 3) && (iRawlen != 4) &&
4011       (iRawlen != 12) && (iRawlen != 28))
4012     MNG_ERROR (pData, MNG_INVALIDLENGTH);
4013 
4014 #ifdef MNG_SUPPORT_DISPLAY
4015   {
4016     mng_retcode iRetcode;
4017 
4018     pData->iDEFIobjectid       = mng_get_uint16 (pRawdata);
4019 
4020     if (iRawlen > 2)
4021     {
4022       pData->bDEFIhasdonotshow = MNG_TRUE;
4023       pData->iDEFIdonotshow    = *(pRawdata+2);
4024     }
4025     else
4026     {
4027       pData->bDEFIhasdonotshow = MNG_FALSE;
4028       pData->iDEFIdonotshow    = 0;
4029     }
4030 
4031     if (iRawlen > 3)
4032     {
4033       pData->bDEFIhasconcrete  = MNG_TRUE;
4034       pData->iDEFIconcrete     = *(pRawdata+3);
4035     }
4036     else
4037     {
4038       pData->bDEFIhasconcrete  = MNG_FALSE;
4039       pData->iDEFIconcrete     = 0;
4040     }
4041 
4042     if (iRawlen > 4)
4043     {
4044       pData->bDEFIhasloca      = MNG_TRUE;
4045       pData->iDEFIlocax        = mng_get_int32 (pRawdata+4);
4046       pData->iDEFIlocay        = mng_get_int32 (pRawdata+8);
4047     }
4048     else
4049     {
4050       pData->bDEFIhasloca      = MNG_FALSE;
4051       pData->iDEFIlocax        = 0;
4052       pData->iDEFIlocay        = 0;
4053     }
4054 
4055     if (iRawlen > 12)
4056     {
4057       pData->bDEFIhasclip      = MNG_TRUE;
4058       pData->iDEFIclipl        = mng_get_int32 (pRawdata+12);
4059       pData->iDEFIclipr        = mng_get_int32 (pRawdata+16);
4060       pData->iDEFIclipt        = mng_get_int32 (pRawdata+20);
4061       pData->iDEFIclipb        = mng_get_int32 (pRawdata+24);
4062     }
4063     else
4064     {
4065       pData->bDEFIhasclip      = MNG_FALSE;
4066       pData->iDEFIclipl        = 0;
4067       pData->iDEFIclipr        = 0;
4068       pData->iDEFIclipt        = 0;
4069       pData->iDEFIclipb        = 0;
4070     }
4071                                        /* create an animation object */
4072     iRetcode = mng_create_ani_defi (pData);
4073 
4074     if (!iRetcode)                     /* do display processing */
4075       iRetcode = mng_process_display_defi (pData);
4076 
4077     if (iRetcode)                      /* on error bail out */
4078       return iRetcode;
4079 
4080   }
4081 #endif /* MNG_SUPPORT_DISPLAY */
4082 
4083 #ifdef MNG_STORE_CHUNKS
4084   if (pData->bStorechunks)
4085   {                                    /* initialize storage */
4086     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
4087 
4088     if (iRetcode)                      /* on error bail out */
4089       return iRetcode;
4090                                        /* store the fields */
4091     ((mng_defip)*ppChunk)->iObjectid       = mng_get_uint16 (pRawdata);
4092 
4093     if (iRawlen > 2)
4094     {
4095       ((mng_defip)*ppChunk)->bHasdonotshow = MNG_TRUE;
4096       ((mng_defip)*ppChunk)->iDonotshow    = *(pRawdata+2);
4097     }
4098     else
4099       ((mng_defip)*ppChunk)->bHasdonotshow = MNG_FALSE;
4100 
4101     if (iRawlen > 3)
4102     {
4103       ((mng_defip)*ppChunk)->bHasconcrete  = MNG_TRUE;
4104       ((mng_defip)*ppChunk)->iConcrete     = *(pRawdata+3);
4105     }
4106     else
4107       ((mng_defip)*ppChunk)->bHasconcrete  = MNG_FALSE;
4108 
4109     if (iRawlen > 4)
4110     {
4111       ((mng_defip)*ppChunk)->bHasloca      = MNG_TRUE;
4112       ((mng_defip)*ppChunk)->iXlocation    = mng_get_int32 (pRawdata+4);
4113       ((mng_defip)*ppChunk)->iYlocation    = mng_get_int32 (pRawdata+8);
4114     }
4115     else
4116       ((mng_defip)*ppChunk)->bHasloca      = MNG_FALSE;
4117 
4118     if (iRawlen > 12)
4119     {
4120       ((mng_defip)*ppChunk)->bHasclip      = MNG_TRUE;
4121       ((mng_defip)*ppChunk)->iLeftcb       = mng_get_int32 (pRawdata+12);
4122       ((mng_defip)*ppChunk)->iRightcb      = mng_get_int32 (pRawdata+16);
4123       ((mng_defip)*ppChunk)->iTopcb        = mng_get_int32 (pRawdata+20);
4124       ((mng_defip)*ppChunk)->iBottomcb     = mng_get_int32 (pRawdata+24);
4125     }
4126     else
4127       ((mng_defip)*ppChunk)->bHasclip      = MNG_FALSE;
4128 
4129   }
4130 #endif /* MNG_STORE_CHUNKS */
4131 
4132 #ifdef MNG_SUPPORT_TRACE
4133   MNG_TRACE (pData, MNG_FN_READ_DEFI, MNG_LC_END);
4134 #endif
4135 
4136   return MNG_NOERROR;                  /* done */
4137 }
4138 #endif
4139 #endif
4140 
4141 /* ************************************************************************** */
4142 
4143 #ifndef MNG_OPTIMIZE_CHUNKREADER
4144 #ifndef MNG_SKIPCHUNK_BASI
READ_CHUNK(mng_read_basi)4145 READ_CHUNK (mng_read_basi)
4146 {
4147 #ifdef MNG_SUPPORT_TRACE
4148   MNG_TRACE (pData, MNG_FN_READ_BASI, MNG_LC_START);
4149 #endif
4150 
4151   if (!pData->bHasMHDR)                /* sequence checks */
4152     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4153 
4154 #ifdef MNG_INCLUDE_JNG
4155   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
4156 #else
4157   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
4158 #endif
4159     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4160                                        /* check the length */
4161   if ((iRawlen != 13) && (iRawlen != 19) && (iRawlen != 21) && (iRawlen != 22))
4162     MNG_ERROR (pData, MNG_INVALIDLENGTH);
4163 
4164   pData->bHasBASI     = MNG_TRUE;      /* inside a BASI-IEND block now */
4165                                        /* store interesting fields */
4166   pData->iDatawidth   = mng_get_uint32 (pRawdata);
4167   pData->iDataheight  = mng_get_uint32 (pRawdata+4);
4168   pData->iBitdepth    = *(pRawdata+8);
4169   pData->iColortype   = *(pRawdata+9);
4170   pData->iCompression = *(pRawdata+10);
4171   pData->iFilter      = *(pRawdata+11);
4172   pData->iInterlace   = *(pRawdata+12);
4173 
4174 
4175 #if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
4176   pData->iPNGmult = 1;
4177   pData->iPNGdepth = pData->iBitdepth;
4178 #endif
4179 
4180 #ifdef MNG_NO_1_2_4BIT_SUPPORT
4181   if (pData->iBitdepth < 8)
4182     pData->iBitdepth = 8;
4183 #endif
4184 #ifdef MNG_NO_16BIT_SUPPORT
4185   if (pData->iBitdepth > 8)
4186     {
4187       pData->iBitdepth = 8;
4188       pData->iPNGmult = 2;
4189     }
4190 #endif
4191 
4192   if ((pData->iBitdepth !=  8)      /* parameter validity checks */
4193 #ifndef MNG_NO_1_2_4BIT_SUPPORT
4194       && (pData->iBitdepth !=  1) &&
4195       (pData->iBitdepth !=  2) &&
4196       (pData->iBitdepth !=  4)
4197 #endif
4198 #ifndef MNG_NO_16BIT_SUPPORT
4199       && (pData->iBitdepth != 16)
4200 #endif
4201       )
4202     MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
4203 
4204   if ((pData->iColortype != MNG_COLORTYPE_GRAY   ) &&
4205       (pData->iColortype != MNG_COLORTYPE_RGB    ) &&
4206       (pData->iColortype != MNG_COLORTYPE_INDEXED) &&
4207       (pData->iColortype != MNG_COLORTYPE_GRAYA  ) &&
4208       (pData->iColortype != MNG_COLORTYPE_RGBA   )    )
4209     MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
4210 
4211   if ((pData->iColortype == MNG_COLORTYPE_INDEXED) && (pData->iBitdepth > 8))
4212     MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
4213 
4214   if (((pData->iColortype == MNG_COLORTYPE_RGB    ) ||
4215        (pData->iColortype == MNG_COLORTYPE_GRAYA  ) ||
4216        (pData->iColortype == MNG_COLORTYPE_RGBA   )    ) &&
4217       (pData->iBitdepth < 8                            )    )
4218     MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
4219 
4220   if (pData->iCompression != MNG_COMPRESSION_DEFLATE)
4221     MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
4222 
4223 #if defined(FILTER192) || defined(FILTER193)
4224   if ((pData->iFilter != MNG_FILTER_ADAPTIVE ) &&
4225 #if defined(FILTER192) && defined(FILTER193)
4226       (pData->iFilter != MNG_FILTER_DIFFERING) &&
4227       (pData->iFilter != MNG_FILTER_NOFILTER )    )
4228 #else
4229 #ifdef FILTER192
4230       (pData->iFilter != MNG_FILTER_DIFFERING)    )
4231 #else
4232       (pData->iFilter != MNG_FILTER_NOFILTER )    )
4233 #endif
4234 #endif
4235     MNG_ERROR (pData, MNG_INVALIDFILTER);
4236 #else
4237   if (pData->iFilter)
4238     MNG_ERROR (pData, MNG_INVALIDFILTER);
4239 #endif
4240 
4241   if ((pData->iInterlace != MNG_INTERLACE_NONE ) &&
4242       (pData->iInterlace != MNG_INTERLACE_ADAM7)    )
4243     MNG_ERROR (pData, MNG_INVALIDINTERLACE);
4244 
4245   pData->iImagelevel++;                /* one level deeper */
4246 
4247 #ifdef MNG_SUPPORT_DISPLAY
4248   {
4249     mng_uint16  iRed      = 0;
4250     mng_uint16  iGreen    = 0;
4251     mng_uint16  iBlue     = 0;
4252     mng_bool    bHasalpha = MNG_FALSE;
4253     mng_uint16  iAlpha    = 0xFFFF;
4254     mng_uint8   iViewable = 0;
4255     mng_retcode iRetcode;
4256 
4257     if (iRawlen > 13)                  /* get remaining fields, if any */
4258     {
4259       iRed      = mng_get_uint16 (pRawdata+13);
4260       iGreen    = mng_get_uint16 (pRawdata+15);
4261       iBlue     = mng_get_uint16 (pRawdata+17);
4262     }
4263 
4264     if (iRawlen > 19)
4265     {
4266       bHasalpha = MNG_TRUE;
4267       iAlpha    = mng_get_uint16 (pRawdata+19);
4268     }
4269 
4270     if (iRawlen > 21)
4271       iViewable = *(pRawdata+21);
4272                                        /* create an animation object */
4273     iRetcode = mng_create_ani_basi (pData, iRed, iGreen, iBlue,
4274                                     bHasalpha, iAlpha, iViewable);
4275 
4276 /*    if (!iRetcode)
4277       iRetcode = mng_process_display_basi (pData, iRed, iGreen, iBlue,
4278                                            bHasalpha, iAlpha, iViewable); */
4279 
4280     if (iRetcode)                      /* on error bail out */
4281       return iRetcode;
4282 
4283   }
4284 #endif /* MNG_SUPPORT_DISPLAY */
4285 
4286 #ifdef MNG_STORE_CHUNKS
4287   if (pData->bStorechunks)
4288   {                                    /* initialize storage */
4289     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
4290 
4291     if (iRetcode)                      /* on error bail out */
4292       return iRetcode;
4293                                        /* store the fields */
4294     ((mng_basip)*ppChunk)->iWidth       = mng_get_uint32 (pRawdata);
4295     ((mng_basip)*ppChunk)->iHeight      = mng_get_uint32 (pRawdata+4);
4296 #ifdef MNG_NO_16BIT_SUPPORT
4297     if (*(pRawdata+8) > 8)
4298       ((mng_basip)*ppChunk)->iBitdepth    = 8;
4299     else
4300 #endif
4301       ((mng_basip)*ppChunk)->iBitdepth    = *(pRawdata+8);
4302     ((mng_basip)*ppChunk)->iColortype   = *(pRawdata+9);
4303     ((mng_basip)*ppChunk)->iCompression = *(pRawdata+10);
4304     ((mng_basip)*ppChunk)->iFilter      = *(pRawdata+11);
4305     ((mng_basip)*ppChunk)->iInterlace   = *(pRawdata+12);
4306 
4307     if (iRawlen > 13)
4308     {
4309       ((mng_basip)*ppChunk)->iRed       = mng_get_uint16 (pRawdata+13);
4310       ((mng_basip)*ppChunk)->iGreen     = mng_get_uint16 (pRawdata+15);
4311       ((mng_basip)*ppChunk)->iBlue      = mng_get_uint16 (pRawdata+17);
4312     }
4313 
4314     if (iRawlen > 19)
4315       ((mng_basip)*ppChunk)->iAlpha     = mng_get_uint16 (pRawdata+19);
4316 
4317     if (iRawlen > 21)
4318       ((mng_basip)*ppChunk)->iViewable  = *(pRawdata+21);
4319 
4320   }
4321 #endif /* MNG_STORE_CHUNKS */
4322 
4323 #ifdef MNG_SUPPORT_TRACE
4324   MNG_TRACE (pData, MNG_FN_READ_BASI, MNG_LC_END);
4325 #endif
4326 
4327   return MNG_NOERROR;                  /* done */
4328 }
4329 #endif
4330 #endif
4331 
4332 /* ************************************************************************** */
4333 
4334 #ifndef MNG_OPTIMIZE_CHUNKREADER
4335 #ifndef MNG_SKIPCHUNK_CLON
READ_CHUNK(mng_read_clon)4336 READ_CHUNK (mng_read_clon)
4337 {
4338 #ifdef MNG_SUPPORT_TRACE
4339   MNG_TRACE (pData, MNG_FN_READ_CLON, MNG_LC_START);
4340 #endif
4341 
4342   if (!pData->bHasMHDR)                /* sequence checks */
4343     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4344 
4345 #ifdef MNG_INCLUDE_JNG
4346   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
4347 #else
4348   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
4349 #endif
4350     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4351                                        /* check the length */
4352   if ((iRawlen != 4) && (iRawlen != 5) && (iRawlen != 6) &&
4353       (iRawlen != 7) && (iRawlen != 16))
4354     MNG_ERROR (pData, MNG_INVALIDLENGTH);
4355 
4356 #ifdef MNG_SUPPORT_DISPLAY
4357   {
4358     mng_uint16  iSourceid, iCloneid;
4359     mng_uint8   iClonetype    = 0;
4360     mng_bool    bHasdonotshow = MNG_FALSE;
4361     mng_uint8   iDonotshow    = 0;
4362     mng_uint8   iConcrete     = 0;
4363     mng_bool    bHasloca      = MNG_FALSE;
4364     mng_uint8   iLocationtype = 0;
4365     mng_int32   iLocationx    = 0;
4366     mng_int32   iLocationy    = 0;
4367     mng_retcode iRetcode;
4368 
4369     iSourceid       = mng_get_uint16 (pRawdata);
4370     iCloneid        = mng_get_uint16 (pRawdata+2);
4371 
4372     if (iRawlen > 4)
4373       iClonetype    = *(pRawdata+4);
4374 
4375     if (iRawlen > 5)
4376     {
4377       bHasdonotshow = MNG_TRUE;
4378       iDonotshow    = *(pRawdata+5);
4379     }
4380 
4381     if (iRawlen > 6)
4382       iConcrete     = *(pRawdata+6);
4383 
4384     if (iRawlen > 7)
4385     {
4386       bHasloca      = MNG_TRUE;
4387       iLocationtype = *(pRawdata+7);
4388       iLocationx    = mng_get_int32 (pRawdata+8);
4389       iLocationy    = mng_get_int32 (pRawdata+12);
4390     }
4391 
4392     iRetcode = mng_create_ani_clon (pData, iSourceid, iCloneid, iClonetype,
4393                                     bHasdonotshow, iDonotshow, iConcrete,
4394                                     bHasloca, iLocationtype, iLocationx, iLocationy);
4395 
4396 /*    if (!iRetcode)
4397       iRetcode = mng_process_display_clon (pData, iSourceid, iCloneid, iClonetype,
4398                                            bHasdonotshow, iDonotshow, iConcrete,
4399                                            bHasloca, iLocationtype, iLocationx,
4400                                            iLocationy); */
4401 
4402     if (iRetcode)                      /* on error bail out */
4403       return iRetcode;
4404 
4405   }
4406 #endif /* MNG_SUPPORT_DISPLAY */
4407 
4408 #ifdef MNG_STORE_CHUNKS
4409   if (pData->bStorechunks)
4410   {                                    /* initialize storage */
4411     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
4412 
4413     if (iRetcode)                      /* on error bail out */
4414       return iRetcode;
4415                                        /* store the fields */
4416     ((mng_clonp)*ppChunk)->iSourceid       = mng_get_uint16 (pRawdata);
4417     ((mng_clonp)*ppChunk)->iCloneid        = mng_get_uint16 (pRawdata+2);
4418 
4419     if (iRawlen > 4)
4420       ((mng_clonp)*ppChunk)->iClonetype    = *(pRawdata+4);
4421 
4422     if (iRawlen > 5)
4423       ((mng_clonp)*ppChunk)->iDonotshow    = *(pRawdata+5);
4424 
4425     if (iRawlen > 6)
4426       ((mng_clonp)*ppChunk)->iConcrete     = *(pRawdata+6);
4427 
4428     if (iRawlen > 7)
4429     {
4430       ((mng_clonp)*ppChunk)->bHasloca      = MNG_TRUE;
4431       ((mng_clonp)*ppChunk)->iLocationtype = *(pRawdata+7);
4432       ((mng_clonp)*ppChunk)->iLocationx    = mng_get_int32 (pRawdata+8);
4433       ((mng_clonp)*ppChunk)->iLocationy    = mng_get_int32 (pRawdata+12);
4434     }
4435     else
4436     {
4437       ((mng_clonp)*ppChunk)->bHasloca      = MNG_FALSE;
4438     }
4439   }
4440 #endif /* MNG_STORE_CHUNKS */
4441 
4442 #ifdef MNG_SUPPORT_TRACE
4443   MNG_TRACE (pData, MNG_FN_READ_CLON, MNG_LC_END);
4444 #endif
4445 
4446   return MNG_NOERROR;                  /* done */
4447 }
4448 #endif
4449 #endif
4450 
4451 /* ************************************************************************** */
4452 
4453 #ifndef MNG_OPTIMIZE_CHUNKREADER
4454 #ifndef MNG_SKIPCHUNK_PAST
READ_CHUNK(mng_read_past)4455 READ_CHUNK (mng_read_past)
4456 {
4457 #if defined(MNG_STORE_CHUNKS) || defined(MNG_SUPPORT_DISPLAY)
4458   mng_retcode      iRetcode;
4459   mng_uint16       iTargetid;
4460   mng_uint8        iTargettype;
4461   mng_int32        iTargetx;
4462   mng_int32        iTargety;
4463   mng_uint32       iCount;
4464   mng_uint32       iSize;
4465   mng_ptr          pSources;
4466   mng_uint32       iX;
4467   mng_past_sourcep pSource;
4468 #endif
4469 
4470 #ifdef MNG_SUPPORT_TRACE
4471   MNG_TRACE (pData, MNG_FN_READ_PAST, MNG_LC_START);
4472 #endif
4473 
4474   if (!pData->bHasMHDR)                /* sequence checks */
4475     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4476 
4477 #ifdef MNG_INCLUDE_JNG
4478   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
4479 #else
4480   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
4481 #endif
4482     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4483 
4484                                        /* check the length */
4485   if ((iRawlen < 41) || (((iRawlen - 11) % 30) != 0))
4486     MNG_ERROR (pData, MNG_INVALIDLENGTH);
4487 
4488 #if defined(MNG_STORE_CHUNKS) || defined(MNG_SUPPORT_DISPLAY)
4489   iTargetid   = mng_get_uint16 (pRawdata);
4490   iTargettype = *(pRawdata+2);
4491   iTargetx    = mng_get_int32  (pRawdata+3);
4492   iTargety    = mng_get_int32  (pRawdata+7);
4493   iCount      = ((iRawlen - 11) / 30); /* how many entries again? */
4494   iSize       = iCount * sizeof (mng_past_source);
4495 
4496   pRawdata += 11;
4497                                        /* get a buffer for all the source blocks */
4498   MNG_ALLOC (pData, pSources, iSize);
4499 
4500   pSource = (mng_past_sourcep)pSources;
4501 
4502   for (iX = 0; iX < iCount; iX++)      /* now copy the source blocks */
4503   {
4504     pSource->iSourceid     = mng_get_uint16 (pRawdata);
4505     pSource->iComposition  = *(pRawdata+2);
4506     pSource->iOrientation  = *(pRawdata+3);
4507     pSource->iOffsettype   = *(pRawdata+4);
4508     pSource->iOffsetx      = mng_get_int32 (pRawdata+5);
4509     pSource->iOffsety      = mng_get_int32 (pRawdata+9);
4510     pSource->iBoundarytype = *(pRawdata+13);
4511     pSource->iBoundaryl    = mng_get_int32 (pRawdata+14);
4512     pSource->iBoundaryr    = mng_get_int32 (pRawdata+18);
4513     pSource->iBoundaryt    = mng_get_int32 (pRawdata+22);
4514     pSource->iBoundaryb    = mng_get_int32 (pRawdata+26);
4515 
4516     pSource++;
4517     pRawdata += 30;
4518   }
4519 #endif
4520 
4521 #ifdef MNG_SUPPORT_DISPLAY
4522   {                                    /* create playback object */
4523     iRetcode = mng_create_ani_past (pData, iTargetid, iTargettype, iTargetx,
4524                                     iTargety, iCount, pSources);
4525 
4526 /*    if (!iRetcode)
4527       iRetcode = mng_process_display_past (pData, iTargetid, iTargettype, iTargetx,
4528                                            iTargety, iCount, pSources); */
4529 
4530     if (iRetcode)                      /* on error bail out */
4531     {
4532       MNG_FREEX (pData, pSources, iSize);
4533       return iRetcode;
4534     }
4535   }
4536 #endif /* MNG_SUPPORT_DISPLAY */
4537 
4538 #ifdef MNG_STORE_CHUNKS
4539   if (pData->bStorechunks)
4540   {                                    /* initialize storage */
4541     iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
4542 
4543     if (iRetcode)                      /* on error bail out */
4544     {
4545       MNG_FREEX (pData, pSources, iSize);
4546       return iRetcode;
4547     }
4548                                        /* store the fields */
4549     ((mng_pastp)*ppChunk)->iDestid     = iTargetid;
4550     ((mng_pastp)*ppChunk)->iTargettype = iTargettype;
4551     ((mng_pastp)*ppChunk)->iTargetx    = iTargetx;
4552     ((mng_pastp)*ppChunk)->iTargety    = iTargety;
4553     ((mng_pastp)*ppChunk)->iCount      = iCount;
4554                                        /* get a buffer & copy the source blocks */
4555     MNG_ALLOC (pData, ((mng_pastp)*ppChunk)->pSources, iSize);
4556     MNG_COPY (((mng_pastp)*ppChunk)->pSources, pSources, iSize);
4557   }
4558 #endif /* MNG_STORE_CHUNKS */
4559 
4560 #if defined(MNG_STORE_CHUNKS) || defined(MNG_SUPPORT_DISPLAY)
4561                                        /* free the source block buffer */
4562   MNG_FREEX (pData, pSources, iSize);
4563 #endif
4564 
4565 #ifdef MNG_SUPPORT_TRACE
4566   MNG_TRACE (pData, MNG_FN_READ_PAST, MNG_LC_END);
4567 #endif
4568 
4569   return MNG_NOERROR;                  /* done */
4570 }
4571 #endif
4572 #endif
4573 
4574 /* ************************************************************************** */
4575 
4576 #ifndef MNG_OPTIMIZE_CHUNKREADER
4577 #ifndef MNG_SKIPCHUNK_DISC
READ_CHUNK(mng_read_disc)4578 READ_CHUNK (mng_read_disc)
4579 {
4580 #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
4581   mng_uint32  iCount;
4582   mng_uint16p pIds = MNG_NULL;
4583   mng_retcode iRetcode;
4584 #endif
4585 
4586 #ifdef MNG_SUPPORT_TRACE
4587   MNG_TRACE (pData, MNG_FN_READ_DISC, MNG_LC_START);
4588 #endif
4589 
4590   if (!pData->bHasMHDR)                /* sequence checks */
4591     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4592 
4593 #ifdef MNG_INCLUDE_JNG
4594   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
4595 #else
4596   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
4597 #endif
4598     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4599 
4600   if ((iRawlen % 2) != 0)              /* check the length */
4601     MNG_ERROR (pData, MNG_INVALIDLENGTH);
4602 
4603 #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
4604   iCount = (iRawlen / sizeof (mng_uint16));
4605 
4606   if (iCount)
4607   {
4608     MNG_ALLOC (pData, pIds, iRawlen);
4609 
4610 #ifndef MNG_BIGENDIAN_SUPPORTED
4611     {
4612       mng_uint32  iX;
4613       mng_uint8p  pIn  = pRawdata;
4614       mng_uint16p pOut = pIds;
4615 
4616       for (iX = 0; iX < iCount; iX++)
4617       {
4618         *pOut++ = mng_get_uint16 (pIn);
4619         pIn += 2;
4620       }
4621     }
4622 #else
4623     MNG_COPY (pIds, pRawdata, iRawlen);
4624 #endif /* !MNG_BIGENDIAN_SUPPORTED */
4625   }
4626 #endif
4627 
4628 #ifdef MNG_SUPPORT_DISPLAY
4629   {                                    /* create playback object */
4630     iRetcode = mng_create_ani_disc (pData, iCount, pIds);
4631 
4632 /*    if (!iRetcode)
4633       iRetcode = mng_process_display_disc (pData, iCount, pIds); */
4634 
4635     if (iRetcode)                      /* on error bail out */
4636       return iRetcode;
4637   }
4638 #endif /* MNG_SUPPORT_DISPLAY */
4639 
4640 #ifdef MNG_STORE_CHUNKS
4641   if (pData->bStorechunks)
4642   {                                    /* initialize storage */
4643     iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
4644 
4645     if (iRetcode)                      /* on error bail out */
4646       return iRetcode;
4647                                        /* store the fields */
4648     ((mng_discp)*ppChunk)->iCount = iCount;
4649 
4650     if (iRawlen)
4651     {
4652       MNG_ALLOC (pData, ((mng_discp)*ppChunk)->pObjectids, iRawlen);
4653       MNG_COPY (((mng_discp)*ppChunk)->pObjectids, pIds, iRawlen);
4654     }
4655   }
4656 #endif /* MNG_STORE_CHUNKS */
4657 
4658 #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
4659   if (iRawlen)
4660     MNG_FREEX (pData, pIds, iRawlen);
4661 #endif
4662 
4663 #ifdef MNG_SUPPORT_TRACE
4664   MNG_TRACE (pData, MNG_FN_READ_DISC, MNG_LC_END);
4665 #endif
4666 
4667   return MNG_NOERROR;                  /* done */
4668 }
4669 #endif
4670 #endif
4671 
4672 /* ************************************************************************** */
4673 
4674 #ifndef MNG_OPTIMIZE_CHUNKREADER
4675 #ifndef MNG_SKIPCHUNK_BACK
READ_CHUNK(mng_read_back)4676 READ_CHUNK (mng_read_back)
4677 {
4678 #ifdef MNG_SUPPORT_TRACE
4679   MNG_TRACE (pData, MNG_FN_READ_BACK, MNG_LC_START);
4680 #endif
4681 
4682   if (!pData->bHasMHDR)                /* sequence checks */
4683     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4684 
4685 #ifdef MNG_INCLUDE_JNG
4686   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
4687 #else
4688   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
4689 #endif
4690     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4691                                        /* check the length */
4692   if ((iRawlen != 6) && (iRawlen != 7) && (iRawlen != 9) && (iRawlen != 10))
4693     MNG_ERROR (pData, MNG_INVALIDLENGTH);
4694 
4695 #ifdef MNG_SUPPORT_DISPLAY
4696   {
4697     mng_retcode iRetcode;
4698                                        /* retrieve the fields */
4699     pData->bHasBACK         = MNG_TRUE;
4700     pData->iBACKred         = mng_get_uint16 (pRawdata);
4701     pData->iBACKgreen       = mng_get_uint16 (pRawdata+2);
4702     pData->iBACKblue        = mng_get_uint16 (pRawdata+4);
4703 
4704     if (iRawlen > 6)
4705       pData->iBACKmandatory = *(pRawdata+6);
4706     else
4707       pData->iBACKmandatory = 0;
4708 
4709     if (iRawlen > 7)
4710       pData->iBACKimageid   = mng_get_uint16 (pRawdata+7);
4711     else
4712       pData->iBACKimageid   = 0;
4713 
4714     if (iRawlen > 9)
4715       pData->iBACKtile      = *(pRawdata+9);
4716     else
4717       pData->iBACKtile      = 0;
4718 
4719     iRetcode = mng_create_ani_back (pData, pData->iBACKred, pData->iBACKgreen,
4720                                     pData->iBACKblue, pData->iBACKmandatory,
4721                                     pData->iBACKimageid, pData->iBACKtile);
4722 
4723     if (iRetcode)                    /* on error bail out */
4724       return iRetcode;
4725   }
4726 #endif /* MNG_SUPPORT_DISPLAY */
4727 
4728 #ifdef MNG_STORE_CHUNKS
4729   if (pData->bStorechunks)
4730   {                                    /* initialize storage */
4731     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
4732 
4733     if (iRetcode)                      /* on error bail out */
4734       return iRetcode;
4735                                        /* store the fields */
4736     ((mng_backp)*ppChunk)->iRed         = mng_get_uint16 (pRawdata);
4737     ((mng_backp)*ppChunk)->iGreen       = mng_get_uint16 (pRawdata+2);
4738     ((mng_backp)*ppChunk)->iBlue        = mng_get_uint16 (pRawdata+4);
4739 
4740     if (iRawlen > 6)
4741       ((mng_backp)*ppChunk)->iMandatory = *(pRawdata+6);
4742 
4743     if (iRawlen > 7)
4744       ((mng_backp)*ppChunk)->iImageid   = mng_get_uint16 (pRawdata+7);
4745 
4746     if (iRawlen > 9)
4747       ((mng_backp)*ppChunk)->iTile      = *(pRawdata+9);
4748 
4749   }
4750 #endif /* MNG_STORE_CHUNKS */
4751 
4752 #ifdef MNG_SUPPORT_TRACE
4753   MNG_TRACE (pData, MNG_FN_READ_BACK, MNG_LC_END);
4754 #endif
4755 
4756   return MNG_NOERROR;                  /* done */
4757 }
4758 #endif
4759 #endif
4760 
4761 /* ************************************************************************** */
4762 
4763 #ifndef MNG_OPTIMIZE_CHUNKREADER
4764 #ifndef MNG_SKIPCHUNK_FRAM
READ_CHUNK(mng_read_fram)4765 READ_CHUNK (mng_read_fram)
4766 {
4767   mng_uint8p pTemp;
4768 #ifdef MNG_STORE_CHUNKS
4769   mng_uint32 iNamelen;
4770 #endif
4771   mng_uint32 iRemain;
4772   mng_uint32 iRequired = 0;
4773 
4774 #ifdef MNG_SUPPORT_TRACE
4775   MNG_TRACE (pData, MNG_FN_READ_FRAM, MNG_LC_START);
4776 #endif
4777 
4778   if (!pData->bHasMHDR)                /* sequence checks */
4779     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4780 
4781 #ifdef MNG_INCLUDE_JNG
4782   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
4783 #else
4784   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
4785 #endif
4786     MNG_ERROR (pData, MNG_SEQUENCEERROR);
4787 
4788   if (iRawlen <= 1)                    /* only framing-mode ? */
4789   {
4790 #ifdef MNG_STORE_CHUNKS
4791     iNamelen = 0;                      /* indicate so */
4792 #endif
4793     iRemain  = 0;
4794     pTemp    = MNG_NULL;
4795   }
4796   else
4797   {
4798     pTemp = find_null (pRawdata+1);    /* find null-separator */
4799                                        /* not found inside input-data ? */
4800     if ((pTemp - pRawdata) > (mng_int32)iRawlen)
4801       pTemp  = pRawdata + iRawlen;     /* than remainder is name */
4802 
4803 #ifdef MNG_STORE_CHUNKS
4804     iNamelen = (mng_uint32)((pTemp - pRawdata) - 1);
4805 #endif
4806     iRemain  = (mng_uint32)(iRawlen - (pTemp - pRawdata));
4807 
4808     if (iRemain)                       /* if there is remaining data it's less 1 byte */
4809       iRemain--;
4810 
4811     if ((iRemain) && (iRemain < 4))    /* remains must be empty or at least 4 bytes */
4812       MNG_ERROR (pData, MNG_INVALIDLENGTH);
4813 
4814     if (iRemain)
4815     {
4816       iRequired = 4;                   /* calculate and check required remaining length */
4817 
4818       if (*(pTemp+1)) { iRequired += 4; }
4819       if (*(pTemp+2)) { iRequired += 4; }
4820       if (*(pTemp+3)) { iRequired += 17; }
4821 
4822       if (*(pTemp+4))
4823       {
4824         if ((iRemain - iRequired) % 4 != 0)
4825           MNG_ERROR (pData, MNG_INVALIDLENGTH);
4826       }
4827       else
4828       {
4829         if (iRemain != iRequired)
4830           MNG_ERROR (pData, MNG_INVALIDLENGTH);
4831       }
4832     }
4833   }
4834 
4835 #ifdef MNG_SUPPORT_DISPLAY
4836   {
4837     mng_uint8p  pWork           = pTemp;
4838     mng_uint8   iFramemode      = 0;
4839     mng_uint8   iChangedelay    = 0;
4840     mng_uint32  iDelay          = 0;
4841     mng_uint8   iChangetimeout  = 0;
4842     mng_uint32  iTimeout        = 0;
4843     mng_uint8   iChangeclipping = 0;
4844     mng_uint8   iCliptype       = 0;
4845     mng_int32   iClipl          = 0;
4846     mng_int32   iClipr          = 0;
4847     mng_int32   iClipt          = 0;
4848     mng_int32   iClipb          = 0;
4849     mng_retcode iRetcode;
4850 
4851     if (iRawlen)                       /* any data specified ? */
4852     {
4853       if (*(pRawdata))                 /* save the new framing mode ? */
4854       {
4855         iFramemode = *(pRawdata);
4856 
4857 #ifndef MNG_NO_OLD_VERSIONS
4858         if (pData->bPreDraft48)        /* old style input-stream ? */
4859         {
4860           switch (iFramemode)
4861           {
4862             case  0: { break; }
4863             case  1: { iFramemode = 3; break; }
4864             case  2: { iFramemode = 4; break; }
4865             case  3: { iFramemode = 1; break; }
4866             case  4: { iFramemode = 1; break; }
4867             case  5: { iFramemode = 2; break; }
4868             default: { iFramemode = 1; break; }
4869           }
4870         }
4871 #endif
4872       }
4873 
4874       if (iRemain)
4875       {
4876         iChangedelay    = *(pWork+1);
4877         iChangetimeout  = *(pWork+2);
4878         iChangeclipping = *(pWork+3);
4879         pWork += 5;
4880 
4881         if (iChangedelay)              /* delay changed ? */
4882         {
4883           iDelay = mng_get_uint32 (pWork);
4884           pWork += 4;
4885         }
4886 
4887         if (iChangetimeout)            /* timeout changed ? */
4888         {
4889           iTimeout = mng_get_uint32 (pWork);
4890           pWork += 4;
4891         }
4892 
4893         if (iChangeclipping)           /* clipping changed ? */
4894         {
4895           iCliptype = *pWork;
4896           iClipl    = mng_get_int32 (pWork+1);
4897           iClipr    = mng_get_int32 (pWork+5);
4898           iClipt    = mng_get_int32 (pWork+9);
4899           iClipb    = mng_get_int32 (pWork+13);
4900         }
4901       }
4902     }
4903 
4904     iRetcode = mng_create_ani_fram (pData, iFramemode, iChangedelay, iDelay,
4905                                     iChangetimeout, iTimeout,
4906                                     iChangeclipping, iCliptype,
4907                                     iClipl, iClipr, iClipt, iClipb);
4908 
4909 /*    if (!iRetcode)
4910       iRetcode = mng_process_display_fram (pData, iFramemode, iChangedelay, iDelay,
4911                                            iChangetimeout, iTimeout,
4912                                            iChangeclipping, iCliptype,
4913                                            iClipl, iClipr, iClipt, iClipb); */
4914 
4915     if (iRetcode)                      /* on error bail out */
4916       return iRetcode;
4917 
4918   }
4919 #endif /* MNG_SUPPORT_DISPLAY */
4920 
4921 #ifdef MNG_STORE_CHUNKS
4922   if (pData->bStorechunks)
4923   {                                    /* initialize storage */
4924     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
4925 
4926     if (iRetcode)                      /* on error bail out */
4927       return iRetcode;
4928                                        /* store the fields */
4929     ((mng_framp)*ppChunk)->bEmpty              = (mng_bool)(iRawlen == 0);
4930 
4931     if (iRawlen)
4932     {
4933       mng_uint8 iFramemode = *(pRawdata);
4934 
4935 #ifndef MNG_NO_OLD_VERSIONS
4936       if (pData->bPreDraft48)          /* old style input-stream ? */
4937       {
4938         switch (iFramemode)
4939         {
4940           case  1: { iFramemode = 3; break; }
4941           case  2: { iFramemode = 4; break; }
4942           case  3: { iFramemode = 5; break; }    /* TODO: provision for mode=5 ??? */
4943           case  4: { iFramemode = 1; break; }
4944           case  5: { iFramemode = 2; break; }
4945           default: { iFramemode = 1; break; }
4946         }
4947       }
4948 #endif
4949 
4950       ((mng_framp)*ppChunk)->iMode             = iFramemode;
4951       ((mng_framp)*ppChunk)->iNamesize         = iNamelen;
4952 
4953       if (iNamelen)
4954       {
4955         MNG_ALLOC (pData, ((mng_framp)*ppChunk)->zName, iNamelen+1);
4956         MNG_COPY (((mng_framp)*ppChunk)->zName, pRawdata+1, iNamelen);
4957       }
4958 
4959       if (iRemain)
4960       {
4961         ((mng_framp)*ppChunk)->iChangedelay    = *(pTemp+1);
4962         ((mng_framp)*ppChunk)->iChangetimeout  = *(pTemp+2);
4963         ((mng_framp)*ppChunk)->iChangeclipping = *(pTemp+3);
4964         ((mng_framp)*ppChunk)->iChangesyncid   = *(pTemp+4);
4965 
4966         pTemp += 5;
4967 
4968         if (((mng_framp)*ppChunk)->iChangedelay)
4969         {
4970           ((mng_framp)*ppChunk)->iDelay        = mng_get_uint32 (pTemp);
4971           pTemp += 4;
4972         }
4973 
4974         if (((mng_framp)*ppChunk)->iChangetimeout)
4975         {
4976           ((mng_framp)*ppChunk)->iTimeout      = mng_get_uint32 (pTemp);
4977           pTemp += 4;
4978         }
4979 
4980         if (((mng_framp)*ppChunk)->iChangeclipping)
4981         {
4982           ((mng_framp)*ppChunk)->iBoundarytype = *pTemp;
4983           ((mng_framp)*ppChunk)->iBoundaryl    = mng_get_int32 (pTemp+1);
4984           ((mng_framp)*ppChunk)->iBoundaryr    = mng_get_int32 (pTemp+5);
4985           ((mng_framp)*ppChunk)->iBoundaryt    = mng_get_int32 (pTemp+9);
4986           ((mng_framp)*ppChunk)->iBoundaryb    = mng_get_int32 (pTemp+13);
4987           pTemp += 17;
4988         }
4989 
4990         if (((mng_framp)*ppChunk)->iChangesyncid)
4991         {
4992           ((mng_framp)*ppChunk)->iCount        = (iRemain - iRequired) / 4;
4993 
4994           if (((mng_framp)*ppChunk)->iCount)
4995           {
4996             MNG_ALLOC (pData, ((mng_framp)*ppChunk)->pSyncids,
4997                               ((mng_framp)*ppChunk)->iCount * 4);
4998 
4999 #ifndef MNG_BIGENDIAN_SUPPORTED
5000             {
5001               mng_uint32 iX;
5002               mng_uint32p pOut = ((mng_framp)*ppChunk)->pSyncids;
5003 
5004               for (iX = 0; iX < ((mng_framp)*ppChunk)->iCount; iX++)
5005               {
5006                 *pOut++ = mng_get_uint32 (pTemp);
5007                 pTemp += 4;
5008               }
5009             }
5010 #else
5011             MNG_COPY (((mng_framp)*ppChunk)->pSyncids, pTemp,
5012                       ((mng_framp)*ppChunk)->iCount * 4);
5013 #endif /* !MNG_BIGENDIAN_SUPPORTED */
5014           }
5015         }
5016       }
5017     }
5018   }
5019 #endif /* MNG_STORE_CHUNKS */
5020 
5021 #ifdef MNG_SUPPORT_TRACE
5022   MNG_TRACE (pData, MNG_FN_READ_FRAM, MNG_LC_END);
5023 #endif
5024 
5025   return MNG_NOERROR;                  /* done */
5026 }
5027 #endif
5028 #endif
5029 
5030 /* ************************************************************************** */
5031 
5032 #ifndef MNG_OPTIMIZE_CHUNKREADER
5033 #ifndef MNG_SKIPCHUNK_MOVE
READ_CHUNK(mng_read_move)5034 READ_CHUNK (mng_read_move)
5035 {
5036 #ifdef MNG_SUPPORT_TRACE
5037   MNG_TRACE (pData, MNG_FN_READ_MOVE, MNG_LC_START);
5038 #endif
5039 
5040   if (!pData->bHasMHDR)                /* sequence checks */
5041     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5042 
5043 #ifdef MNG_INCLUDE_JNG
5044   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
5045 #else
5046   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
5047 #endif
5048     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5049 
5050   if (iRawlen != 13)                   /* check the length */
5051     MNG_ERROR (pData, MNG_INVALIDLENGTH);
5052 
5053 #ifdef MNG_SUPPORT_DISPLAY
5054   {
5055     mng_retcode iRetcode;
5056                                        /* create a MOVE animation object */
5057     iRetcode = mng_create_ani_move (pData, mng_get_uint16 (pRawdata),
5058                                            mng_get_uint16 (pRawdata+2),
5059                                            *(pRawdata+4),
5060                                            mng_get_int32 (pRawdata+5),
5061                                            mng_get_int32 (pRawdata+9));
5062 
5063 /*    if (!iRetcode)
5064       iRetcode = mng_process_display_move (pData,
5065                                            mng_get_uint16 (pRawdata),
5066                                            mng_get_uint16 (pRawdata+2),
5067                                            *(pRawdata+4),
5068                                            mng_get_int32 (pRawdata+5),
5069                                            mng_get_int32 (pRawdata+9)); */
5070 
5071     if (iRetcode)                      /* on error bail out */
5072       return iRetcode;
5073 
5074   }
5075 #endif /* MNG_SUPPORT_DISPLAY */
5076 
5077 #ifdef MNG_STORE_CHUNKS
5078   if (pData->bStorechunks)
5079   {                                    /* initialize storage */
5080     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
5081 
5082     if (iRetcode)                      /* on error bail out */
5083       return iRetcode;
5084                                        /* store the fields */
5085     ((mng_movep)*ppChunk)->iFirstid  = mng_get_uint16 (pRawdata);
5086     ((mng_movep)*ppChunk)->iLastid   = mng_get_uint16 (pRawdata+2);
5087     ((mng_movep)*ppChunk)->iMovetype = *(pRawdata+4);
5088     ((mng_movep)*ppChunk)->iMovex    = mng_get_int32 (pRawdata+5);
5089     ((mng_movep)*ppChunk)->iMovey    = mng_get_int32 (pRawdata+9);
5090   }
5091 #endif /* MNG_STORE_CHUNKS */
5092 
5093 #ifdef MNG_SUPPORT_TRACE
5094   MNG_TRACE (pData, MNG_FN_READ_MOVE, MNG_LC_END);
5095 #endif
5096 
5097   return MNG_NOERROR;                  /* done */
5098 }
5099 #endif
5100 #endif
5101 
5102 /* ************************************************************************** */
5103 
5104 #ifndef MNG_OPTIMIZE_CHUNKREADER
5105 #ifndef MNG_SKIPCHUNK_CLIP
READ_CHUNK(mng_read_clip)5106 READ_CHUNK (mng_read_clip)
5107 {
5108 #ifdef MNG_SUPPORT_TRACE
5109   MNG_TRACE (pData, MNG_FN_READ_CLIP, MNG_LC_START);
5110 #endif
5111 
5112   if (!pData->bHasMHDR)                /* sequence checks */
5113     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5114 
5115 #ifdef MNG_INCLUDE_JNG
5116   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
5117 #else
5118   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
5119 #endif
5120     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5121 
5122   if (iRawlen != 21)                   /* check the length */
5123     MNG_ERROR (pData, MNG_INVALIDLENGTH);
5124 
5125 #ifdef MNG_SUPPORT_DISPLAY
5126   {
5127     mng_retcode iRetcode;
5128                                        /* create a CLIP animation object */
5129     iRetcode = mng_create_ani_clip (pData, mng_get_uint16 (pRawdata),
5130                                            mng_get_uint16 (pRawdata+2),
5131                                            *(pRawdata+4),
5132                                            mng_get_int32 (pRawdata+5),
5133                                            mng_get_int32 (pRawdata+9),
5134                                            mng_get_int32 (pRawdata+13),
5135                                            mng_get_int32 (pRawdata+17));
5136 
5137 /*    if (!iRetcode)
5138       iRetcode = mng_process_display_clip (pData,
5139                                            mng_get_uint16 (pRawdata),
5140                                            mng_get_uint16 (pRawdata+2),
5141                                            *(pRawdata+4),
5142                                            mng_get_int32 (pRawdata+5),
5143                                            mng_get_int32 (pRawdata+9),
5144                                            mng_get_int32 (pRawdata+13),
5145                                            mng_get_int32 (pRawdata+17)); */
5146 
5147     if (iRetcode)                      /* on error bail out */
5148       return iRetcode;
5149 
5150   }
5151 #endif /* MNG_SUPPORT_DISPLAY */
5152 
5153 #ifdef MNG_STORE_CHUNKS
5154   if (pData->bStorechunks)
5155   {                                    /* initialize storage */
5156     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
5157 
5158     if (iRetcode)                      /* on error bail out */
5159       return iRetcode;
5160                                        /* store the fields */
5161     ((mng_clipp)*ppChunk)->iFirstid  = mng_get_uint16 (pRawdata);
5162     ((mng_clipp)*ppChunk)->iLastid   = mng_get_uint16 (pRawdata+2);
5163     ((mng_clipp)*ppChunk)->iCliptype = *(pRawdata+4);
5164     ((mng_clipp)*ppChunk)->iClipl    = mng_get_int32 (pRawdata+5);
5165     ((mng_clipp)*ppChunk)->iClipr    = mng_get_int32 (pRawdata+9);
5166     ((mng_clipp)*ppChunk)->iClipt    = mng_get_int32 (pRawdata+13);
5167     ((mng_clipp)*ppChunk)->iClipb    = mng_get_int32 (pRawdata+17);
5168   }
5169 #endif /* MNG_STORE_CHUNKS */
5170 
5171 #ifdef MNG_SUPPORT_TRACE
5172   MNG_TRACE (pData, MNG_FN_READ_CLIP, MNG_LC_END);
5173 #endif
5174 
5175   return MNG_NOERROR;                  /* done */
5176 }
5177 #endif
5178 #endif
5179 
5180 /* ************************************************************************** */
5181 
5182 #ifndef MNG_OPTIMIZE_CHUNKREADER
5183 #ifndef MNG_SKIPCHUNK_SHOW
READ_CHUNK(mng_read_show)5184 READ_CHUNK (mng_read_show)
5185 {
5186 #ifdef MNG_SUPPORT_TRACE
5187   MNG_TRACE (pData, MNG_FN_READ_SHOW, MNG_LC_START);
5188 #endif
5189 
5190   if (!pData->bHasMHDR)                /* sequence checks */
5191     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5192 
5193 #ifdef MNG_INCLUDE_JNG
5194   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
5195 #else
5196   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
5197 #endif
5198     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5199                                        /* check the length */
5200   if ((iRawlen != 0) && (iRawlen != 2) && (iRawlen != 4) && (iRawlen != 5))
5201     MNG_ERROR (pData, MNG_INVALIDLENGTH);
5202 
5203 #ifdef MNG_SUPPORT_DISPLAY
5204   {
5205     mng_retcode iRetcode;
5206 
5207     if (iRawlen)                       /* determine parameters if any */
5208     {
5209       pData->iSHOWfromid = mng_get_uint16 (pRawdata);
5210 
5211       if (iRawlen > 2)
5212         pData->iSHOWtoid = mng_get_uint16 (pRawdata+2);
5213       else
5214         pData->iSHOWtoid = pData->iSHOWfromid;
5215 
5216       if (iRawlen > 4)
5217         pData->iSHOWmode = *(pRawdata+4);
5218       else
5219         pData->iSHOWmode = 0;
5220     }
5221     else                               /* use defaults then */
5222     {
5223       pData->iSHOWmode   = 2;
5224       pData->iSHOWfromid = 1;
5225       pData->iSHOWtoid   = 65535;
5226     }
5227                                        /* create a SHOW animation object */
5228     iRetcode = mng_create_ani_show (pData, pData->iSHOWfromid,
5229                                     pData->iSHOWtoid, pData->iSHOWmode);
5230 
5231     if (!iRetcode)
5232       iRetcode = mng_process_display_show (pData);
5233 
5234     if (iRetcode)                      /* on error bail out */
5235       return iRetcode;
5236 
5237   }
5238 #endif /* MNG_SUPPORT_DISPLAY */
5239 
5240 #ifdef MNG_STORE_CHUNKS
5241   if (pData->bStorechunks)
5242   {                                    /* initialize storage */
5243     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
5244 
5245     if (iRetcode)                      /* on error bail out */
5246       return iRetcode;
5247                                        /* store the fields */
5248     ((mng_showp)*ppChunk)->bEmpty      = (mng_bool)(iRawlen == 0);
5249 
5250     if (iRawlen)
5251     {
5252       ((mng_showp)*ppChunk)->iFirstid  = mng_get_uint16 (pRawdata);
5253 
5254       if (iRawlen > 2)
5255         ((mng_showp)*ppChunk)->iLastid = mng_get_uint16 (pRawdata+2);
5256       else
5257         ((mng_showp)*ppChunk)->iLastid = ((mng_showp)*ppChunk)->iFirstid;
5258 
5259       if (iRawlen > 4)
5260         ((mng_showp)*ppChunk)->iMode   = *(pRawdata+4);
5261     }
5262   }
5263 #endif /* MNG_STORE_CHUNKS */
5264 
5265 #ifdef MNG_SUPPORT_TRACE
5266   MNG_TRACE (pData, MNG_FN_READ_SHOW, MNG_LC_END);
5267 #endif
5268 
5269   return MNG_NOERROR;                  /* done */
5270 }
5271 #endif
5272 #endif
5273 
5274 /* ************************************************************************** */
5275 
5276 #ifndef MNG_OPTIMIZE_CHUNKREADER
5277 #ifndef MNG_SKIPCHUNK_TERM
READ_CHUNK(mng_read_term)5278 READ_CHUNK (mng_read_term)
5279 {
5280   mng_uint8   iTermaction;
5281   mng_uint8   iIteraction = 0;
5282   mng_uint32  iDelay      = 0;
5283   mng_uint32  iItermax    = 0;
5284 
5285 #ifdef MNG_SUPPORT_TRACE
5286   MNG_TRACE (pData, MNG_FN_READ_TERM, MNG_LC_START);
5287 #endif
5288 
5289   if (!pData->bHasMHDR)                /* sequence checks */
5290     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5291 
5292 #ifdef MNG_INCLUDE_JNG
5293   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
5294 #else
5295   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
5296 #endif
5297     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5298 
5299                                        /* should be behind MHDR or SAVE !! */
5300   if ((!pData->bHasSAVE) && (pData->iChunkseq > 2))
5301   {
5302     pData->bMisplacedTERM = MNG_TRUE;  /* indicate we found a misplaced TERM */
5303                                        /* and send a warning signal!!! */
5304     MNG_WARNING (pData, MNG_SEQUENCEERROR);
5305   }
5306 
5307   if (pData->bHasLOOP)                 /* no way, jose! */
5308     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5309 
5310   if (pData->bHasTERM)                 /* only 1 allowed! */
5311     MNG_ERROR (pData, MNG_MULTIPLEERROR);
5312                                        /* check the length */
5313   if ((iRawlen != 1) && (iRawlen != 10))
5314     MNG_ERROR (pData, MNG_INVALIDLENGTH);
5315 
5316   pData->bHasTERM = MNG_TRUE;
5317 
5318   iTermaction = *pRawdata;             /* get the fields */
5319 
5320   if (iRawlen > 1)
5321   {
5322     iIteraction = *(pRawdata+1);
5323     iDelay      = mng_get_uint32 (pRawdata+2);
5324     iItermax    = mng_get_uint32 (pRawdata+6);
5325   }
5326 
5327   if (pData->fProcessterm)             /* inform the app ? */
5328     if (!pData->fProcessterm (((mng_handle)pData), iTermaction, iIteraction,
5329                                                    iDelay, iItermax))
5330       MNG_ERROR (pData, MNG_APPMISCERROR);
5331 
5332 #ifdef MNG_SUPPORT_DISPLAY
5333   {                                    /* create the TERM ani-object */
5334     mng_retcode iRetcode = mng_create_ani_term (pData, iTermaction, iIteraction,
5335                                                 iDelay, iItermax);
5336 
5337     if (iRetcode)                      /* on error bail out */
5338       return iRetcode;
5339                                        /* save for future reference */
5340     pData->pTermaniobj = pData->pLastaniobj;
5341   }
5342 #endif /* MNG_SUPPORT_DISPLAY */
5343 
5344 #ifdef MNG_STORE_CHUNKS
5345   if (pData->bStorechunks)
5346   {                                    /* initialize storage */
5347     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
5348 
5349     if (iRetcode)                      /* on error bail out */
5350       return iRetcode;
5351                                        /* store the fields */
5352     ((mng_termp)*ppChunk)->iTermaction = iTermaction;
5353     ((mng_termp)*ppChunk)->iIteraction = iIteraction;
5354     ((mng_termp)*ppChunk)->iDelay      = iDelay;
5355     ((mng_termp)*ppChunk)->iItermax    = iItermax;
5356   }
5357 #endif /* MNG_STORE_CHUNKS */
5358 
5359 #ifdef MNG_SUPPORT_TRACE
5360   MNG_TRACE (pData, MNG_FN_READ_TERM, MNG_LC_END);
5361 #endif
5362 
5363   return MNG_NOERROR;                  /* done */
5364 }
5365 #endif
5366 #endif
5367 
5368 /* ************************************************************************** */
5369 
5370 #ifndef MNG_OPTIMIZE_CHUNKREADER
5371 #ifndef MNG_SKIPCHUNK_SAVE
READ_CHUNK(mng_read_save)5372 READ_CHUNK (mng_read_save)
5373 {
5374 #ifdef MNG_SUPPORT_TRACE
5375   MNG_TRACE (pData, MNG_FN_READ_SAVE, MNG_LC_START);
5376 #endif
5377                                        /* sequence checks */
5378   if ((!pData->bHasMHDR) || (pData->bHasSAVE))
5379     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5380 
5381 #ifdef MNG_INCLUDE_JNG
5382   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
5383 #else
5384   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
5385 #endif
5386     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5387 
5388   pData->bHasSAVE = MNG_TRUE;
5389 
5390   if (pData->fProcesssave)             /* inform the application ? */
5391   {
5392     mng_bool bOke = pData->fProcesssave ((mng_handle)pData);
5393 
5394     if (!bOke)
5395       MNG_ERROR (pData, MNG_APPMISCERROR);
5396   }
5397 
5398 #ifdef MNG_SUPPORT_DISPLAY
5399   {
5400     mng_retcode iRetcode;
5401 
5402 
5403     /* TODO: something with the parameters */
5404 
5405 
5406                                        /* create a SAVE animation object */
5407     iRetcode = mng_create_ani_save (pData);
5408 
5409     if (!iRetcode)
5410       iRetcode = mng_process_display_save (pData);
5411 
5412     if (iRetcode)                      /* on error bail out */
5413       return iRetcode;
5414 
5415   }
5416 #endif /* MNG_SUPPORT_DISPLAY */
5417 
5418 #ifdef MNG_STORE_CHUNKS
5419   if (pData->bStorechunks)
5420   {                                    /* initialize storage */
5421     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
5422 
5423     if (iRetcode)                      /* on error bail out */
5424       return iRetcode;
5425                                        /* store the fields */
5426     ((mng_savep)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
5427 
5428     if (iRawlen)                       /* not empty ? */
5429     {
5430       mng_uint8       iOtype = *pRawdata;
5431       mng_uint8       iEtype;
5432       mng_uint32      iCount = 0;
5433       mng_uint8p      pTemp;
5434       mng_uint8p      pNull;
5435       mng_uint32      iLen;
5436       mng_uint32      iOffset[2];
5437       mng_uint32      iStarttime[2];
5438       mng_uint32      iFramenr;
5439       mng_uint32      iLayernr;
5440       mng_uint32      iX;
5441       mng_save_entryp pEntry = MNG_NULL;
5442       mng_uint32      iNamesize;
5443 
5444       if ((iOtype != 4) && (iOtype != 8))
5445         MNG_ERROR (pData, MNG_INVOFFSETSIZE);
5446 
5447       ((mng_savep)*ppChunk)->iOffsettype = iOtype;
5448 
5449       for (iX = 0; iX < 2; iX++)       /* do this twice to get the count first ! */
5450       {
5451         pTemp = pRawdata + 1;
5452         iLen  = iRawlen  - 1;
5453 
5454         if (iX)                        /* second run ? */
5455         {
5456           MNG_ALLOC (pData, pEntry, (iCount * sizeof (mng_save_entry)));
5457 
5458           ((mng_savep)*ppChunk)->iCount   = iCount;
5459           ((mng_savep)*ppChunk)->pEntries = pEntry;
5460         }
5461 
5462         while (iLen)                   /* anything left ? */
5463         {
5464           iEtype = *pTemp;             /* entrytype */
5465 
5466           if ((iEtype != 0) && (iEtype != 1) && (iEtype != 2) && (iEtype != 3))
5467             MNG_ERROR (pData, MNG_INVENTRYTYPE);
5468 
5469           pTemp++;
5470 
5471           if (iEtype > 1)
5472           {
5473             iOffset    [0] = 0;
5474             iOffset    [1] = 0;
5475             iStarttime [0] = 0;
5476             iStarttime [1] = 0;
5477             iLayernr       = 0;
5478             iFramenr       = 0;
5479           }
5480           else
5481           {
5482             if (iOtype == 4)
5483             {
5484               iOffset [0] = 0;
5485               iOffset [1] = mng_get_uint32 (pTemp);
5486 
5487               pTemp += 4;
5488             }
5489             else
5490             {
5491               iOffset [0] = mng_get_uint32 (pTemp);
5492               iOffset [1] = mng_get_uint32 (pTemp+4);
5493 
5494               pTemp += 8;
5495             }
5496 
5497             if (iEtype > 0)
5498             {
5499               iStarttime [0] = 0;
5500               iStarttime [1] = 0;
5501               iLayernr       = 0;
5502               iFramenr       = 0;
5503             }
5504             else
5505             {
5506               if (iOtype == 4)
5507               {
5508                 iStarttime [0] = 0;
5509                 iStarttime [1] = mng_get_uint32 (pTemp+0);
5510                 iLayernr       = mng_get_uint32 (pTemp+4);
5511                 iFramenr       = mng_get_uint32 (pTemp+8);
5512 
5513                 pTemp += 12;
5514               }
5515               else
5516               {
5517                 iStarttime [0] = mng_get_uint32 (pTemp+0);
5518                 iStarttime [1] = mng_get_uint32 (pTemp+4);
5519                 iLayernr       = mng_get_uint32 (pTemp+8);
5520                 iFramenr       = mng_get_uint32 (pTemp+12);
5521 
5522                 pTemp += 16;
5523               }
5524             }
5525           }
5526 
5527           pNull = find_null (pTemp);   /* get the name length */
5528 
5529           if ((pNull - pRawdata) > (mng_int32)iRawlen)
5530           {
5531             iNamesize = iLen;          /* no null found; so end of SAVE */
5532             iLen      = 0;
5533           }
5534           else
5535           {
5536             iNamesize = pNull - pTemp; /* should be another entry */
5537             iLen     -= iNamesize;
5538 
5539             if (!iLen)                 /* must not end with a null ! */
5540               MNG_ERROR (pData, MNG_ENDWITHNULL);
5541           }
5542 
5543           if (!pEntry)
5544           {
5545             iCount++;
5546           }
5547           else
5548           {
5549             pEntry->iEntrytype     = iEtype;
5550             pEntry->iOffset    [0] = iOffset    [0];
5551             pEntry->iOffset    [1] = iOffset    [1];
5552             pEntry->iStarttime [0] = iStarttime [0];
5553             pEntry->iStarttime [1] = iStarttime [1];
5554             pEntry->iLayernr       = iLayernr;
5555             pEntry->iFramenr       = iFramenr;
5556             pEntry->iNamesize      = iNamesize;
5557 
5558             if (iNamesize)
5559             {
5560               MNG_ALLOC (pData, pEntry->zName, iNamesize+1);
5561               MNG_COPY (pEntry->zName, pTemp, iNamesize);
5562             }
5563 
5564             pEntry++;
5565           }
5566 
5567           pTemp += iNamesize;
5568         }
5569       }
5570     }
5571   }
5572 #endif /* MNG_STORE_CHUNKS */
5573 
5574 #ifdef MNG_SUPPORT_TRACE
5575   MNG_TRACE (pData, MNG_FN_READ_SAVE, MNG_LC_END);
5576 #endif
5577 
5578   return MNG_NOERROR;                  /* done */
5579 }
5580 #endif
5581 #endif
5582 
5583 /* ************************************************************************** */
5584 
5585 #ifndef MNG_OPTIMIZE_CHUNKREADER
5586 #ifndef MNG_SKIPCHUNK_SEEK
READ_CHUNK(mng_read_seek)5587 READ_CHUNK (mng_read_seek)
5588 {
5589   mng_retcode iRetcode;
5590 
5591 #ifdef MNG_SUPPORT_TRACE
5592   MNG_TRACE (pData, MNG_FN_READ_SEEK, MNG_LC_START);
5593 #endif
5594                                        /* sequence checks */
5595   if ((!pData->bHasMHDR) || (!pData->bHasSAVE))
5596     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5597 
5598 #ifdef MNG_INCLUDE_JNG
5599   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
5600 #else
5601   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
5602 #endif
5603     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5604 
5605 #ifdef MNG_SUPPORT_DISPLAY
5606                                        /* create a SEEK animation object */
5607   iRetcode = mng_create_ani_seek (pData, iRawlen, (mng_pchar)pRawdata);
5608 
5609   if (iRetcode)                        /* on error bail out */
5610     return iRetcode;
5611 
5612 #endif /* MNG_SUPPORT_DISPLAY */
5613 
5614   if (pData->fProcessseek)             /* inform the app ? */
5615   {
5616     mng_bool  bOke;
5617     mng_pchar zName;
5618 
5619     MNG_ALLOC (pData, zName, iRawlen + 1);
5620 
5621     if (iRawlen)
5622       MNG_COPY (zName, pRawdata, iRawlen);
5623 
5624     bOke = pData->fProcessseek ((mng_handle)pData, zName);
5625 
5626     MNG_FREEX (pData, zName, iRawlen + 1);
5627 
5628     if (!bOke)
5629       MNG_ERROR (pData, MNG_APPMISCERROR);
5630   }
5631 
5632 #ifdef MNG_SUPPORT_DISPLAY
5633                                        /* do display processing of the SEEK */
5634   iRetcode = mng_process_display_seek (pData);
5635 
5636   if (iRetcode)                        /* on error bail out */
5637     return iRetcode;
5638 #endif /* MNG_SUPPORT_DISPLAY */
5639 
5640 #ifdef MNG_STORE_CHUNKS
5641   if (pData->bStorechunks)
5642   {                                    /* initialize storage */
5643     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
5644 
5645     if (iRetcode)                      /* on error bail out */
5646       return iRetcode;
5647                                        /* store the fields */
5648     ((mng_seekp)*ppChunk)->iNamesize = iRawlen;
5649 
5650     if (iRawlen)
5651     {
5652       MNG_ALLOC (pData, ((mng_seekp)*ppChunk)->zName, iRawlen+1);
5653       MNG_COPY (((mng_seekp)*ppChunk)->zName, pRawdata, iRawlen);
5654     }
5655   }
5656 #endif /* MNG_STORE_CHUNKS */
5657 
5658 #ifdef MNG_SUPPORT_TRACE
5659   MNG_TRACE (pData, MNG_FN_READ_SEEK, MNG_LC_END);
5660 #endif
5661 
5662   return MNG_NOERROR;                  /* done */
5663 }
5664 #endif
5665 #endif
5666 
5667 /* ************************************************************************** */
5668 
5669 #ifndef MNG_OPTIMIZE_CHUNKREADER
5670 #ifndef MNG_SKIPCHUNK_eXPI
READ_CHUNK(mng_read_expi)5671 READ_CHUNK (mng_read_expi)
5672 {
5673 #ifdef MNG_SUPPORT_TRACE
5674   MNG_TRACE (pData, MNG_FN_READ_EXPI, MNG_LC_START);
5675 #endif
5676 
5677   if (!pData->bHasMHDR)                /* sequence checks */
5678     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5679 
5680 #ifdef MNG_INCLUDE_JNG
5681   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
5682 #else
5683   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
5684 #endif
5685     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5686 
5687   if (iRawlen < 3)                     /* check the length */
5688     MNG_ERROR (pData, MNG_INVALIDLENGTH);
5689 
5690 #ifdef MNG_SUPPORT_DISPLAY
5691   {
5692 
5693 
5694     /* TODO: something !!! */
5695 
5696 
5697   }
5698 #endif /* MNG_SUPPORT_DISPLAY */
5699 
5700 #ifdef MNG_STORE_CHUNKS
5701   if (pData->bStorechunks)
5702   {                                    /* initialize storage */
5703     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
5704 
5705     if (iRetcode)                      /* on error bail out */
5706       return iRetcode;
5707                                        /* store the fields */
5708     ((mng_expip)*ppChunk)->iSnapshotid = mng_get_uint16 (pRawdata);
5709     ((mng_expip)*ppChunk)->iNamesize   = iRawlen - 2;
5710 
5711     if (((mng_expip)*ppChunk)->iNamesize)
5712     {
5713       MNG_ALLOC (pData, ((mng_expip)*ppChunk)->zName,
5714                         ((mng_expip)*ppChunk)->iNamesize + 1);
5715       MNG_COPY (((mng_expip)*ppChunk)->zName, pRawdata+2,
5716                 ((mng_expip)*ppChunk)->iNamesize);
5717     }
5718   }
5719 #endif /* MNG_STORE_CHUNKS */
5720 
5721 #ifdef MNG_SUPPORT_TRACE
5722   MNG_TRACE (pData, MNG_FN_READ_EXPI, MNG_LC_END);
5723 #endif
5724 
5725   return MNG_NOERROR;                  /* done */
5726 }
5727 #endif
5728 #endif
5729 
5730 /* ************************************************************************** */
5731 
5732 #ifndef MNG_OPTIMIZE_CHUNKREADER
5733 #ifndef MNG_SKIPCHUNK_fPRI
READ_CHUNK(mng_read_fpri)5734 READ_CHUNK (mng_read_fpri)
5735 {
5736 #ifdef MNG_SUPPORT_TRACE
5737   MNG_TRACE (pData, MNG_FN_READ_FPRI, MNG_LC_START);
5738 #endif
5739 
5740   if (!pData->bHasMHDR)                /* sequence checks */
5741     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5742 
5743 #ifdef MNG_INCLUDE_JNG
5744   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
5745 #else
5746   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
5747 #endif
5748     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5749 
5750   if (iRawlen != 2)                    /* must be two bytes long */
5751     MNG_ERROR (pData, MNG_INVALIDLENGTH);
5752 
5753 #ifdef MNG_SUPPORT_DISPLAY
5754   {
5755 
5756 
5757     /* TODO: something !!! */
5758 
5759 
5760   }
5761 #endif /* MNG_SUPPORT_DISPLAY */
5762 
5763 #ifdef MNG_STORE_CHUNKS
5764   if (pData->bStorechunks)
5765   {                                    /* initialize storage */
5766     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
5767 
5768     if (iRetcode)                      /* on error bail out */
5769       return iRetcode;
5770                                        /* store the fields */
5771     ((mng_fprip)*ppChunk)->iDeltatype = *pRawdata;
5772     ((mng_fprip)*ppChunk)->iPriority  = *(pRawdata+1);
5773   }
5774 #endif /* MNG_STORE_CHUNKS */
5775 
5776 #ifdef MNG_SUPPORT_TRACE
5777   MNG_TRACE (pData, MNG_FN_READ_FPRI, MNG_LC_END);
5778 #endif
5779 
5780   return MNG_NOERROR;                  /* done */
5781 }
5782 #endif
5783 #endif
5784 
5785 /* ************************************************************************** */
5786 
5787 #ifndef MNG_OPTIMIZE_CHUNKREADER
5788 #ifndef MNG_SKIPCHUNK_nEED
CheckKeyword(mng_datap pData,mng_uint8p pKeyword)5789 MNG_LOCAL mng_bool CheckKeyword (mng_datap  pData,
5790                                  mng_uint8p pKeyword)
5791 {
5792   mng_chunkid handled_chunks [] =
5793   {
5794     MNG_UINT_BACK,                     /* keep it sorted !!!! */
5795     MNG_UINT_BASI,
5796     MNG_UINT_CLIP,
5797     MNG_UINT_CLON,
5798 #ifndef MNG_NO_DELTA_PNG
5799 /* TODO:    MNG_UINT_DBYK,  */
5800 #endif
5801     MNG_UINT_DEFI,
5802 #ifndef MNG_NO_DELTA_PNG
5803     MNG_UINT_DHDR,
5804 #endif
5805     MNG_UINT_DISC,
5806 #ifndef MNG_NO_DELTA_PNG
5807 /* TODO:    MNG_UINT_DROP,  */
5808 #endif
5809     MNG_UINT_ENDL,
5810     MNG_UINT_FRAM,
5811     MNG_UINT_IDAT,
5812     MNG_UINT_IEND,
5813     MNG_UINT_IHDR,
5814 #ifndef MNG_NO_DELTA_PNG
5815 #ifdef MNG_INCLUDE_JNG
5816     MNG_UINT_IJNG,
5817 #endif
5818     MNG_UINT_IPNG,
5819 #endif
5820 #ifdef MNG_INCLUDE_JNG
5821     MNG_UINT_JDAA,
5822     MNG_UINT_JDAT,
5823     MNG_UINT_JHDR,
5824 /* TODO:    MNG_UINT_JSEP,  */
5825     MNG_UINT_JdAA,
5826 #endif
5827     MNG_UINT_LOOP,
5828     MNG_UINT_MAGN,
5829     MNG_UINT_MEND,
5830     MNG_UINT_MHDR,
5831     MNG_UINT_MOVE,
5832 /* TODO:    MNG_UINT_ORDR,  */
5833     MNG_UINT_PAST,
5834     MNG_UINT_PLTE,
5835 #ifndef MNG_NO_DELTA_PNG
5836     MNG_UINT_PPLT,
5837     MNG_UINT_PROM,
5838 #endif
5839     MNG_UINT_SAVE,
5840     MNG_UINT_SEEK,
5841     MNG_UINT_SHOW,
5842     MNG_UINT_TERM,
5843 #ifdef MNG_INCLUDE_ANG_PROPOSAL
5844     MNG_UINT_adAT,
5845     MNG_UINT_ahDR,
5846 #endif
5847     MNG_UINT_bKGD,
5848     MNG_UINT_cHRM,
5849 /* TODO:    MNG_UINT_eXPI,  */
5850     MNG_UINT_evNT,
5851 /* TODO:    MNG_UINT_fPRI,  */
5852     MNG_UINT_gAMA,
5853 /* TODO:    MNG_UINT_hIST,  */
5854     MNG_UINT_iCCP,
5855     MNG_UINT_iTXt,
5856 #ifdef MNG_INCLUDE_MPNG_PROPOSAL
5857     MNG_UINT_mpNG,
5858 #endif
5859     MNG_UINT_nEED,
5860 /* TODO:    MNG_UINT_oFFs,  */
5861 /* TODO:    MNG_UINT_pCAL,  */
5862 /* TODO:    MNG_UINT_pHYg,  */
5863 /* TODO:    MNG_UINT_pHYs,  */
5864 /* TODO:    MNG_UINT_sBIT,  */
5865 /* TODO:    MNG_UINT_sCAL,  */
5866 /* TODO:    MNG_UINT_sPLT,  */
5867     MNG_UINT_sRGB,
5868     MNG_UINT_tEXt,
5869     MNG_UINT_tIME,
5870     MNG_UINT_tRNS,
5871     MNG_UINT_zTXt,
5872   };
5873 
5874   mng_bool bOke = MNG_FALSE;
5875 
5876   if (pData->fProcessneed)             /* does the app handle it ? */
5877     bOke = pData->fProcessneed ((mng_handle)pData, (mng_pchar)pKeyword);
5878 
5879   if (!bOke)
5880   {                                    /* find the keyword length */
5881     mng_uint8p pNull = find_null (pKeyword);
5882 
5883     if (pNull - pKeyword == 4)         /* test a chunk ? */
5884     {                                  /* get the chunk-id */
5885       mng_chunkid iChunkid = (*pKeyword     << 24) + (*(pKeyword+1) << 16) +
5886                              (*(pKeyword+2) <<  8) + (*(pKeyword+3)      );
5887                                        /* binary search variables */
5888       mng_int32   iTop, iLower, iUpper, iMiddle;
5889                                        /* determine max index of table */
5890       iTop = (sizeof (handled_chunks) / sizeof (handled_chunks [0])) - 1;
5891 
5892       /* binary search; with 52 chunks, worst-case is 7 comparisons */
5893       iLower  = 0;
5894       iMiddle = iTop >> 1;
5895       iUpper  = iTop;
5896 
5897       do                                   /* the binary search itself */
5898         {
5899           if (handled_chunks [iMiddle] < iChunkid)
5900             iLower = iMiddle + 1;
5901           else if (handled_chunks [iMiddle] > iChunkid)
5902             iUpper = iMiddle - 1;
5903           else
5904           {
5905             bOke = MNG_TRUE;
5906             break;
5907           }
5908 
5909           iMiddle = (iLower + iUpper) >> 1;
5910         }
5911       while (iLower <= iUpper);
5912     }
5913                                        /* test draft ? */
5914     if ((!bOke) && (pNull - pKeyword == 8) &&
5915         (*pKeyword     == 'd') && (*(pKeyword+1) == 'r') &&
5916         (*(pKeyword+2) == 'a') && (*(pKeyword+3) == 'f') &&
5917         (*(pKeyword+4) == 't') && (*(pKeyword+5) == ' '))
5918     {
5919       mng_uint32 iDraft;
5920 
5921       iDraft = (*(pKeyword+6) - '0') * 10 + (*(pKeyword+7) - '0');
5922       bOke   = (mng_bool)(iDraft <= MNG_MNG_DRAFT);
5923     }
5924                                        /* test MNG 1.0/1.1 ? */
5925     if ((!bOke) && (pNull - pKeyword == 7) &&
5926         (*pKeyword     == 'M') && (*(pKeyword+1) == 'N') &&
5927         (*(pKeyword+2) == 'G') && (*(pKeyword+3) == '-') &&
5928         (*(pKeyword+4) == '1') && (*(pKeyword+5) == '.') &&
5929         ((*(pKeyword+6) == '0') || (*(pKeyword+6) == '1')))
5930       bOke   = MNG_TRUE;
5931                                        /* test CACHEOFF ? */
5932     if ((!bOke) && (pNull - pKeyword == 8) &&
5933         (*pKeyword     == 'C') && (*(pKeyword+1) == 'A') &&
5934         (*(pKeyword+2) == 'C') && (*(pKeyword+3) == 'H') &&
5935         (*(pKeyword+4) == 'E') && (*(pKeyword+5) == 'O') &&
5936         (*(pKeyword+6) == 'F') && (*(pKeyword+7) == 'F'))
5937     {
5938       if (!pData->pFirstaniobj)        /* only if caching hasn't started yet ! */
5939       {
5940         bOke                  = MNG_TRUE;
5941         pData->bCacheplayback = MNG_FALSE;
5942         pData->bStorechunks   = MNG_FALSE;
5943       }
5944     }
5945   }
5946 
5947   return bOke;
5948 }
5949 #endif
5950 #endif
5951 
5952 /* ************************************************************************** */
5953 
5954 #ifndef MNG_OPTIMIZE_CHUNKREADER
5955 #ifndef MNG_SKIPCHUNK_nEED
READ_CHUNK(mng_read_need)5956 READ_CHUNK (mng_read_need)
5957 {
5958 #ifdef MNG_SUPPORT_TRACE
5959   MNG_TRACE (pData, MNG_FN_READ_NEED, MNG_LC_START);
5960 #endif
5961 
5962   if (!pData->bHasMHDR)                /* sequence checks */
5963     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5964 
5965 #ifdef MNG_INCLUDE_JNG
5966   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
5967 #else
5968   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
5969 #endif
5970     MNG_ERROR (pData, MNG_SEQUENCEERROR);
5971 
5972   if (iRawlen < 1)                     /* check the length */
5973     MNG_ERROR (pData, MNG_INVALIDLENGTH);
5974 
5975   {                                    /* let's check it */
5976     mng_bool   bOke = MNG_TRUE;
5977     mng_pchar  zKeywords;
5978     mng_uint8p pNull, pTemp;
5979 
5980     MNG_ALLOC (pData, zKeywords, iRawlen + 1);
5981 
5982     if (iRawlen)
5983       MNG_COPY (zKeywords, pRawdata, iRawlen);
5984 
5985     pTemp = (mng_uint8p)zKeywords;
5986     pNull = find_null (pTemp);
5987 
5988     while ((bOke) && (pNull < (mng_uint8p)zKeywords + iRawlen))
5989     {
5990       bOke  = CheckKeyword (pData, pTemp);
5991       pTemp = pNull + 1;
5992       pNull = find_null (pTemp);
5993     }
5994 
5995     if (bOke)
5996       bOke = CheckKeyword (pData, pTemp);
5997 
5998     MNG_FREEX (pData, zKeywords, iRawlen + 1);
5999 
6000     if (!bOke)
6001       MNG_ERROR (pData, MNG_UNSUPPORTEDNEED);
6002   }
6003 
6004 #ifdef MNG_STORE_CHUNKS
6005   if (pData->bStorechunks)
6006   {                                    /* initialize storage */
6007     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6008 
6009     if (iRetcode)                      /* on error bail out */
6010       return iRetcode;
6011                                        /* store the fields */
6012     ((mng_needp)*ppChunk)->iKeywordssize = iRawlen;
6013 
6014     if (iRawlen)
6015     {
6016       MNG_ALLOC (pData, ((mng_needp)*ppChunk)->zKeywords, iRawlen+1);
6017       MNG_COPY (((mng_needp)*ppChunk)->zKeywords, pRawdata, iRawlen);
6018     }
6019   }
6020 #endif /* MNG_STORE_CHUNKS */
6021 
6022 #ifdef MNG_SUPPORT_TRACE
6023   MNG_TRACE (pData, MNG_FN_READ_NEED, MNG_LC_END);
6024 #endif
6025 
6026   return MNG_NOERROR;                  /* done */
6027 }
6028 #endif
6029 #endif
6030 
6031 /* ************************************************************************** */
6032 
6033 #ifndef MNG_OPTIMIZE_CHUNKREADER
6034 #ifndef MNG_SKIPCHUNK_pHYg
READ_CHUNK(mng_read_phyg)6035 READ_CHUNK (mng_read_phyg)
6036 {
6037 #ifdef MNG_SUPPORT_TRACE
6038   MNG_TRACE (pData, MNG_FN_READ_PHYG, MNG_LC_START);
6039 #endif
6040 
6041   if (!pData->bHasMHDR)                /* sequence checks */
6042     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6043 
6044 #ifdef MNG_INCLUDE_JNG
6045   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
6046 #else
6047   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
6048 #endif
6049     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6050                                        /* it's 9 bytes or empty; no more, no less! */
6051   if ((iRawlen != 9) && (iRawlen != 0))
6052     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6053 
6054 #ifdef MNG_SUPPORT_DISPLAY
6055   {
6056 
6057 
6058     /* TODO: something !!! */
6059 
6060 
6061   }
6062 #endif /* MNG_SUPPORT_DISPLAY */
6063 
6064 #ifdef MNG_STORE_CHUNKS
6065   if (pData->bStorechunks)
6066   {                                    /* initialize storage */
6067     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6068 
6069     if (iRetcode)                      /* on error bail out */
6070       return iRetcode;
6071                                        /* store the fields */
6072     ((mng_phygp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
6073 
6074     if (iRawlen)
6075     {
6076       ((mng_phygp)*ppChunk)->iSizex = mng_get_uint32 (pRawdata);
6077       ((mng_phygp)*ppChunk)->iSizey = mng_get_uint32 (pRawdata+4);
6078       ((mng_phygp)*ppChunk)->iUnit  = *(pRawdata+8);
6079     }
6080   }
6081 #endif /* MNG_STORE_CHUNKS */
6082 
6083 #ifdef MNG_SUPPORT_TRACE
6084   MNG_TRACE (pData, MNG_FN_READ_PHYG, MNG_LC_END);
6085 #endif
6086 
6087   return MNG_NOERROR;                  /* done */
6088 }
6089 #endif
6090 #endif
6091 
6092 /* ************************************************************************** */
6093 
6094 #ifndef MNG_OPTIMIZE_CHUNKREADER
6095 #ifdef MNG_INCLUDE_JNG
READ_CHUNK(mng_read_jhdr)6096 READ_CHUNK (mng_read_jhdr)
6097 {
6098 #ifdef MNG_SUPPORT_TRACE
6099   MNG_TRACE (pData, MNG_FN_READ_JHDR, MNG_LC_START);
6100 #endif
6101                                        /* sequence checks */
6102   if ((pData->eSigtype != mng_it_jng) && (pData->eSigtype != mng_it_mng))
6103     MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
6104 
6105   if ((pData->eSigtype == mng_it_jng) && (pData->iChunkseq > 1))
6106     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6107 
6108   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
6109     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6110 
6111   if (iRawlen != 16)                   /* length oke ? */
6112     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6113                                        /* inside a JHDR-IEND block now */
6114   pData->bHasJHDR              = MNG_TRUE;
6115                                        /* and store interesting fields */
6116   pData->iDatawidth            = mng_get_uint32 (pRawdata);
6117   pData->iDataheight           = mng_get_uint32 (pRawdata+4);
6118   pData->iJHDRcolortype        = *(pRawdata+8);
6119   pData->iJHDRimgbitdepth      = *(pRawdata+9);
6120   pData->iJHDRimgcompression   = *(pRawdata+10);
6121   pData->iJHDRimginterlace     = *(pRawdata+11);
6122   pData->iJHDRalphabitdepth    = *(pRawdata+12);
6123   pData->iJHDRalphacompression = *(pRawdata+13);
6124   pData->iJHDRalphafilter      = *(pRawdata+14);
6125   pData->iJHDRalphainterlace   = *(pRawdata+15);
6126 
6127 
6128 #if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
6129   pData->iPNGmult = 1;
6130   pData->iPNGdepth = pData->iJHDRalphabitdepth;
6131 #endif
6132 
6133 #ifdef MNG_NO_1_2_4BIT_SUPPORT
6134   if (pData->iJHDRalphabitdepth < 8)
6135     pData->iJHDRalphabitdepth = 8;
6136 #endif
6137 
6138 #ifdef MNG_NO_16BIT_SUPPORT
6139   if (pData->iJHDRalphabitdepth > 8)
6140   {
6141     pData->iPNGmult = 2;
6142     pData->iJHDRalphabitdepth = 8;
6143   }
6144 #endif
6145                                        /* parameter validity checks */
6146   if ((pData->iJHDRcolortype != MNG_COLORTYPE_JPEGGRAY  ) &&
6147       (pData->iJHDRcolortype != MNG_COLORTYPE_JPEGCOLOR ) &&
6148       (pData->iJHDRcolortype != MNG_COLORTYPE_JPEGGRAYA ) &&
6149       (pData->iJHDRcolortype != MNG_COLORTYPE_JPEGCOLORA)    )
6150     MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
6151 
6152   if ((pData->iJHDRimgbitdepth != MNG_BITDEPTH_JPEG8     ) &&
6153       (pData->iJHDRimgbitdepth != MNG_BITDEPTH_JPEG12    ) &&
6154       (pData->iJHDRimgbitdepth != MNG_BITDEPTH_JPEG8AND12)    )
6155     MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
6156 
6157   if (pData->iJHDRimgcompression != MNG_COMPRESSION_BASELINEJPEG)
6158     MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
6159 
6160   if ((pData->iJHDRimginterlace != MNG_INTERLACE_SEQUENTIAL ) &&
6161       (pData->iJHDRimginterlace != MNG_INTERLACE_PROGRESSIVE)    )
6162     MNG_ERROR (pData, MNG_INVALIDINTERLACE);
6163 
6164   if ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) ||
6165       (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA)    )
6166   {
6167     if ((pData->iJHDRalphabitdepth != MNG_BITDEPTH_8 )
6168 #ifndef MNG_NO_1_2_4BIT_SUPPORT
6169         && (pData->iJHDRalphabitdepth != MNG_BITDEPTH_1 ) &&
6170         (pData->iJHDRalphabitdepth != MNG_BITDEPTH_2 ) &&
6171         (pData->iJHDRalphabitdepth != MNG_BITDEPTH_4 )
6172 #endif
6173 #ifndef MNG_NO_16BIT_SUPPORT
6174         && (pData->iJHDRalphabitdepth != MNG_BITDEPTH_16)
6175 #endif
6176         )
6177       MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
6178 
6179     if ((pData->iJHDRalphacompression != MNG_COMPRESSION_DEFLATE     ) &&
6180         (pData->iJHDRalphacompression != MNG_COMPRESSION_BASELINEJPEG)    )
6181       MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
6182 
6183     if ((pData->iJHDRalphacompression == MNG_COMPRESSION_BASELINEJPEG) &&
6184         (pData->iJHDRalphabitdepth    !=  MNG_BITDEPTH_8             )    )
6185       MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
6186 
6187 #if defined(FILTER192) || defined(FILTER193)
6188     if ((pData->iJHDRalphafilter != MNG_FILTER_ADAPTIVE ) &&
6189 #if defined(FILTER192) && defined(FILTER193)
6190         (pData->iJHDRalphafilter != MNG_FILTER_DIFFERING) &&
6191         (pData->iJHDRalphafilter != MNG_FILTER_NOFILTER )    )
6192 #else
6193 #ifdef FILTER192
6194         (pData->iJHDRalphafilter != MNG_FILTER_DIFFERING)    )
6195 #else
6196         (pData->iJHDRalphafilter != MNG_FILTER_NOFILTER )    )
6197 #endif
6198 #endif
6199       MNG_ERROR (pData, MNG_INVALIDFILTER);
6200 #else
6201     if (pData->iJHDRalphafilter)
6202       MNG_ERROR (pData, MNG_INVALIDFILTER);
6203 #endif
6204 
6205     if ((pData->iJHDRalphainterlace != MNG_INTERLACE_NONE ) &&
6206         (pData->iJHDRalphainterlace != MNG_INTERLACE_ADAM7)    )
6207       MNG_ERROR (pData, MNG_INVALIDINTERLACE);
6208 
6209   }
6210   else
6211   {
6212     if (pData->iJHDRalphabitdepth)
6213       MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
6214 
6215     if (pData->iJHDRalphacompression)
6216       MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
6217 
6218     if (pData->iJHDRalphafilter)
6219       MNG_ERROR (pData, MNG_INVALIDFILTER);
6220 
6221     if (pData->iJHDRalphainterlace)
6222       MNG_ERROR (pData, MNG_INVALIDINTERLACE);
6223 
6224   }
6225 
6226   if (!pData->bHasheader)              /* first chunk ? */
6227   {
6228     pData->bHasheader = MNG_TRUE;      /* we've got a header */
6229     pData->eImagetype = mng_it_jng;    /* then this must be a JNG */
6230     pData->iWidth     = mng_get_uint32 (pRawdata);
6231     pData->iHeight    = mng_get_uint32 (pRawdata+4);
6232                                        /* predict alpha-depth ! */
6233   if ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) ||
6234       (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA)    )
6235       pData->iAlphadepth = pData->iJHDRalphabitdepth;
6236     else
6237       pData->iAlphadepth = 0;
6238                                        /* fits on maximum canvas ? */
6239     if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
6240       MNG_WARNING (pData, MNG_IMAGETOOLARGE);
6241 
6242     if (pData->fProcessheader)         /* inform the app ? */
6243       if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
6244       MNG_ERROR (pData, MNG_APPMISCERROR);
6245 
6246   }
6247 
6248   pData->iColortype = 0;               /* fake grayscale for other routines */
6249   pData->iImagelevel++;                /* one level deeper */
6250 
6251 #ifdef MNG_SUPPORT_DISPLAY
6252   {
6253     mng_retcode iRetcode = mng_process_display_jhdr (pData);
6254 
6255     if (iRetcode)                      /* on error bail out */
6256       return iRetcode;
6257   }
6258 #endif /* MNG_SUPPORT_DISPLAY */
6259 
6260 #ifdef MNG_STORE_CHUNKS
6261   if (pData->bStorechunks)
6262   {                                    /* initialize storage */
6263     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6264 
6265     if (iRetcode)                      /* on error bail out */
6266       return iRetcode;
6267                                        /* store the fields */
6268     ((mng_jhdrp)*ppChunk)->iWidth            = mng_get_uint32 (pRawdata);
6269     ((mng_jhdrp)*ppChunk)->iHeight           = mng_get_uint32 (pRawdata+4);
6270     ((mng_jhdrp)*ppChunk)->iColortype        = *(pRawdata+8);
6271     ((mng_jhdrp)*ppChunk)->iImagesampledepth = *(pRawdata+9);
6272     ((mng_jhdrp)*ppChunk)->iImagecompression = *(pRawdata+10);
6273     ((mng_jhdrp)*ppChunk)->iImageinterlace   = *(pRawdata+11);
6274     ((mng_jhdrp)*ppChunk)->iAlphasampledepth = *(pRawdata+12);
6275 #ifdef MNG_NO_16BIT_SUPPORT
6276     if (*(pRawdata+12) > 8)
6277         ((mng_jhdrp)*ppChunk)->iAlphasampledepth = 8;
6278 #endif
6279     ((mng_jhdrp)*ppChunk)->iAlphacompression = *(pRawdata+13);
6280     ((mng_jhdrp)*ppChunk)->iAlphafilter      = *(pRawdata+14);
6281     ((mng_jhdrp)*ppChunk)->iAlphainterlace   = *(pRawdata+15);
6282   }
6283 #endif /* MNG_STORE_CHUNKS */
6284 
6285 #ifdef MNG_SUPPORT_TRACE
6286   MNG_TRACE (pData, MNG_FN_READ_JHDR, MNG_LC_END);
6287 #endif
6288 
6289   return MNG_NOERROR;                  /* done */
6290 }
6291 #else
6292 #define read_jhdr 0
6293 #endif /* MNG_INCLUDE_JNG */
6294 #endif
6295 
6296 /* ************************************************************************** */
6297 
6298 #ifndef MNG_OPTIMIZE_CHUNKREADER
6299 #ifdef MNG_INCLUDE_JNG
READ_CHUNK(mng_read_jdaa)6300 READ_CHUNK (mng_read_jdaa)
6301 {
6302 #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
6303   volatile mng_retcode iRetcode;
6304 
6305   iRetcode=MNG_NOERROR;
6306 #endif
6307 
6308 #ifdef MNG_SUPPORT_TRACE
6309   MNG_TRACE (pData, MNG_FN_READ_JDAA, MNG_LC_START);
6310 #endif
6311                                        /* sequence checks */
6312   if ((!pData->bHasJHDR) && (!pData->bHasDHDR))
6313     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6314 
6315   if (pData->bHasJSEP)
6316     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6317 
6318   if (pData->iJHDRalphacompression != MNG_COMPRESSION_BASELINEJPEG)
6319     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6320 
6321   if (iRawlen == 0)                    /* can never be empty */
6322     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6323 
6324   pData->bHasJDAA = MNG_TRUE;          /* got some JDAA now, don't we */
6325 
6326 #ifdef MNG_SUPPORT_DISPLAY
6327   iRetcode = mng_process_display_jdaa (pData, iRawlen, pRawdata);
6328 
6329   if (iRetcode)                      /* on error bail out */
6330     return iRetcode;
6331 #endif /* MNG_SUPPORT_DISPLAY */
6332 
6333 #ifdef MNG_STORE_CHUNKS
6334   if (pData->bStorechunks)
6335   {                                    /* initialize storage */
6336     iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6337 
6338     if (iRetcode)                      /* on error bail out */
6339       return iRetcode;
6340                                        /* store the fields */
6341     ((mng_jdaap)*ppChunk)->bEmpty    = (mng_bool)(iRawlen == 0);
6342     ((mng_jdaap)*ppChunk)->iDatasize = iRawlen;
6343 
6344     if (iRawlen != 0)                  /* is there any data ? */
6345     {
6346       MNG_ALLOC (pData, ((mng_jdaap)*ppChunk)->pData, iRawlen);
6347       MNG_COPY  (((mng_jdaap)*ppChunk)->pData, pRawdata, iRawlen);
6348     }
6349   }
6350 #endif /* MNG_STORE_CHUNKS */
6351 
6352 #ifdef MNG_SUPPORT_TRACE
6353   MNG_TRACE (pData, MNG_FN_READ_JDAA, MNG_LC_END);
6354 #endif
6355 
6356   return MNG_NOERROR;                  /* done */
6357 }
6358 #else
6359 #define read_jdaa 0
6360 #endif /* MNG_INCLUDE_JNG */
6361 #endif
6362 
6363 /* ************************************************************************** */
6364 
6365 #ifndef MNG_OPTIMIZE_CHUNKREADER
6366 #ifdef MNG_INCLUDE_JNG
READ_CHUNK(mng_read_jdat)6367 READ_CHUNK (mng_read_jdat)
6368 {
6369 #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
6370   volatile mng_retcode iRetcode;
6371 
6372   iRetcode=MNG_NOERROR;
6373 #endif
6374 
6375 #ifdef MNG_SUPPORT_TRACE
6376   MNG_TRACE (pData, MNG_FN_READ_JDAT, MNG_LC_START);
6377 #endif
6378                                        /* sequence checks */
6379   if ((!pData->bHasJHDR) && (!pData->bHasDHDR))
6380     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6381 
6382   if (iRawlen == 0)                    /* can never be empty */
6383     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6384 
6385   pData->bHasJDAT = MNG_TRUE;          /* got some JDAT now, don't we */
6386 
6387 #ifdef MNG_SUPPORT_DISPLAY
6388   iRetcode = mng_process_display_jdat (pData, iRawlen, pRawdata);
6389 
6390   if (iRetcode)                      /* on error bail out */
6391     return iRetcode;
6392 #endif /* MNG_SUPPORT_DISPLAY */
6393 
6394 #ifdef MNG_STORE_CHUNKS
6395   if (pData->bStorechunks)
6396   {                                    /* initialize storage */
6397     iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6398 
6399     if (iRetcode)                      /* on error bail out */
6400       return iRetcode;
6401                                        /* store the fields */
6402     ((mng_jdatp)*ppChunk)->bEmpty    = (mng_bool)(iRawlen == 0);
6403     ((mng_jdatp)*ppChunk)->iDatasize = iRawlen;
6404 
6405     if (iRawlen != 0)                  /* is there any data ? */
6406     {
6407       MNG_ALLOC (pData, ((mng_jdatp)*ppChunk)->pData, iRawlen);
6408       MNG_COPY  (((mng_jdatp)*ppChunk)->pData, pRawdata, iRawlen);
6409     }
6410   }
6411 #endif /* MNG_STORE_CHUNKS */
6412 
6413 #ifdef MNG_SUPPORT_TRACE
6414   MNG_TRACE (pData, MNG_FN_READ_JDAT, MNG_LC_END);
6415 #endif
6416 
6417   return MNG_NOERROR;                  /* done */
6418 }
6419 #else
6420 #define read_jdat 0
6421 #endif /* MNG_INCLUDE_JNG */
6422 #endif
6423 
6424 /* ************************************************************************** */
6425 
6426 #ifndef MNG_OPTIMIZE_CHUNKREADER
6427 #ifdef MNG_INCLUDE_JNG
READ_CHUNK(mng_read_jsep)6428 READ_CHUNK (mng_read_jsep)
6429 {
6430 #ifdef MNG_SUPPORT_TRACE
6431   MNG_TRACE (pData, MNG_FN_READ_JSEP, MNG_LC_START);
6432 #endif
6433 
6434   if (!pData->bHasJHDR)                /* sequence checks */
6435     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6436 
6437   if (iRawlen != 0)                    /* must be empty ! */
6438     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6439 
6440   pData->bHasJSEP = MNG_TRUE;          /* indicate we've had the 8-/12-bit separator */
6441 
6442 #ifdef MNG_STORE_CHUNKS
6443   if (pData->bStorechunks)
6444   {                                    /* initialize storage */
6445     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6446 
6447     if (iRetcode)                      /* on error bail out */
6448       return iRetcode;
6449 
6450   }
6451 #endif /* MNG_STORE_CHUNKS */
6452 
6453 #ifdef MNG_SUPPORT_TRACE
6454   MNG_TRACE (pData, MNG_FN_READ_JSEP, MNG_LC_END);
6455 #endif
6456 
6457   return MNG_NOERROR;                  /* done */
6458 }
6459 #else
6460 #define read_jsep 0
6461 #endif /* MNG_INCLUDE_JNG */
6462 #endif
6463 
6464 /* ************************************************************************** */
6465 
6466 #ifndef MNG_OPTIMIZE_CHUNKREADER
6467 #ifndef MNG_NO_DELTA_PNG
READ_CHUNK(mng_read_dhdr)6468 READ_CHUNK (mng_read_dhdr)
6469 {
6470   mng_uint8 iImagetype, iDeltatype;
6471 #ifdef MNG_SUPPORT_TRACE
6472   MNG_TRACE (pData, MNG_FN_READ_DHDR, MNG_LC_START);
6473 #endif
6474 
6475   if (!pData->bHasMHDR)                /* sequence checks */
6476     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6477 
6478 #ifdef MNG_INCLUDE_JNG
6479   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
6480 #else
6481   if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
6482 #endif
6483     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6484                                        /* check for valid length */
6485   if ((iRawlen != 4) && (iRawlen != 12) && (iRawlen != 20))
6486     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6487 
6488   iImagetype = *(pRawdata+2);          /* check fields for validity */
6489   iDeltatype = *(pRawdata+3);
6490 
6491   if (iImagetype > MNG_IMAGETYPE_JNG)
6492     MNG_ERROR (pData, MNG_INVIMAGETYPE);
6493 
6494   if (iDeltatype > MNG_DELTATYPE_NOCHANGE)
6495     MNG_ERROR (pData, MNG_INVDELTATYPE);
6496 
6497   if ((iDeltatype == MNG_DELTATYPE_REPLACE) && (iRawlen > 12))
6498     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6499 
6500   if ((iDeltatype == MNG_DELTATYPE_NOCHANGE) && (iRawlen > 4))
6501     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6502 
6503   pData->bHasDHDR   = MNG_TRUE;        /* inside a DHDR-IEND block now */
6504   pData->iDeltatype = iDeltatype;
6505 
6506   pData->iImagelevel++;                /* one level deeper */
6507 
6508 #ifdef MNG_SUPPORT_DISPLAY
6509   {
6510     mng_uint16  iObjectid    = mng_get_uint16 (pRawdata);
6511     mng_uint32  iBlockwidth  = 0;
6512     mng_uint32  iBlockheight = 0;
6513     mng_uint32  iBlockx      = 0;
6514     mng_uint32  iBlocky      = 0;
6515     mng_retcode iRetcode;
6516 
6517     if (iRawlen > 4)
6518     {
6519       iBlockwidth  = mng_get_uint32 (pRawdata+4);
6520       iBlockheight = mng_get_uint32 (pRawdata+8);
6521     }
6522 
6523     if (iRawlen > 12)
6524     {
6525       iBlockx      = mng_get_uint32 (pRawdata+12);
6526       iBlocky      = mng_get_uint32 (pRawdata+16);
6527     }
6528 
6529     iRetcode = mng_create_ani_dhdr (pData, iObjectid, iImagetype, iDeltatype,
6530                                     iBlockwidth, iBlockheight, iBlockx, iBlocky);
6531 
6532 /*    if (!iRetcode)
6533       iRetcode = mng_process_display_dhdr (pData, iObjectid, iImagetype, iDeltatype,
6534                                            iBlockwidth, iBlockheight, iBlockx, iBlocky); */
6535 
6536     if (iRetcode)                      /* on error bail out */
6537       return iRetcode;
6538 
6539   }
6540 #endif /* MNG_SUPPORT_DISPLAY */
6541 
6542 #ifdef MNG_STORE_CHUNKS
6543   if (pData->bStorechunks)
6544   {                                    /* initialize storage */
6545     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6546 
6547     if (iRetcode)                      /* on error bail out */
6548       return iRetcode;
6549                                        /* store the fields */
6550     ((mng_dhdrp)*ppChunk)->iObjectid      = mng_get_uint16 (pRawdata);
6551     ((mng_dhdrp)*ppChunk)->iImagetype     = iImagetype;
6552     ((mng_dhdrp)*ppChunk)->iDeltatype     = iDeltatype;
6553 
6554     if (iRawlen > 4)
6555     {
6556       ((mng_dhdrp)*ppChunk)->iBlockwidth  = mng_get_uint32 (pRawdata+4);
6557       ((mng_dhdrp)*ppChunk)->iBlockheight = mng_get_uint32 (pRawdata+8);
6558     }
6559 
6560     if (iRawlen > 12)
6561     {
6562       ((mng_dhdrp)*ppChunk)->iBlockx      = mng_get_uint32 (pRawdata+12);
6563       ((mng_dhdrp)*ppChunk)->iBlocky      = mng_get_uint32 (pRawdata+16);
6564     }
6565   }
6566 #endif /* MNG_STORE_CHUNKS */
6567 
6568 #ifdef MNG_SUPPORT_TRACE
6569   MNG_TRACE (pData, MNG_FN_READ_DHDR, MNG_LC_END);
6570 #endif
6571 
6572   return MNG_NOERROR;                  /* done */
6573 }
6574 #endif
6575 #endif
6576 
6577 /* ************************************************************************** */
6578 
6579 #ifndef MNG_OPTIMIZE_CHUNKREADER
6580 #ifndef MNG_NO_DELTA_PNG
READ_CHUNK(mng_read_prom)6581 READ_CHUNK (mng_read_prom)
6582 {
6583   mng_uint8 iColortype;
6584   mng_uint8 iSampledepth;
6585   mng_uint8 iFilltype;
6586 
6587 #ifdef MNG_SUPPORT_TRACE
6588   MNG_TRACE (pData, MNG_FN_READ_PROM, MNG_LC_START);
6589 #endif
6590                                        /* sequence checks */
6591   if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
6592     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6593 
6594   if (iRawlen != 3)                    /* gotta be exactly 3 bytes */
6595     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6596 
6597   iColortype   = *pRawdata;            /* check fields for validity */
6598   iSampledepth = *(pRawdata+1);
6599   iFilltype    = *(pRawdata+2);
6600 
6601   if ((iColortype != MNG_COLORTYPE_GRAY   ) &&
6602       (iColortype != MNG_COLORTYPE_RGB    ) &&
6603       (iColortype != MNG_COLORTYPE_INDEXED) &&
6604       (iColortype != MNG_COLORTYPE_GRAYA  ) &&
6605       (iColortype != MNG_COLORTYPE_RGBA   )    )
6606     MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
6607 
6608 #ifdef MNG_NO_16BIT_SUPPORT
6609   if (iSampledepth == MNG_BITDEPTH_16 )
6610       iSampledepth = MNG_BITDEPTH_8;
6611 #endif
6612 
6613   if ((iSampledepth != MNG_BITDEPTH_1 ) &&
6614       (iSampledepth != MNG_BITDEPTH_2 ) &&
6615       (iSampledepth != MNG_BITDEPTH_4 ) &&
6616       (iSampledepth != MNG_BITDEPTH_8 )
6617 #ifndef MNG_NO_16BIT_SUPPORT
6618       && (iSampledepth != MNG_BITDEPTH_16)
6619 #endif
6620     )
6621     MNG_ERROR (pData, MNG_INVSAMPLEDEPTH);
6622 
6623   if ((iFilltype != MNG_FILLMETHOD_LEFTBITREPLICATE) &&
6624       (iFilltype != MNG_FILLMETHOD_ZEROFILL        )    )
6625     MNG_ERROR (pData, MNG_INVFILLMETHOD);
6626 
6627 #ifdef MNG_SUPPORT_DISPLAY
6628   {
6629     mng_retcode iRetcode = mng_create_ani_prom (pData, iSampledepth,
6630                                                 iColortype, iFilltype);
6631 
6632 /*    if (!iRetcode)
6633       iRetcode = mng_process_display_prom (pData, iSampledepth,
6634                                            iColortype, iFilltype); */
6635 
6636     if (iRetcode)                      /* on error bail out */
6637       return iRetcode;
6638   }
6639 #endif /* MNG_SUPPORT_DISPLAY */
6640 
6641 #ifdef MNG_STORE_CHUNKS
6642   if (pData->bStorechunks)
6643   {                                    /* initialize storage */
6644     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6645 
6646     if (iRetcode)                      /* on error bail out */
6647       return iRetcode;
6648                                        /* store the fields */
6649     ((mng_promp)*ppChunk)->iColortype   = iColortype;
6650     ((mng_promp)*ppChunk)->iSampledepth = iSampledepth;
6651     ((mng_promp)*ppChunk)->iFilltype    = iFilltype;
6652   }
6653 #endif /* MNG_STORE_CHUNKS */
6654 
6655 #ifdef MNG_SUPPORT_TRACE
6656   MNG_TRACE (pData, MNG_FN_READ_PROM, MNG_LC_END);
6657 #endif
6658 
6659   return MNG_NOERROR;                  /* done */
6660 }
6661 #endif
6662 #endif
6663 
6664 /* ************************************************************************** */
6665 
6666 #ifndef MNG_OPTIMIZE_CHUNKREADER
6667 #ifndef MNG_NO_DELTA_PNG
READ_CHUNK(mng_read_ipng)6668 READ_CHUNK (mng_read_ipng)
6669 {
6670 #ifdef MNG_SUPPORT_TRACE
6671   MNG_TRACE (pData, MNG_FN_READ_IPNG, MNG_LC_START);
6672 #endif
6673                                        /* sequence checks */
6674   if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
6675     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6676 
6677   if (iRawlen != 0)                    /* gotta be empty */
6678     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6679 
6680 #ifdef MNG_SUPPORT_DISPLAY
6681   {
6682     mng_retcode iRetcode = mng_create_ani_ipng (pData);
6683 
6684     if (!iRetcode)
6685       iRetcode = mng_process_display_ipng (pData);
6686 
6687     if (iRetcode)                      /* on error bail out */
6688       return iRetcode;
6689 
6690   }
6691 #endif /* MNG_SUPPORT_DISPLAY */
6692 
6693 #ifdef MNG_STORE_CHUNKS
6694   if (pData->bStorechunks)
6695   {                                    /* initialize storage */
6696     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6697 
6698     if (iRetcode)                      /* on error bail out */
6699       return iRetcode;
6700   }
6701 #endif /* MNG_STORE_CHUNKS */
6702 
6703 #ifdef MNG_SUPPORT_TRACE
6704   MNG_TRACE (pData, MNG_FN_READ_IPNG, MNG_LC_END);
6705 #endif
6706 
6707   return MNG_NOERROR;                  /* done */
6708 }
6709 #endif
6710 #endif
6711 
6712 /* ************************************************************************** */
6713 
6714 #ifndef MNG_OPTIMIZE_CHUNKREADER
6715 #ifndef MNG_NO_DELTA_PNG
READ_CHUNK(mng_read_pplt)6716 READ_CHUNK (mng_read_pplt)
6717 {
6718   mng_uint8     iDeltatype;
6719   mng_uint8p    pTemp;
6720   mng_uint32    iLen;
6721   mng_uint8     iX, iM;
6722   mng_uint32    iY;
6723   mng_uint32    iMax;
6724   mng_rgbpaltab aIndexentries;
6725   mng_uint8arr  aAlphaentries;
6726   mng_uint8arr  aUsedentries;
6727 
6728 #ifdef MNG_SUPPORT_TRACE
6729   MNG_TRACE (pData, MNG_FN_READ_PPLT, MNG_LC_START);
6730 #endif
6731                                        /* sequence checks */
6732   if ((!pData->bHasMHDR) && (!pData->bHasDHDR))
6733     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6734 
6735   if (iRawlen < 1)                     /* must have at least 1 byte */
6736     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6737 
6738   iDeltatype = *pRawdata;
6739                                        /* valid ? */
6740   if (iDeltatype > MNG_DELTATYPE_DELTARGBA)
6741     MNG_ERROR (pData, MNG_INVDELTATYPE);
6742                                        /* must be indexed color ! */
6743   if (pData->iColortype != MNG_COLORTYPE_INDEXED)
6744     MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
6745 
6746   pTemp = pRawdata + 1;
6747   iLen  = iRawlen - 1;
6748   iMax  = 0;
6749 
6750   for (iY = 0; iY < 256; iY++)         /* reset arrays */
6751   {
6752     aIndexentries [iY].iRed   = 0;
6753     aIndexentries [iY].iGreen = 0;
6754     aIndexentries [iY].iBlue  = 0;
6755     aAlphaentries [iY]        = 255;
6756     aUsedentries  [iY]        = 0;
6757   }
6758 
6759   while (iLen)                         /* as long as there are entries left ... */
6760   {
6761     mng_uint32 iDiff;
6762 
6763     if (iLen < 2)
6764       MNG_ERROR (pData, MNG_INVALIDLENGTH);
6765 
6766     iX = *pTemp;                       /* get start and end index */
6767     iM = *(pTemp+1);
6768 
6769     if (iM < iX)
6770       MNG_ERROR (pData, MNG_INVALIDINDEX);
6771 
6772     if ((mng_uint32)iM >= iMax)        /* determine highest used index */
6773       iMax = (mng_uint32)iM + 1;
6774 
6775     pTemp += 2;
6776     iLen  -= 2;
6777     iDiff = (iM - iX + 1);
6778     if ((iDeltatype == MNG_DELTATYPE_REPLACERGB  ) ||
6779         (iDeltatype == MNG_DELTATYPE_DELTARGB    )    )
6780       iDiff = iDiff * 3;
6781     else
6782     if ((iDeltatype == MNG_DELTATYPE_REPLACERGBA) ||
6783         (iDeltatype == MNG_DELTATYPE_DELTARGBA  )    )
6784       iDiff = iDiff * 4;
6785 
6786     if (iLen < iDiff)
6787       MNG_ERROR (pData, MNG_INVALIDLENGTH);
6788 
6789     if ((iDeltatype == MNG_DELTATYPE_REPLACERGB  ) ||
6790         (iDeltatype == MNG_DELTATYPE_DELTARGB    )    )
6791     {
6792       for (iY = (mng_uint32)iX; iY <= (mng_uint32)iM; iY++)
6793       {
6794         aIndexentries [iY].iRed   = *pTemp;
6795         aIndexentries [iY].iGreen = *(pTemp+1);
6796         aIndexentries [iY].iBlue  = *(pTemp+2);
6797         aUsedentries  [iY]        = 1;
6798 
6799         pTemp += 3;
6800         iLen  -= 3;
6801       }
6802     }
6803     else
6804     if ((iDeltatype == MNG_DELTATYPE_REPLACEALPHA) ||
6805         (iDeltatype == MNG_DELTATYPE_DELTAALPHA  )    )
6806     {
6807       for (iY = (mng_uint32)iX; iY <= (mng_uint32)iM; iY++)
6808       {
6809         aAlphaentries [iY]        = *pTemp;
6810         aUsedentries  [iY]        = 1;
6811 
6812         pTemp++;
6813         iLen--;
6814       }
6815     }
6816     else
6817     {
6818       for (iY = (mng_uint32)iX; iY <= (mng_uint32)iM; iY++)
6819       {
6820         aIndexentries [iY].iRed   = *pTemp;
6821         aIndexentries [iY].iGreen = *(pTemp+1);
6822         aIndexentries [iY].iBlue  = *(pTemp+2);
6823         aAlphaentries [iY]        = *(pTemp+3);
6824         aUsedentries  [iY]        = 1;
6825 
6826         pTemp += 4;
6827         iLen  -= 4;
6828       }
6829     }
6830   }
6831 
6832   switch (pData->iBitdepth)            /* check maximum allowed entries for bitdepth */
6833   {
6834     case MNG_BITDEPTH_1 : {
6835                             if (iMax > 2)
6836                               MNG_ERROR (pData, MNG_INVALIDINDEX);
6837                             break;
6838                           }
6839     case MNG_BITDEPTH_2 : {
6840                             if (iMax > 4)
6841                               MNG_ERROR (pData, MNG_INVALIDINDEX);
6842                             break;
6843                           }
6844     case MNG_BITDEPTH_4 : {
6845                             if (iMax > 16)
6846                               MNG_ERROR (pData, MNG_INVALIDINDEX);
6847                             break;
6848                           }
6849   }
6850 
6851 #ifdef MNG_SUPPORT_DISPLAY
6852   {                                    /* create animation object */
6853     mng_retcode iRetcode = mng_create_ani_pplt (pData, iDeltatype, iMax,
6854                                                 aIndexentries, aAlphaentries,
6855                                                 aUsedentries);
6856 
6857 /*    if (!iRetcode)
6858       iRetcode = mng_process_display_pplt (pData, iDeltatype, iMax, aIndexentries,
6859                                            aAlphaentries, aUsedentries); */
6860 
6861     if (iRetcode)                      /* on error bail out */
6862       return iRetcode;
6863 
6864   }
6865 #endif /* MNG_SUPPORT_DISPLAY */
6866 
6867 #ifdef MNG_STORE_CHUNKS
6868   if (pData->bStorechunks)
6869   {                                    /* initialize storage */
6870     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6871 
6872     if (iRetcode)                      /* on error bail out */
6873       return iRetcode;
6874                                        /* store the fields */
6875     ((mng_ppltp)*ppChunk)->iDeltatype = iDeltatype;
6876     ((mng_ppltp)*ppChunk)->iCount     = iMax;
6877 
6878     for (iY = 0; iY < 256; iY++)
6879     {
6880       ((mng_ppltp)*ppChunk)->aEntries [iY].iRed   = aIndexentries [iY].iRed;
6881       ((mng_ppltp)*ppChunk)->aEntries [iY].iGreen = aIndexentries [iY].iGreen;
6882       ((mng_ppltp)*ppChunk)->aEntries [iY].iBlue  = aIndexentries [iY].iBlue;
6883       ((mng_ppltp)*ppChunk)->aEntries [iY].iAlpha = aAlphaentries [iY];
6884       ((mng_ppltp)*ppChunk)->aEntries [iY].bUsed  = (mng_bool)(aUsedentries [iY]);
6885     }
6886   }
6887 #endif /* MNG_STORE_CHUNKS */
6888 
6889 #ifdef MNG_SUPPORT_TRACE
6890   MNG_TRACE (pData, MNG_FN_READ_PPLT, MNG_LC_END);
6891 #endif
6892 
6893   return MNG_NOERROR;                  /* done */
6894 }
6895 #endif
6896 #endif
6897 
6898 /* ************************************************************************** */
6899 
6900 #ifndef MNG_OPTIMIZE_CHUNKREADER
6901 #ifndef MNG_NO_DELTA_PNG
6902 #ifdef MNG_INCLUDE_JNG
READ_CHUNK(mng_read_ijng)6903 READ_CHUNK (mng_read_ijng)
6904 {
6905 #ifdef MNG_SUPPORT_TRACE
6906   MNG_TRACE (pData, MNG_FN_READ_IJNG, MNG_LC_START);
6907 #endif
6908                                        /* sequence checks */
6909   if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
6910     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6911 
6912   if (iRawlen != 0)                    /* gotta be empty */
6913     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6914 
6915 #ifdef MNG_SUPPORT_DISPLAY
6916   {
6917     mng_retcode iRetcode = mng_create_ani_ijng (pData);
6918 
6919     if (!iRetcode)
6920       iRetcode = mng_process_display_ijng (pData);
6921 
6922     if (iRetcode)                      /* on error bail out */
6923       return iRetcode;
6924 
6925   }
6926 #endif /* MNG_SUPPORT_DISPLAY */
6927 
6928 #ifdef MNG_STORE_CHUNKS
6929   if (pData->bStorechunks)
6930   {                                    /* initialize storage */
6931     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6932 
6933     if (iRetcode)                      /* on error bail out */
6934       return iRetcode;
6935   }
6936 #endif /* MNG_STORE_CHUNKS */
6937 
6938 #ifdef MNG_SUPPORT_TRACE
6939   MNG_TRACE (pData, MNG_FN_READ_IJNG, MNG_LC_END);
6940 #endif
6941 
6942   return MNG_NOERROR;                  /* done */
6943 }
6944 #endif
6945 #endif
6946 #endif
6947 
6948 /* ************************************************************************** */
6949 
6950 #ifndef MNG_OPTIMIZE_CHUNKREADER
6951 #ifndef MNG_NO_DELTA_PNG
READ_CHUNK(mng_read_drop)6952 READ_CHUNK (mng_read_drop)
6953 {
6954 #ifdef MNG_SUPPORT_TRACE
6955   MNG_TRACE (pData, MNG_FN_READ_DROP, MNG_LC_START);
6956 #endif
6957                                        /* sequence checks */
6958   if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
6959     MNG_ERROR (pData, MNG_SEQUENCEERROR);
6960                                        /* check length */
6961   if ((iRawlen < 4) || ((iRawlen % 4) != 0))
6962     MNG_ERROR (pData, MNG_INVALIDLENGTH);
6963 
6964 #ifdef MNG_SUPPORT_DISPLAY
6965   {
6966 
6967 
6968     /* TODO: something !!! */
6969 
6970 
6971   }
6972 #endif /* MNG_SUPPORT_DISPLAY */
6973 
6974 #ifdef MNG_STORE_CHUNKS
6975   if (pData->bStorechunks)
6976   {                                    /* initialize storage */
6977     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
6978 
6979     if (iRetcode)                      /* on error bail out */
6980       return iRetcode;
6981                                        /* store the fields */
6982     ((mng_dropp)*ppChunk)->iCount = iRawlen / 4;
6983 
6984     if (iRawlen)
6985     {
6986       mng_uint32      iX;
6987       mng_uint8p      pTemp = pRawdata;
6988       mng_uint32p     pEntry;
6989 
6990       MNG_ALLOC (pData, pEntry, iRawlen);
6991 
6992       ((mng_dropp)*ppChunk)->pChunknames = (mng_ptr)pEntry;
6993 
6994       for (iX = 0; iX < iRawlen / 4; iX++)
6995       {
6996         *pEntry = mng_get_uint32 (pTemp);
6997 
6998         pTemp  += 4;
6999         pEntry++;
7000       }
7001     }
7002   }
7003 #endif /* MNG_STORE_CHUNKS */
7004 
7005 #ifdef MNG_SUPPORT_TRACE
7006   MNG_TRACE (pData, MNG_FN_READ_DROP, MNG_LC_END);
7007 #endif
7008 
7009   return MNG_NOERROR;                  /* done */
7010 }
7011 #endif
7012 #endif
7013 
7014 /* ************************************************************************** */
7015 
7016 #ifndef MNG_OPTIMIZE_CHUNKREADER
7017 #ifndef MNG_NO_DELTA_PNG
7018 #ifndef MNG_SKIPCHUNK_DBYK
READ_CHUNK(mng_read_dbyk)7019 READ_CHUNK (mng_read_dbyk)
7020 {
7021 #ifdef MNG_SUPPORT_TRACE
7022   MNG_TRACE (pData, MNG_FN_READ_DBYK, MNG_LC_START);
7023 #endif
7024                                        /* sequence checks */
7025   if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
7026     MNG_ERROR (pData, MNG_SEQUENCEERROR);
7027 
7028   if (iRawlen < 6)                     /* must be at least 6 long */
7029     MNG_ERROR (pData, MNG_INVALIDLENGTH);
7030 
7031 #ifdef MNG_SUPPORT_DISPLAY
7032   {
7033 
7034 
7035     /* TODO: something !!! */
7036 
7037 
7038   }
7039 #endif /* MNG_SUPPORT_DISPLAY */
7040 
7041 #ifdef MNG_STORE_CHUNKS
7042   if (pData->bStorechunks)
7043   {                                    /* initialize storage */
7044     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
7045 
7046     if (iRetcode)                      /* on error bail out */
7047       return iRetcode;
7048                                        /* store the fields */
7049     ((mng_dbykp)*ppChunk)->iChunkname    = mng_get_uint32 (pRawdata);
7050     ((mng_dbykp)*ppChunk)->iPolarity     = *(pRawdata+4);
7051     ((mng_dbykp)*ppChunk)->iKeywordssize = iRawlen - 5;
7052 
7053     if (iRawlen > 5)
7054     {
7055       MNG_ALLOC (pData, ((mng_dbykp)*ppChunk)->zKeywords, iRawlen-4);
7056       MNG_COPY (((mng_dbykp)*ppChunk)->zKeywords, pRawdata+5, iRawlen-5);
7057     }
7058   }
7059 #endif /* MNG_STORE_CHUNKS */
7060 
7061 #ifdef MNG_SUPPORT_TRACE
7062   MNG_TRACE (pData, MNG_FN_READ_DBYK, MNG_LC_END);
7063 #endif
7064 
7065   return MNG_NOERROR;                  /* done */
7066 }
7067 #endif
7068 #endif
7069 #endif
7070 
7071 /* ************************************************************************** */
7072 
7073 #ifndef MNG_OPTIMIZE_CHUNKREADER
7074 #ifndef MNG_NO_DELTA_PNG
7075 #ifndef MNG_SKIPCHUNK_ORDR
READ_CHUNK(mng_read_ordr)7076 READ_CHUNK (mng_read_ordr)
7077 {
7078 #ifdef MNG_SUPPORT_TRACE
7079   MNG_TRACE (pData, MNG_FN_READ_ORDR, MNG_LC_START);
7080 #endif
7081                                        /* sequence checks */
7082   if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
7083     MNG_ERROR (pData, MNG_SEQUENCEERROR);
7084                                        /* check length */
7085   if ((iRawlen < 5) || ((iRawlen % 5) != 0))
7086     MNG_ERROR (pData, MNG_INVALIDLENGTH);
7087 
7088 #ifdef MNG_SUPPORT_DISPLAY
7089   {
7090 
7091 
7092     /* TODO: something !!! */
7093 
7094 
7095   }
7096 #endif /* MNG_SUPPORT_DISPLAY */
7097 
7098 #ifdef MNG_STORE_CHUNKS
7099   if (pData->bStorechunks)
7100   {                                    /* initialize storage */
7101     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
7102 
7103     if (iRetcode)                      /* on error bail out */
7104       return iRetcode;
7105                                        /* store the fields */
7106     ((mng_ordrp)*ppChunk)->iCount = iRawlen / 5;
7107 
7108     if (iRawlen)
7109     {
7110       mng_uint32      iX;
7111       mng_ordr_entryp pEntry;
7112       mng_uint8p      pTemp = pRawdata;
7113 
7114       MNG_ALLOC (pData, pEntry, iRawlen);
7115 
7116       ((mng_ordrp)*ppChunk)->pEntries = pEntry;
7117 
7118       for (iX = 0; iX < iRawlen / 5; iX++)
7119       {
7120         pEntry->iChunkname = mng_get_uint32 (pTemp);
7121         pEntry->iOrdertype = *(pTemp+4);
7122 
7123         pTemp += 5;
7124         pEntry++;
7125       }
7126     }
7127   }
7128 #endif /* MNG_STORE_CHUNKS */
7129 
7130 #ifdef MNG_SUPPORT_TRACE
7131   MNG_TRACE (pData, MNG_FN_READ_ORDR, MNG_LC_END);
7132 #endif
7133 
7134   return MNG_NOERROR;                  /* done */
7135 }
7136 #endif
7137 #endif
7138 #endif
7139 
7140 /* ************************************************************************** */
7141 
7142 #ifndef MNG_OPTIMIZE_CHUNKREADER
7143 #ifndef MNG_SKIPCHUNK_MAGN
READ_CHUNK(mng_read_magn)7144 READ_CHUNK (mng_read_magn)
7145 {
7146   mng_uint16 iFirstid, iLastid;
7147   mng_uint8  iMethodX, iMethodY;
7148   mng_uint16 iMX, iMY, iML, iMR, iMT, iMB;
7149   mng_bool   bFaulty;
7150 
7151 #ifdef MNG_SUPPORT_TRACE
7152   MNG_TRACE (pData, MNG_FN_READ_MAGN, MNG_LC_START);
7153 #endif
7154                                        /* sequence checks */
7155 #ifdef MNG_SUPPORT_JNG
7156   if ((!pData->bHasMHDR) || (pData->bHasIHDR) || (pData->bHasDHDR) || (pData->bHasJHDR))
7157 #else
7158   if ((!pData->bHasMHDR) || (pData->bHasIHDR) || (pData->bHasDHDR))
7159 #endif
7160     MNG_ERROR (pData, MNG_SEQUENCEERROR);
7161                                        /* check length */
7162   if (iRawlen > 20)
7163     MNG_ERROR (pData, MNG_INVALIDLENGTH);
7164 
7165   /* following is an ugly hack to allow faulty layout caused by previous
7166      versions of libmng and MNGeye, which wrote MAGN with a 16-bit
7167      MethodX/MethodY (as opposed to the proper 8-bit as defined in the spec!) */
7168 
7169   if ((iRawlen ==  6) || (iRawlen ==  8) || (iRawlen == 10) || (iRawlen == 12) ||
7170       (iRawlen == 14) || (iRawlen == 16) || (iRawlen == 20))
7171     bFaulty = MNG_TRUE;                /* these lengths are all wrong */
7172   else                                 /* length 18 can be right or wrong !!! */
7173   if ((iRawlen ==  18) && (mng_get_uint16 (pRawdata+4) <= 5) &&
7174       (mng_get_uint16 (pRawdata+6)  < 256) &&
7175       (mng_get_uint16 (pRawdata+8)  < 256) &&
7176       (mng_get_uint16 (pRawdata+10) < 256) &&
7177       (mng_get_uint16 (pRawdata+12) < 256) &&
7178       (mng_get_uint16 (pRawdata+14) < 256) &&
7179       (mng_get_uint16 (pRawdata+16) < 256))
7180     bFaulty = MNG_TRUE;                /* this is very likely the wrong layout */
7181   else
7182     bFaulty = MNG_FALSE;               /* all other cases are handled as right */
7183 
7184   if (bFaulty)                         /* wrong layout ? */
7185   {
7186     if (iRawlen > 0)                   /* get the fields */
7187       iFirstid = mng_get_uint16 (pRawdata);
7188     else
7189       iFirstid = 0;
7190 
7191     if (iRawlen > 2)
7192       iLastid  = mng_get_uint16 (pRawdata+2);
7193     else
7194       iLastid  = iFirstid;
7195 
7196     if (iRawlen > 4)
7197       iMethodX = (mng_uint8)(mng_get_uint16 (pRawdata+4));
7198     else
7199       iMethodX = 0;
7200 
7201     if (iRawlen > 6)
7202       iMX      = mng_get_uint16 (pRawdata+6);
7203     else
7204       iMX      = 1;
7205 
7206     if (iRawlen > 8)
7207       iMY      = mng_get_uint16 (pRawdata+8);
7208     else
7209       iMY      = iMX;
7210 
7211     if (iRawlen > 10)
7212       iML      = mng_get_uint16 (pRawdata+10);
7213     else
7214       iML      = iMX;
7215 
7216     if (iRawlen > 12)
7217       iMR      = mng_get_uint16 (pRawdata+12);
7218     else
7219       iMR      = iMX;
7220 
7221     if (iRawlen > 14)
7222       iMT      = mng_get_uint16 (pRawdata+14);
7223     else
7224       iMT      = iMY;
7225 
7226     if (iRawlen > 16)
7227       iMB      = mng_get_uint16 (pRawdata+16);
7228     else
7229       iMB      = iMY;
7230 
7231     if (iRawlen > 18)
7232       iMethodY = (mng_uint8)(mng_get_uint16 (pRawdata+18));
7233     else
7234       iMethodY = iMethodX;
7235   }
7236   else                                 /* proper layout !!!! */
7237   {
7238     if (iRawlen > 0)                   /* get the fields */
7239       iFirstid = mng_get_uint16 (pRawdata);
7240     else
7241       iFirstid = 0;
7242 
7243     if (iRawlen > 2)
7244       iLastid  = mng_get_uint16 (pRawdata+2);
7245     else
7246       iLastid  = iFirstid;
7247 
7248     if (iRawlen > 4)
7249       iMethodX = *(pRawdata+4);
7250     else
7251       iMethodX = 0;
7252 
7253     if (iRawlen > 5)
7254       iMX      = mng_get_uint16 (pRawdata+5);
7255     else
7256       iMX      = 1;
7257 
7258     if (iRawlen > 7)
7259       iMY      = mng_get_uint16 (pRawdata+7);
7260     else
7261       iMY      = iMX;
7262 
7263     if (iRawlen > 9)
7264       iML      = mng_get_uint16 (pRawdata+9);
7265     else
7266       iML      = iMX;
7267 
7268     if (iRawlen > 11)
7269       iMR      = mng_get_uint16 (pRawdata+11);
7270     else
7271       iMR      = iMX;
7272 
7273     if (iRawlen > 13)
7274       iMT      = mng_get_uint16 (pRawdata+13);
7275     else
7276       iMT      = iMY;
7277 
7278     if (iRawlen > 15)
7279       iMB      = mng_get_uint16 (pRawdata+15);
7280     else
7281       iMB      = iMY;
7282 
7283     if (iRawlen > 17)
7284       iMethodY = *(pRawdata+17);
7285     else
7286       iMethodY = iMethodX;
7287   }
7288                                        /* check field validity */
7289   if ((iMethodX > 5) || (iMethodY > 5))
7290     MNG_ERROR (pData, MNG_INVALIDMETHOD);
7291 
7292 #ifdef MNG_SUPPORT_DISPLAY
7293   {
7294     mng_retcode iRetcode;
7295 
7296     iRetcode = mng_create_ani_magn (pData, iFirstid, iLastid, iMethodX,
7297                                     iMX, iMY, iML, iMR, iMT, iMB, iMethodY);
7298 
7299 /*    if (!iRetcode)
7300       iRetcode = mng_process_display_magn (pData, iFirstid, iLastid, iMethodX,
7301                                            iMX, iMY, iML, iMR, iMT, iMB, iMethodY); */
7302 
7303     if (iRetcode)                      /* on error bail out */
7304       return iRetcode;
7305 
7306   }
7307 #endif /* MNG_SUPPORT_DISPLAY */
7308 
7309 #ifdef MNG_STORE_CHUNKS
7310   if (pData->bStorechunks)
7311   {                                    /* initialize storage */
7312     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
7313 
7314     if (iRetcode)                      /* on error bail out */
7315       return iRetcode;
7316                                        /* store the fields */
7317     ((mng_magnp)*ppChunk)->iFirstid = iFirstid;
7318     ((mng_magnp)*ppChunk)->iLastid  = iLastid;
7319     ((mng_magnp)*ppChunk)->iMethodX = iMethodX;
7320     ((mng_magnp)*ppChunk)->iMX      = iMX;
7321     ((mng_magnp)*ppChunk)->iMY      = iMY;
7322     ((mng_magnp)*ppChunk)->iML      = iML;
7323     ((mng_magnp)*ppChunk)->iMR      = iMR;
7324     ((mng_magnp)*ppChunk)->iMT      = iMT;
7325     ((mng_magnp)*ppChunk)->iMB      = iMB;
7326     ((mng_magnp)*ppChunk)->iMethodY = iMethodY;
7327   }
7328 #endif /* MNG_STORE_CHUNKS */
7329 
7330 #ifdef MNG_SUPPORT_TRACE
7331   MNG_TRACE (pData, MNG_FN_READ_MAGN, MNG_LC_END);
7332 #endif
7333 
7334   return MNG_NOERROR;                  /* done */
7335 }
7336 #endif
7337 #endif
7338 
7339 /* ************************************************************************** */
7340 
7341 #ifndef MNG_OPTIMIZE_CHUNKREADER
7342 #ifdef MNG_INCLUDE_MPNG_PROPOSAL
READ_CHUNK(mng_read_mpng)7343 READ_CHUNK (mng_read_mpng)
7344 {
7345   mng_uint32  iFramewidth;
7346   mng_uint32  iFrameheight;
7347   mng_uint16  iTickspersec;
7348   mng_uint32  iFramessize;
7349   mng_uint32  iCompressedsize;
7350 #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
7351   mng_retcode iRetcode;
7352   mng_uint16  iNumplays;
7353   mng_uint32  iBufsize;
7354   mng_uint8p  pBuf = 0;
7355 #endif
7356 
7357 #ifdef MNG_SUPPORT_TRACE
7358   MNG_TRACE (pData, MNG_FN_READ_MPNG, MNG_LC_START);
7359 #endif
7360                                        /* sequence checks */
7361   if (!pData->bHasIHDR)
7362     MNG_ERROR (pData, MNG_SEQUENCEERROR);
7363 
7364   if (iRawlen < 41)                    /* length must be at least 41 */
7365     MNG_ERROR (pData, MNG_INVALIDLENGTH);
7366 
7367   iFramewidth     = mng_get_int32 (pRawdata);
7368   if (iFramewidth == 0)                /* frame_width must not be zero */
7369     MNG_ERROR (pData, MNG_INVALIDWIDTH);
7370 
7371   iFrameheight    = mng_get_int32 (pRawdata+4);
7372   if (iFrameheight == 0)               /* frame_height must not be zero */
7373     MNG_ERROR (pData, MNG_INVALIDHEIGHT);
7374 
7375   iTickspersec    = mng_get_uint16 (pRawdata+10);
7376   if (iTickspersec == 0)               /* delay_den must not be zero */
7377     MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
7378 
7379   if (*(pRawdata+12) != 0)             /* only deflate compression-method allowed */
7380     MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
7381 
7382 #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
7383   iNumplays       = mng_get_uint16 (pRawdata+8);
7384   iCompressedsize = (mng_uint32)(iRawlen - 13);
7385 #endif
7386 
7387 #ifdef MNG_SUPPORT_DISPLAY
7388   {
7389     iRetcode = mng_inflate_buffer (pData, pRawdata+13, iCompressedsize,
7390                                    &pBuf, &iBufsize, &iFramessize);
7391     if (iRetcode)                    /* on error bail out */
7392     {
7393       MNG_FREEX (pData, pBuf, iBufsize);
7394       return iRetcode;
7395     }
7396 
7397     if (iFramessize % 26)
7398     {
7399       MNG_FREEX (pData, pBuf, iBufsize);
7400       MNG_ERROR (pData, MNG_INVALIDLENGTH);
7401     }
7402 
7403     iRetcode = mng_create_mpng_obj (pData, iFramewidth, iFrameheight, iNumplays,
7404                                     iTickspersec, iFramessize, pBuf);
7405     if (iRetcode)                      /* on error bail out */
7406     {
7407       MNG_FREEX (pData, pBuf, iBufsize);
7408       return iRetcode;
7409     }
7410   }
7411 #endif /* MNG_SUPPORT_DISPLAY */
7412 
7413 #ifdef MNG_STORE_CHUNKS
7414   if (pData->bStorechunks)
7415   {                                    /* initialize storage */
7416     iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
7417     if (iRetcode)                      /* on error bail out */
7418       return iRetcode;
7419                                        /* store the fields */
7420     ((mng_mpngp)*ppChunk)->iFramewidth        = iFramewidth;
7421     ((mng_mpngp)*ppChunk)->iFrameheight       = iFrameheight;
7422     ((mng_mpngp)*ppChunk)->iNumplays          = iNumplays;
7423     ((mng_mpngp)*ppChunk)->iTickspersec       = iTickspersec;
7424     ((mng_mpngp)*ppChunk)->iCompressionmethod = *(pRawdata+14);
7425 
7426 #ifndef MNG_SUPPORT_DISPLAY
7427     iRetcode = mng_inflate_buffer (pData, pRawdata+13, iCompressedsize,
7428                                    &pBuf, &iBufsize, &iFramessize);
7429     if (iRetcode)                    /* on error bail out */
7430     {
7431       MNG_FREEX (pData, pBuf, iBufsize);
7432       return iRetcode;
7433     }
7434 
7435     if (iFramessize % 26)
7436     {
7437       MNG_FREEX (pData, pBuf, iBufsize);
7438       MNG_ERROR (pData, MNG_INVALIDLENGTH);
7439     }
7440 #endif
7441 
7442     if (iFramessize)
7443     {
7444       MNG_ALLOCX (pData, ((mng_mpngp)*ppChunk)->pFrames, iFramessize);
7445       if (((mng_mpngp)*ppChunk)->pFrames == 0)
7446       {
7447         MNG_FREEX (pData, pBuf, iBufsize);
7448         MNG_ERROR (pData, MNG_OUTOFMEMORY);
7449       }
7450 
7451       ((mng_mpngp)*ppChunk)->iFramessize = iFramessize;
7452       MNG_COPY (((mng_mpngp)*ppChunk)->pFrames, pBuf, iFramessize);
7453     }
7454   }
7455 #endif /* MNG_STORE_CHUNKS */
7456 
7457 #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
7458   MNG_FREEX (pData, pBuf, iBufsize);
7459 #endif
7460 
7461 #ifdef MNG_SUPPORT_TRACE
7462   MNG_TRACE (pData, MNG_FN_READ_MPNG, MNG_LC_END);
7463 #endif
7464 
7465   return MNG_NOERROR;                  /* done */
7466 }
7467 #endif
7468 #endif
7469 
7470 /* ************************************************************************** */
7471 
7472 #ifndef MNG_OPTIMIZE_CHUNKREADER
7473 #ifndef MNG_SKIPCHUNK_evNT
READ_CHUNK(mng_read_evnt)7474 READ_CHUNK (mng_read_evnt)
7475 {
7476 #ifdef MNG_SUPPORT_TRACE
7477   MNG_TRACE (pData, MNG_FN_READ_EVNT, MNG_LC_START);
7478 #endif
7479                                        /* sequence checks */
7480   if ((!pData->bHasMHDR) || (pData->bHasSAVE))
7481     MNG_ERROR (pData, MNG_SEQUENCEERROR);
7482 
7483   if (iRawlen < 2)                     /* must have at least 1 entry ! */
7484     MNG_ERROR (pData, MNG_INVALIDLENGTH);
7485 
7486 #if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_SUPPORT_DYNAMICMNG)
7487   {
7488     if (iRawlen)                       /* not empty ? */
7489     {
7490       mng_retcode iRetcode;
7491       mng_uint8p  pTemp;
7492       mng_uint8p  pNull;
7493       mng_uint32  iLen;
7494       mng_uint8   iEventtype;
7495       mng_uint8   iMasktype;
7496       mng_int32   iLeft;
7497       mng_int32   iRight;
7498       mng_int32   iTop;
7499       mng_int32   iBottom;
7500       mng_uint16  iObjectid;
7501       mng_uint8   iIndex;
7502       mng_uint32  iNamesize;
7503 
7504       pTemp = pRawdata;
7505       iLen  = iRawlen;
7506 
7507       while (iLen)                   /* anything left ? */
7508       {
7509         iEventtype = *pTemp;         /* eventtype */
7510         if (iEventtype > 5)
7511           MNG_ERROR (pData, MNG_INVALIDEVENT);
7512 
7513         pTemp++;
7514 
7515         iMasktype  = *pTemp;         /* masktype */
7516         if (iMasktype > 5)
7517           MNG_ERROR (pData, MNG_INVALIDMASK);
7518 
7519         pTemp++;
7520         iLen -= 2;
7521 
7522         iLeft     = 0;
7523         iRight    = 0;
7524         iTop      = 0;
7525         iBottom   = 0;
7526         iObjectid = 0;
7527         iIndex    = 0;
7528 
7529         switch (iMasktype)
7530         {
7531           case 1 :
7532             {
7533               if (iLen > 16)
7534               {
7535                 iLeft     = mng_get_int32 (pTemp);
7536                 iRight    = mng_get_int32 (pTemp+4);
7537                 iTop      = mng_get_int32 (pTemp+8);
7538                 iBottom   = mng_get_int32 (pTemp+12);
7539                 pTemp += 16;
7540                 iLen -= 16;
7541               }
7542               else
7543                 MNG_ERROR (pData, MNG_INVALIDLENGTH);
7544               break;
7545             }
7546           case 2 :
7547             {
7548               if (iLen > 2)
7549               {
7550                 iObjectid = mng_get_uint16 (pTemp);
7551                 pTemp += 2;
7552                 iLen -= 2;
7553               }
7554               else
7555                 MNG_ERROR (pData, MNG_INVALIDLENGTH);
7556               break;
7557             }
7558           case 3 :
7559             {
7560               if (iLen > 3)
7561               {
7562                 iObjectid = mng_get_uint16 (pTemp);
7563                 iIndex    = *(pTemp+2);
7564                 pTemp += 3;
7565                 iLen -= 3;
7566               }
7567               else
7568                 MNG_ERROR (pData, MNG_INVALIDLENGTH);
7569               break;
7570             }
7571           case 4 :
7572             {
7573               if (iLen > 18)
7574               {
7575                 iLeft     = mng_get_int32 (pTemp);
7576                 iRight    = mng_get_int32 (pTemp+4);
7577                 iTop      = mng_get_int32 (pTemp+8);
7578                 iBottom   = mng_get_int32 (pTemp+12);
7579                 iObjectid = mng_get_uint16 (pTemp+16);
7580                 pTemp += 18;
7581                 iLen -= 18;
7582               }
7583               else
7584                 MNG_ERROR (pData, MNG_INVALIDLENGTH);
7585               break;
7586             }
7587           case 5 :
7588             {
7589               if (iLen > 19)
7590               {
7591                 iLeft     = mng_get_int32 (pTemp);
7592                 iRight    = mng_get_int32 (pTemp+4);
7593                 iTop      = mng_get_int32 (pTemp+8);
7594                 iBottom   = mng_get_int32 (pTemp+12);
7595                 iObjectid = mng_get_uint16 (pTemp+16);
7596                 iIndex    = *(pTemp+18);
7597                 pTemp += 19;
7598                 iLen -= 19;
7599               }
7600               else
7601                 MNG_ERROR (pData, MNG_INVALIDLENGTH);
7602               break;
7603             }
7604         }
7605 
7606         pNull = find_null (pTemp);   /* get the name length */
7607 
7608         if ((pNull - pTemp) > (mng_int32)iLen)
7609         {
7610           iNamesize = iLen;          /* no null found; so end of evNT */
7611           iLen      = 0;
7612         }
7613         else
7614         {
7615           iNamesize = pNull - pTemp; /* should be another entry */
7616           iLen      = iLen - iNamesize - 1;
7617 
7618           if (!iLen)                 /* must not end with a null ! */
7619             MNG_ERROR (pData, MNG_ENDWITHNULL);
7620         }
7621 
7622         iRetcode = mng_create_event (pData, iEventtype, iMasktype, iLeft, iRight,
7623                                             iTop, iBottom, iObjectid, iIndex,
7624                                             iNamesize, (mng_pchar)pTemp);
7625 
7626         if (iRetcode)                 /* on error bail out */
7627           return iRetcode;
7628 
7629         pTemp = pTemp + iNamesize + 1;
7630       }
7631     }
7632   }
7633 #endif /* MNG_SUPPORT_DISPLAY && MNG_SUPPORT_DYNAMICMNG */
7634 
7635 #ifdef MNG_STORE_CHUNKS
7636   if (pData->bStorechunks)
7637   {                                    /* initialize storage */
7638     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
7639 
7640     if (iRetcode)                      /* on error bail out */
7641       return iRetcode;
7642 
7643     if (iRawlen)                       /* not empty ? */
7644     {
7645       mng_uint32      iX;
7646       mng_uint32      iCount = 0;
7647       mng_uint8p      pTemp;
7648       mng_uint8p      pNull;
7649       mng_uint32      iLen;
7650       mng_uint8       iEventtype;
7651       mng_uint8       iMasktype;
7652       mng_int32       iLeft;
7653       mng_int32       iRight;
7654       mng_int32       iTop;
7655       mng_int32       iBottom;
7656       mng_uint16      iObjectid;
7657       mng_uint8       iIndex;
7658       mng_uint32      iNamesize;
7659       mng_evnt_entryp pEntry = MNG_NULL;
7660 
7661       for (iX = 0; iX < 2; iX++)       /* do this twice to get the count first ! */
7662       {
7663         pTemp = pRawdata;
7664         iLen  = iRawlen;
7665 
7666         if (iX)                        /* second run ? */
7667         {
7668           MNG_ALLOC (pData, pEntry, (iCount * sizeof (mng_evnt_entry)));
7669 
7670           ((mng_evntp)*ppChunk)->iCount   = iCount;
7671           ((mng_evntp)*ppChunk)->pEntries = pEntry;
7672         }
7673 
7674         while (iLen)                   /* anything left ? */
7675         {
7676           iEventtype = *pTemp;         /* eventtype */
7677           if (iEventtype > 5)
7678             MNG_ERROR (pData, MNG_INVALIDEVENT);
7679 
7680           pTemp++;
7681 
7682           iMasktype  = *pTemp;         /* masktype */
7683           if (iMasktype > 5)
7684             MNG_ERROR (pData, MNG_INVALIDMASK);
7685 
7686           pTemp++;
7687           iLen -= 2;
7688 
7689           iLeft     = 0;
7690           iRight    = 0;
7691           iTop      = 0;
7692           iBottom   = 0;
7693           iObjectid = 0;
7694           iIndex    = 0;
7695 
7696           switch (iMasktype)
7697           {
7698             case 1 :
7699               {
7700                 if (iLen > 16)
7701                 {
7702                   iLeft     = mng_get_int32 (pTemp);
7703                   iRight    = mng_get_int32 (pTemp+4);
7704                   iTop      = mng_get_int32 (pTemp+8);
7705                   iBottom   = mng_get_int32 (pTemp+12);
7706                   pTemp += 16;
7707                   iLen -= 16;
7708                 }
7709                 else
7710                   MNG_ERROR (pData, MNG_INVALIDLENGTH);
7711                 break;
7712               }
7713             case 2 :
7714               {
7715                 if (iLen > 2)
7716                 {
7717                   iObjectid = mng_get_uint16 (pTemp);
7718                   pTemp += 2;
7719                   iLen -= 2;
7720                 }
7721                 else
7722                   MNG_ERROR (pData, MNG_INVALIDLENGTH);
7723                 break;
7724               }
7725             case 3 :
7726               {
7727                 if (iLen > 3)
7728                 {
7729                   iObjectid = mng_get_uint16 (pTemp);
7730                   iIndex    = *(pTemp+2);
7731                   pTemp += 3;
7732                   iLen -= 3;
7733                 }
7734                 else
7735                   MNG_ERROR (pData, MNG_INVALIDLENGTH);
7736                 break;
7737               }
7738             case 4 :
7739               {
7740                 if (iLen > 18)
7741                 {
7742                   iLeft     = mng_get_int32 (pTemp);
7743                   iRight    = mng_get_int32 (pTemp+4);
7744                   iTop      = mng_get_int32 (pTemp+8);
7745                   iBottom   = mng_get_int32 (pTemp+12);
7746                   iObjectid = mng_get_uint16 (pTemp+16);
7747                   pTemp += 18;
7748                   iLen -= 18;
7749                 }
7750                 else
7751                   MNG_ERROR (pData, MNG_INVALIDLENGTH);
7752                 break;
7753               }
7754             case 5 :
7755               {
7756                 if (iLen > 19)
7757                 {
7758                   iLeft     = mng_get_int32 (pTemp);
7759                   iRight    = mng_get_int32 (pTemp+4);
7760                   iTop      = mng_get_int32 (pTemp+8);
7761                   iBottom   = mng_get_int32 (pTemp+12);
7762                   iObjectid = mng_get_uint16 (pTemp+16);
7763                   iIndex    = *(pTemp+18);
7764                   pTemp += 19;
7765                   iLen -= 19;
7766                 }
7767                 else
7768                   MNG_ERROR (pData, MNG_INVALIDLENGTH);
7769                 break;
7770               }
7771           }
7772 
7773           pNull = find_null (pTemp);   /* get the name length */
7774 
7775           if ((pNull - pTemp) > (mng_int32)iLen)
7776           {
7777             iNamesize = iLen;          /* no null found; so end of evNT */
7778             iLen      = 0;
7779           }
7780           else
7781           {
7782             iNamesize = pNull - pTemp; /* should be another entry */
7783             iLen      = iLen - iNamesize - 1;
7784 
7785             if (!iLen)                 /* must not end with a null ! */
7786               MNG_ERROR (pData, MNG_ENDWITHNULL);
7787           }
7788 
7789           if (!iX)
7790           {
7791             iCount++;
7792           }
7793           else
7794           {
7795             pEntry->iEventtype       = iEventtype;
7796             pEntry->iMasktype        = iMasktype;
7797             pEntry->iLeft            = iLeft;
7798             pEntry->iRight           = iRight;
7799             pEntry->iTop             = iTop;
7800             pEntry->iBottom          = iBottom;
7801             pEntry->iObjectid        = iObjectid;
7802             pEntry->iIndex           = iIndex;
7803             pEntry->iSegmentnamesize = iNamesize;
7804 
7805             if (iNamesize)
7806             {
7807               MNG_ALLOC (pData, pEntry->zSegmentname, iNamesize+1);
7808               MNG_COPY (pEntry->zSegmentname, pTemp, iNamesize);
7809             }
7810 
7811             pEntry++;
7812           }
7813 
7814           pTemp = pTemp + iNamesize + 1;
7815         }
7816       }
7817     }
7818   }
7819 #endif /* MNG_STORE_CHUNKS */
7820 
7821 #ifdef MNG_SUPPORT_TRACE
7822   MNG_TRACE (pData, MNG_FN_READ_EVNT, MNG_LC_END);
7823 #endif
7824 
7825   return MNG_NOERROR;                  /* done */
7826 }
7827 #endif
7828 #endif
7829 
7830 /* ************************************************************************** */
7831 
7832 #ifndef MNG_OPTIMIZE_CHUNKREADER
READ_CHUNK(mng_read_unknown)7833 READ_CHUNK (mng_read_unknown)
7834 {
7835 #ifdef MNG_SUPPORT_TRACE
7836   MNG_TRACE (pData, MNG_FN_READ_UNKNOWN, MNG_LC_START);
7837 #endif
7838                                        /* sequence checks */
7839 #ifdef MNG_INCLUDE_JNG
7840   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
7841       (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
7842 #else
7843   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
7844       (!pData->bHasBASI) && (!pData->bHasDHDR)    )
7845 #endif
7846     MNG_ERROR (pData, MNG_SEQUENCEERROR);
7847                                        /* critical chunk ? */
7848   if ((((mng_uint32)pData->iChunkname & 0x20000000) == 0)
7849 #ifdef MNG_SKIPCHUNK_SAVE
7850     && (pData->iChunkname != MNG_UINT_SAVE)
7851 #endif
7852 #ifdef MNG_SKIPCHUNK_SEEK
7853     && (pData->iChunkname != MNG_UINT_SEEK)
7854 #endif
7855 #ifdef MNG_SKIPCHUNK_DBYK
7856     && (pData->iChunkname != MNG_UINT_DBYK)
7857 #endif
7858 #ifdef MNG_SKIPCHUNK_ORDR
7859     && (pData->iChunkname != MNG_UINT_ORDR)
7860 #endif
7861       )
7862     MNG_ERROR (pData, MNG_UNKNOWNCRITICAL);
7863 
7864   if (pData->fProcessunknown)          /* let the app handle it ? */
7865   {
7866     mng_bool bOke = pData->fProcessunknown ((mng_handle)pData, pData->iChunkname,
7867                                             iRawlen, (mng_ptr)pRawdata);
7868 
7869     if (!bOke)
7870       MNG_ERROR (pData, MNG_APPMISCERROR);
7871   }
7872 
7873 #ifdef MNG_STORE_CHUNKS
7874   if (pData->bStorechunks)
7875   {                                    /* initialize storage */
7876     mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
7877 
7878     if (iRetcode)                      /* on error bail out */
7879       return iRetcode;
7880                                        /* store the length */
7881     ((mng_chunk_headerp)*ppChunk)->iChunkname = pData->iChunkname;
7882     ((mng_unknown_chunkp)*ppChunk)->iDatasize = iRawlen;
7883 
7884     if (iRawlen == 0)                  /* any data at all ? */
7885       ((mng_unknown_chunkp)*ppChunk)->pData = 0;
7886     else
7887     {                                  /* then store it */
7888       MNG_ALLOC (pData, ((mng_unknown_chunkp)*ppChunk)->pData, iRawlen);
7889       MNG_COPY (((mng_unknown_chunkp)*ppChunk)->pData, pRawdata, iRawlen);
7890     }
7891   }
7892 #endif /* MNG_STORE_CHUNKS */
7893 
7894 #ifdef MNG_SUPPORT_TRACE
7895   MNG_TRACE (pData, MNG_FN_READ_UNKNOWN, MNG_LC_END);
7896 #endif
7897 
7898   return MNG_NOERROR;                  /* done */
7899 }
7900 #endif
7901 
7902 /* ************************************************************************** */
7903 
7904 #endif /* MNG_INCLUDE_READ_PROCS */
7905 
7906 /* ************************************************************************** */
7907 /* *                                                                        * */
7908 /* * chunk write functions                                                  * */
7909 /* *                                                                        * */
7910 /* ************************************************************************** */
7911 
7912 #ifdef MNG_INCLUDE_WRITE_PROCS
7913 
7914 /* ************************************************************************** */
7915 
WRITE_CHUNK(mng_write_ihdr)7916 WRITE_CHUNK (mng_write_ihdr)
7917 {
7918   mng_ihdrp   pIHDR;
7919   mng_uint8p  pRawdata;
7920   mng_uint32  iRawlen;
7921   mng_retcode iRetcode;
7922 
7923 #ifdef MNG_SUPPORT_TRACE
7924   MNG_TRACE (pData, MNG_FN_WRITE_IHDR, MNG_LC_START);
7925 #endif
7926 
7927   pIHDR    = (mng_ihdrp)pChunk;        /* address the proper chunk */
7928   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
7929   iRawlen  = 13;
7930                                        /* fill the output buffer */
7931   mng_put_uint32 (pRawdata,   pIHDR->iWidth);
7932   mng_put_uint32 (pRawdata+4, pIHDR->iHeight);
7933 
7934   *(pRawdata+8)  = pIHDR->iBitdepth;
7935   *(pRawdata+9)  = pIHDR->iColortype;
7936   *(pRawdata+10) = pIHDR->iCompression;
7937   *(pRawdata+11) = pIHDR->iFilter;
7938   *(pRawdata+12) = pIHDR->iInterlace;
7939                                        /* and write it */
7940   iRetcode = write_raw_chunk (pData, pIHDR->sHeader.iChunkname, iRawlen, pRawdata);
7941 
7942 #ifdef MNG_SUPPORT_TRACE
7943   MNG_TRACE (pData, MNG_FN_WRITE_IHDR, MNG_LC_END);
7944 #endif
7945 
7946   return iRetcode;
7947 }
7948 
7949 /* ************************************************************************** */
7950 
WRITE_CHUNK(mng_write_plte)7951 WRITE_CHUNK (mng_write_plte)
7952 {
7953   mng_pltep   pPLTE;
7954   mng_uint8p  pRawdata;
7955   mng_uint32  iRawlen;
7956   mng_retcode iRetcode;
7957   mng_uint8p  pTemp;
7958   mng_uint32  iX;
7959 
7960 #ifdef MNG_SUPPORT_TRACE
7961   MNG_TRACE (pData, MNG_FN_WRITE_PLTE, MNG_LC_START);
7962 #endif
7963 
7964   pPLTE    = (mng_pltep)pChunk;        /* address the proper chunk */
7965 
7966   if (pPLTE->bEmpty)                   /* write empty chunk ? */
7967     iRetcode = write_raw_chunk (pData, pPLTE->sHeader.iChunkname, 0, 0);
7968   else
7969   {
7970     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
7971     iRawlen  = pPLTE->iEntrycount * 3;
7972                                        /* fill the output buffer */
7973     pTemp = pRawdata;
7974 
7975     for (iX = 0; iX < pPLTE->iEntrycount; iX++)
7976     {
7977       *pTemp     = pPLTE->aEntries [iX].iRed;
7978       *(pTemp+1) = pPLTE->aEntries [iX].iGreen;
7979       *(pTemp+2) = pPLTE->aEntries [iX].iBlue;
7980 
7981       pTemp += 3;
7982     }
7983                                        /* and write it */
7984     iRetcode = write_raw_chunk (pData, pPLTE->sHeader.iChunkname, iRawlen, pRawdata);
7985   }
7986 
7987 #ifdef MNG_SUPPORT_TRACE
7988   MNG_TRACE (pData, MNG_FN_WRITE_PLTE, MNG_LC_END);
7989 #endif
7990 
7991   return iRetcode;
7992 }
7993 
7994 /* ************************************************************************** */
7995 
WRITE_CHUNK(mng_write_idat)7996 WRITE_CHUNK (mng_write_idat)
7997 {
7998   mng_idatp   pIDAT;
7999   mng_retcode iRetcode;
8000 
8001 #ifdef MNG_SUPPORT_TRACE
8002   MNG_TRACE (pData, MNG_FN_WRITE_IDAT, MNG_LC_START);
8003 #endif
8004 
8005   pIDAT = (mng_idatp)pChunk;           /* address the proper chunk */
8006 
8007   if (pIDAT->bEmpty)                   /* and write it */
8008     iRetcode = write_raw_chunk (pData, pIDAT->sHeader.iChunkname, 0, 0);
8009   else
8010     iRetcode = write_raw_chunk (pData, pIDAT->sHeader.iChunkname,
8011                                 pIDAT->iDatasize, pIDAT->pData);
8012 
8013 #ifdef MNG_SUPPORT_TRACE
8014   MNG_TRACE (pData, MNG_FN_WRITE_IDAT, MNG_LC_END);
8015 #endif
8016 
8017   return iRetcode;
8018 }
8019 
8020 /* ************************************************************************** */
8021 
WRITE_CHUNK(mng_write_iend)8022 WRITE_CHUNK (mng_write_iend)
8023 {
8024   mng_iendp   pIEND;
8025   mng_retcode iRetcode;
8026 
8027 #ifdef MNG_SUPPORT_TRACE
8028   MNG_TRACE (pData, MNG_FN_WRITE_IEND, MNG_LC_START);
8029 #endif
8030 
8031   pIEND = (mng_iendp)pChunk;           /* address the proper chunk */
8032                                        /* and write it */
8033   iRetcode = write_raw_chunk (pData, pIEND->sHeader.iChunkname, 0, 0);
8034 
8035 #ifdef MNG_SUPPORT_TRACE
8036   MNG_TRACE (pData, MNG_FN_WRITE_IEND, MNG_LC_END);
8037 #endif
8038 
8039   return iRetcode;
8040 }
8041 
8042 /* ************************************************************************** */
8043 
WRITE_CHUNK(mng_write_trns)8044 WRITE_CHUNK (mng_write_trns)
8045 {
8046   mng_trnsp   pTRNS;
8047   mng_uint8p  pRawdata;
8048   mng_uint32  iRawlen;
8049   mng_retcode iRetcode;
8050   mng_uint8p  pTemp;
8051   mng_uint32  iX;
8052 
8053 #ifdef MNG_SUPPORT_TRACE
8054   MNG_TRACE (pData, MNG_FN_WRITE_TRNS, MNG_LC_START);
8055 #endif
8056 
8057   pTRNS = (mng_trnsp)pChunk;           /* address the proper chunk */
8058 
8059   if (pTRNS->bEmpty)                   /* write empty chunk ? */
8060     iRetcode = write_raw_chunk (pData, pTRNS->sHeader.iChunkname, 0, 0);
8061   else
8062   if (pTRNS->bGlobal)                  /* write global chunk ? */
8063     iRetcode = write_raw_chunk (pData, pTRNS->sHeader.iChunkname,
8064                                 pTRNS->iRawlen, (mng_uint8p)pTRNS->aRawdata);
8065   else
8066   {
8067     pRawdata = pData->pWritebuf+8;     /* init output buffer */
8068     iRawlen  = 0;                      /* and default size */
8069 
8070     switch (pTRNS->iType)
8071     {
8072       case 0: {
8073                 iRawlen   = 2;         /* fill the size & output buffer */
8074                 mng_put_uint16 (pRawdata, pTRNS->iGray);
8075 
8076                 break;
8077               }
8078       case 2: {
8079                 iRawlen       = 6;     /* fill the size & output buffer */
8080                 mng_put_uint16 (pRawdata,   pTRNS->iRed);
8081                 mng_put_uint16 (pRawdata+2, pTRNS->iGreen);
8082                 mng_put_uint16 (pRawdata+4, pTRNS->iBlue);
8083 
8084                 break;
8085               }
8086       case 3: {                        /* init output buffer size */
8087                 iRawlen = pTRNS->iCount;
8088 
8089                 pTemp   = pRawdata;    /* fill the output buffer */
8090 
8091                 for (iX = 0; iX < pTRNS->iCount; iX++)
8092                 {
8093                   *pTemp = pTRNS->aEntries[iX];
8094                   pTemp++;
8095                 }
8096 
8097                 break;
8098               }
8099     }
8100                                        /* write the chunk */
8101     iRetcode = write_raw_chunk (pData, pTRNS->sHeader.iChunkname,
8102                                 iRawlen, pRawdata);
8103   }
8104 
8105 #ifdef MNG_SUPPORT_TRACE
8106   MNG_TRACE (pData, MNG_FN_WRITE_TRNS, MNG_LC_END);
8107 #endif
8108 
8109   return iRetcode;
8110 }
8111 
8112 /* ************************************************************************** */
8113 
WRITE_CHUNK(mng_write_gama)8114 WRITE_CHUNK (mng_write_gama)
8115 {
8116   mng_gamap   pGAMA;
8117   mng_uint8p  pRawdata;
8118   mng_uint32  iRawlen;
8119   mng_retcode iRetcode;
8120 
8121 #ifdef MNG_SUPPORT_TRACE
8122   MNG_TRACE (pData, MNG_FN_WRITE_GAMA, MNG_LC_START);
8123 #endif
8124 
8125   pGAMA = (mng_gamap)pChunk;           /* address the proper chunk */
8126 
8127   if (pGAMA->bEmpty)                   /* write empty ? */
8128     iRetcode = write_raw_chunk (pData, pGAMA->sHeader.iChunkname, 0, 0);
8129   else
8130   {
8131     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
8132     iRawlen  = 4;
8133                                        /* fill the buffer */
8134     mng_put_uint32 (pRawdata, pGAMA->iGamma);
8135                                        /* and write it */
8136     iRetcode = write_raw_chunk (pData, pGAMA->sHeader.iChunkname,
8137                                 iRawlen, pRawdata);
8138   }
8139 
8140 #ifdef MNG_SUPPORT_TRACE
8141   MNG_TRACE (pData, MNG_FN_WRITE_GAMA, MNG_LC_END);
8142 #endif
8143 
8144   return iRetcode;
8145 }
8146 
8147 /* ************************************************************************** */
8148 
8149 #ifndef MNG_SKIPCHUNK_cHRM
WRITE_CHUNK(mng_write_chrm)8150 WRITE_CHUNK (mng_write_chrm)
8151 {
8152   mng_chrmp   pCHRM;
8153   mng_uint8p  pRawdata;
8154   mng_uint32  iRawlen;
8155   mng_retcode iRetcode;
8156 
8157 #ifdef MNG_SUPPORT_TRACE
8158   MNG_TRACE (pData, MNG_FN_WRITE_CHRM, MNG_LC_START);
8159 #endif
8160 
8161   pCHRM = (mng_chrmp)pChunk;           /* address the proper chunk */
8162 
8163   if (pCHRM->bEmpty)                   /* write empty ? */
8164     iRetcode = write_raw_chunk (pData, pCHRM->sHeader.iChunkname, 0, 0);
8165   else
8166   {
8167     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
8168     iRawlen  = 32;
8169                                        /* fill the buffer */
8170     mng_put_uint32 (pRawdata,    pCHRM->iWhitepointx);
8171     mng_put_uint32 (pRawdata+4,  pCHRM->iWhitepointy);
8172     mng_put_uint32 (pRawdata+8,  pCHRM->iRedx);
8173     mng_put_uint32 (pRawdata+12, pCHRM->iRedy);
8174     mng_put_uint32 (pRawdata+16, pCHRM->iGreenx);
8175     mng_put_uint32 (pRawdata+20, pCHRM->iGreeny);
8176     mng_put_uint32 (pRawdata+24, pCHRM->iBluex);
8177     mng_put_uint32 (pRawdata+28, pCHRM->iBluey);
8178                                        /* and write it */
8179     iRetcode = write_raw_chunk (pData, pCHRM->sHeader.iChunkname,
8180                                 iRawlen, pRawdata);
8181   }
8182 
8183 #ifdef MNG_SUPPORT_TRACE
8184   MNG_TRACE (pData, MNG_FN_WRITE_CHRM, MNG_LC_END);
8185 #endif
8186 
8187   return iRetcode;
8188 }
8189 #endif
8190 
8191 /* ************************************************************************** */
8192 
WRITE_CHUNK(mng_write_srgb)8193 WRITE_CHUNK (mng_write_srgb)
8194 {
8195   mng_srgbp   pSRGB;
8196   mng_uint8p  pRawdata;
8197   mng_uint32  iRawlen;
8198   mng_retcode iRetcode;
8199 
8200 #ifdef MNG_SUPPORT_TRACE
8201   MNG_TRACE (pData, MNG_FN_WRITE_SRGB, MNG_LC_START);
8202 #endif
8203 
8204   pSRGB = (mng_srgbp)pChunk;           /* address the proper chunk */
8205 
8206   if (pSRGB->bEmpty)                   /* write empty ? */
8207     iRetcode = write_raw_chunk (pData, pSRGB->sHeader.iChunkname, 0, 0);
8208   else
8209   {
8210     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
8211     iRawlen  = 1;
8212                                        /* fill the buffer */
8213     *pRawdata = pSRGB->iRenderingintent;
8214                                        /* and write it */
8215     iRetcode = write_raw_chunk (pData, pSRGB->sHeader.iChunkname,
8216                                 iRawlen, pRawdata);
8217   }
8218 
8219 #ifdef MNG_SUPPORT_TRACE
8220   MNG_TRACE (pData, MNG_FN_WRITE_SRGB, MNG_LC_END);
8221 #endif
8222 
8223   return iRetcode;
8224 }
8225 
8226 /* ************************************************************************** */
8227 
8228 #ifndef MNG_SKIPCHUNK_iCCP
WRITE_CHUNK(mng_write_iccp)8229 WRITE_CHUNK (mng_write_iccp)
8230 {
8231   mng_iccpp   pICCP;
8232   mng_uint8p  pRawdata;
8233   mng_uint32  iRawlen;
8234   mng_retcode iRetcode;
8235   mng_uint8p  pTemp;
8236   mng_uint8p  pBuf = 0;
8237   mng_uint32  iBuflen;
8238   mng_uint32  iReallen;
8239 
8240 #ifdef MNG_SUPPORT_TRACE
8241   MNG_TRACE (pData, MNG_FN_WRITE_ICCP, MNG_LC_START);
8242 #endif
8243 
8244   pICCP = (mng_iccpp)pChunk;           /* address the proper chunk */
8245 
8246   if (pICCP->bEmpty)                   /* write empty ? */
8247     iRetcode = write_raw_chunk (pData, pICCP->sHeader.iChunkname, 0, 0);
8248   else
8249   {                                    /* compress the profile */
8250     iRetcode = deflate_buffer (pData, pICCP->pProfile, pICCP->iProfilesize,
8251                                &pBuf, &iBuflen, &iReallen);
8252 
8253     if (!iRetcode)                     /* still oke ? */
8254     {
8255       pRawdata = pData->pWritebuf+8;   /* init output buffer & size */
8256       iRawlen  = pICCP->iNamesize + 2 + iReallen;
8257                                        /* requires large buffer ? */
8258       if (iRawlen > pData->iWritebufsize)
8259         MNG_ALLOC (pData, pRawdata, iRawlen);
8260 
8261       pTemp = pRawdata;                /* fill the buffer */
8262 
8263       if (pICCP->iNamesize)
8264       {
8265         MNG_COPY (pTemp, pICCP->zName, pICCP->iNamesize);
8266         pTemp += pICCP->iNamesize;
8267       }
8268 
8269       *pTemp     = 0;
8270       *(pTemp+1) = pICCP->iCompression;
8271       pTemp += 2;
8272 
8273       if (iReallen)
8274         MNG_COPY (pTemp, pBuf, iReallen);
8275                                        /* and write it */
8276       iRetcode = write_raw_chunk (pData, pICCP->sHeader.iChunkname,
8277                                   iRawlen, pRawdata);
8278                                        /* drop the temp buffer ? */
8279       if (iRawlen > pData->iWritebufsize)
8280         MNG_FREEX (pData, pRawdata, iRawlen);
8281 
8282     }
8283 
8284     MNG_FREEX (pData, pBuf, iBuflen);  /* always drop the extra buffer */
8285   }
8286 
8287 #ifdef MNG_SUPPORT_TRACE
8288   MNG_TRACE (pData, MNG_FN_WRITE_ICCP, MNG_LC_END);
8289 #endif
8290 
8291   return iRetcode;
8292 }
8293 #endif
8294 
8295 /* ************************************************************************** */
8296 
8297 #ifndef MNG_SKIPCHUNK_tEXt
WRITE_CHUNK(mng_write_text)8298 WRITE_CHUNK (mng_write_text)
8299 {
8300   mng_textp   pTEXT;
8301   mng_uint8p  pRawdata;
8302   mng_uint32  iRawlen;
8303   mng_retcode iRetcode;
8304   mng_uint8p  pTemp;
8305 
8306 #ifdef MNG_SUPPORT_TRACE
8307   MNG_TRACE (pData, MNG_FN_WRITE_TEXT, MNG_LC_START);
8308 #endif
8309 
8310   pTEXT = (mng_textp)pChunk;           /* address the proper chunk */
8311 
8312   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
8313   iRawlen  = pTEXT->iKeywordsize + 1 + pTEXT->iTextsize;
8314                                        /* requires large buffer ? */
8315   if (iRawlen > pData->iWritebufsize)
8316     MNG_ALLOC (pData, pRawdata, iRawlen);
8317 
8318   pTemp = pRawdata;                    /* fill the buffer */
8319 
8320   if (pTEXT->iKeywordsize)
8321   {
8322     MNG_COPY (pTemp, pTEXT->zKeyword, pTEXT->iKeywordsize);
8323     pTemp += pTEXT->iKeywordsize;
8324   }
8325 
8326   *pTemp = 0;
8327   pTemp += 1;
8328 
8329   if (pTEXT->iTextsize)
8330     MNG_COPY (pTemp, pTEXT->zText, pTEXT->iTextsize);
8331                                        /* and write it */
8332   iRetcode = write_raw_chunk (pData, pTEXT->sHeader.iChunkname,
8333                               iRawlen, pRawdata);
8334 
8335   if (iRawlen > pData->iWritebufsize)  /* drop the temp buffer ? */
8336     MNG_FREEX (pData, pRawdata, iRawlen);
8337 
8338 #ifdef MNG_SUPPORT_TRACE
8339   MNG_TRACE (pData, MNG_FN_WRITE_TEXT, MNG_LC_END);
8340 #endif
8341 
8342   return iRetcode;
8343 }
8344 #endif
8345 
8346 /* ************************************************************************** */
8347 
8348 #ifndef MNG_SKIPCHUNK_zTXt
WRITE_CHUNK(mng_write_ztxt)8349 WRITE_CHUNK (mng_write_ztxt)
8350 {
8351   mng_ztxtp   pZTXT;
8352   mng_uint8p  pRawdata;
8353   mng_uint32  iRawlen;
8354   mng_retcode iRetcode;
8355   mng_uint8p  pTemp;
8356   mng_uint8p  pBuf = 0;
8357   mng_uint32  iBuflen;
8358   mng_uint32  iReallen;
8359 
8360 #ifdef MNG_SUPPORT_TRACE
8361   MNG_TRACE (pData, MNG_FN_WRITE_ZTXT, MNG_LC_START);
8362 #endif
8363 
8364   pZTXT = (mng_ztxtp)pChunk;           /* address the proper chunk */
8365                                        /* compress the text */
8366   iRetcode = deflate_buffer (pData, (mng_uint8p)pZTXT->zText, pZTXT->iTextsize,
8367                              &pBuf, &iBuflen, &iReallen);
8368 
8369   if (!iRetcode)                       /* all ok ? */
8370   {
8371     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
8372     iRawlen  = pZTXT->iKeywordsize + 2 + iReallen;
8373                                        /* requires large buffer ? */
8374     if (iRawlen > pData->iWritebufsize)
8375       MNG_ALLOC (pData, pRawdata, iRawlen);
8376 
8377     pTemp = pRawdata;                  /* fill the buffer */
8378 
8379     if (pZTXT->iKeywordsize)
8380     {
8381       MNG_COPY (pTemp, pZTXT->zKeyword, pZTXT->iKeywordsize);
8382       pTemp += pZTXT->iKeywordsize;
8383     }
8384 
8385     *pTemp = 0;                        /* terminator zero */
8386     pTemp++;
8387     *pTemp = 0;                        /* compression type */
8388     pTemp++;
8389 
8390     if (iReallen)
8391       MNG_COPY (pTemp, pBuf, iReallen);
8392                                        /* and write it */
8393     iRetcode = write_raw_chunk (pData, pZTXT->sHeader.iChunkname,
8394                                 iRawlen, pRawdata);
8395                                        /* drop the temp buffer ? */
8396     if (iRawlen > pData->iWritebufsize)
8397       MNG_FREEX (pData, pRawdata, iRawlen);
8398 
8399   }
8400 
8401   MNG_FREEX (pData, pBuf, iBuflen);    /* always drop the compression buffer */
8402 
8403 #ifdef MNG_SUPPORT_TRACE
8404   MNG_TRACE (pData, MNG_FN_WRITE_ZTXT, MNG_LC_END);
8405 #endif
8406 
8407   return iRetcode;
8408 }
8409 #endif
8410 
8411 /* ************************************************************************** */
8412 
8413 #ifndef MNG_SKIPCHUNK_iTXt
WRITE_CHUNK(mng_write_itxt)8414 WRITE_CHUNK (mng_write_itxt)
8415 {
8416   mng_itxtp   pITXT;
8417   mng_uint8p  pRawdata;
8418   mng_uint32  iRawlen;
8419   mng_retcode iRetcode;
8420   mng_uint8p  pTemp;
8421   mng_uint8p  pBuf = 0;
8422   mng_uint32  iBuflen;
8423   mng_uint32  iReallen;
8424 
8425 #ifdef MNG_SUPPORT_TRACE
8426   MNG_TRACE (pData, MNG_FN_WRITE_ITXT, MNG_LC_START);
8427 #endif
8428 
8429   pITXT = (mng_itxtp)pChunk;           /* address the proper chunk */
8430 
8431   if (pITXT->iCompressionflag)         /* compress the text */
8432     iRetcode = deflate_buffer (pData, (mng_uint8p)pITXT->zText, pITXT->iTextsize,
8433                                &pBuf, &iBuflen, &iReallen);
8434   else
8435     iRetcode = MNG_NOERROR;
8436 
8437   if (!iRetcode)                       /* all ok ? */
8438   {
8439     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
8440     iRawlen  = pITXT->iKeywordsize + pITXT->iLanguagesize +
8441                pITXT->iTranslationsize + 5;
8442 
8443     if (pITXT->iCompressionflag)
8444       iRawlen = iRawlen + iReallen;
8445     else
8446       iRawlen = iRawlen + pITXT->iTextsize;
8447                                        /* requires large buffer ? */
8448     if (iRawlen > pData->iWritebufsize)
8449       MNG_ALLOC (pData, pRawdata, iRawlen);
8450 
8451     pTemp = pRawdata;                  /* fill the buffer */
8452 
8453     if (pITXT->iKeywordsize)
8454     {
8455       MNG_COPY (pTemp, pITXT->zKeyword, pITXT->iKeywordsize);
8456       pTemp += pITXT->iKeywordsize;
8457     }
8458 
8459     *pTemp = 0;
8460     pTemp++;
8461     *pTemp = pITXT->iCompressionflag;
8462     pTemp++;
8463     *pTemp = pITXT->iCompressionmethod;
8464     pTemp++;
8465 
8466     if (pITXT->iLanguagesize)
8467     {
8468       MNG_COPY (pTemp, pITXT->zLanguage, pITXT->iLanguagesize);
8469       pTemp += pITXT->iLanguagesize;
8470     }
8471 
8472     *pTemp = 0;
8473     pTemp++;
8474 
8475     if (pITXT->iTranslationsize)
8476     {
8477       MNG_COPY (pTemp, pITXT->zTranslation, pITXT->iTranslationsize);
8478       pTemp += pITXT->iTranslationsize;
8479     }
8480 
8481     *pTemp = 0;
8482     pTemp++;
8483 
8484     if (pITXT->iCompressionflag)
8485     {
8486       if (iReallen)
8487         MNG_COPY (pTemp, pBuf, iReallen);
8488     }
8489     else
8490     {
8491       if (pITXT->iTextsize)
8492         MNG_COPY (pTemp, pITXT->zText, pITXT->iTextsize);
8493     }
8494                                        /* and write it */
8495     iRetcode = write_raw_chunk (pData, pITXT->sHeader.iChunkname,
8496                                 iRawlen, pRawdata);
8497                                        /* drop the temp buffer ? */
8498     if (iRawlen > pData->iWritebufsize)
8499       MNG_FREEX (pData, pRawdata, iRawlen);
8500 
8501   }
8502 
8503   MNG_FREEX (pData, pBuf, iBuflen);    /* always drop the compression buffer */
8504 
8505   if (iRetcode)                        /* on error bail out */
8506     return iRetcode;
8507 
8508 #ifdef MNG_SUPPORT_TRACE
8509   MNG_TRACE (pData, MNG_FN_WRITE_ITXT, MNG_LC_END);
8510 #endif
8511 
8512   return MNG_NOERROR;
8513 }
8514 #endif
8515 
8516 /* ************************************************************************** */
8517 
8518 #ifndef MNG_SKIPCHUNK_bKGD
WRITE_CHUNK(mng_write_bkgd)8519 WRITE_CHUNK (mng_write_bkgd)
8520 {
8521   mng_bkgdp   pBKGD;
8522   mng_uint8p  pRawdata;
8523   mng_uint32  iRawlen;
8524   mng_retcode iRetcode;
8525 
8526 #ifdef MNG_SUPPORT_TRACE
8527   MNG_TRACE (pData, MNG_FN_WRITE_BKGD, MNG_LC_START);
8528 #endif
8529 
8530   pBKGD = (mng_bkgdp)pChunk;           /* address the proper chunk */
8531 
8532   if (pBKGD->bEmpty)                   /* write empty ? */
8533     iRetcode = write_raw_chunk (pData, pBKGD->sHeader.iChunkname, 0, 0);
8534   else
8535   {
8536     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
8537     iRawlen  = 0;                      /* and default size */
8538 
8539     switch (pBKGD->iType)
8540     {
8541       case 0: {                        /* gray */
8542                 iRawlen = 2;           /* fill the size & output buffer */
8543                 mng_put_uint16 (pRawdata, pBKGD->iGray);
8544 
8545                 break;
8546               }
8547       case 2: {                        /* rgb */
8548                 iRawlen = 6;           /* fill the size & output buffer */
8549                 mng_put_uint16 (pRawdata,   pBKGD->iRed);
8550                 mng_put_uint16 (pRawdata+2, pBKGD->iGreen);
8551                 mng_put_uint16 (pRawdata+4, pBKGD->iBlue);
8552 
8553                 break;
8554               }
8555       case 3: {                        /* indexed */
8556                 iRawlen   = 1;         /* fill the size & output buffer */
8557                 *pRawdata = pBKGD->iIndex;
8558 
8559                 break;
8560               }
8561     }
8562                                        /* and write it */
8563     iRetcode = write_raw_chunk (pData, pBKGD->sHeader.iChunkname,
8564                                 iRawlen, pRawdata);
8565   }
8566 
8567 #ifdef MNG_SUPPORT_TRACE
8568   MNG_TRACE (pData, MNG_FN_WRITE_BKGD, MNG_LC_END);
8569 #endif
8570 
8571   return iRetcode;
8572 }
8573 #endif
8574 
8575 /* ************************************************************************** */
8576 
8577 #ifndef MNG_SKIPCHUNK_pHYs
WRITE_CHUNK(mng_write_phys)8578 WRITE_CHUNK (mng_write_phys)
8579 {
8580   mng_physp   pPHYS;
8581   mng_uint8p  pRawdata;
8582   mng_uint32  iRawlen;
8583   mng_retcode iRetcode;
8584 
8585 #ifdef MNG_SUPPORT_TRACE
8586   MNG_TRACE (pData, MNG_FN_WRITE_PHYS, MNG_LC_START);
8587 #endif
8588 
8589   pPHYS = (mng_physp)pChunk;           /* address the proper chunk */
8590 
8591   if (pPHYS->bEmpty)                   /* write empty ? */
8592     iRetcode = write_raw_chunk (pData, pPHYS->sHeader.iChunkname, 0, 0);
8593   else
8594   {
8595     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
8596     iRawlen  = 9;
8597                                        /* fill the output buffer */
8598     mng_put_uint32 (pRawdata,   pPHYS->iSizex);
8599     mng_put_uint32 (pRawdata+4, pPHYS->iSizey);
8600 
8601     *(pRawdata+8) = pPHYS->iUnit;
8602                                        /* and write it */
8603     iRetcode = write_raw_chunk (pData, pPHYS->sHeader.iChunkname,
8604                                 iRawlen, pRawdata);
8605   }
8606 
8607 #ifdef MNG_SUPPORT_TRACE
8608   MNG_TRACE (pData, MNG_FN_WRITE_PHYS, MNG_LC_END);
8609 #endif
8610 
8611   return iRetcode;
8612 }
8613 #endif
8614 
8615 /* ************************************************************************** */
8616 
8617 #ifndef MNG_SKIPCHUNK_sBIT
WRITE_CHUNK(mng_write_sbit)8618 WRITE_CHUNK (mng_write_sbit)
8619 {
8620   mng_sbitp   pSBIT;
8621   mng_uint8p  pRawdata;
8622   mng_uint32  iRawlen;
8623   mng_retcode iRetcode;
8624 
8625 #ifdef MNG_SUPPORT_TRACE
8626   MNG_TRACE (pData, MNG_FN_WRITE_SBIT, MNG_LC_START);
8627 #endif
8628 
8629   pSBIT = (mng_sbitp)pChunk;           /* address the proper chunk */
8630 
8631   if (pSBIT->bEmpty)                   /* write empty ? */
8632     iRetcode = write_raw_chunk (pData, pSBIT->sHeader.iChunkname, 0, 0);
8633   else
8634   {
8635     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
8636     iRawlen  = 0;                      /* and default size */
8637 
8638     switch (pSBIT->iType)
8639     {
8640       case  0: {                       /* gray */
8641                  iRawlen       = 1;    /* fill the size & output buffer */
8642                  *pRawdata     = pSBIT->aBits[0];
8643 
8644                  break;
8645                }
8646       case  2: {                       /* rgb */
8647                  iRawlen       = 3;    /* fill the size & output buffer */
8648                  *pRawdata     = pSBIT->aBits[0];
8649                  *(pRawdata+1) = pSBIT->aBits[1];
8650                  *(pRawdata+2) = pSBIT->aBits[2];
8651 
8652                  break;
8653                }
8654       case  3: {                       /* indexed */
8655                  iRawlen       = 3;    /* fill the size & output buffer */
8656                  *pRawdata     = pSBIT->aBits[0];
8657                  *pRawdata     = pSBIT->aBits[1];
8658                  *pRawdata     = pSBIT->aBits[2];
8659 
8660                  break;
8661                }
8662       case  4: {                       /* gray + alpha */
8663                  iRawlen       = 2;    /* fill the size & output buffer */
8664                  *pRawdata     = pSBIT->aBits[0];
8665                  *(pRawdata+1) = pSBIT->aBits[1];
8666 
8667                  break;
8668                }
8669       case  6: {                       /* rgb + alpha */
8670                  iRawlen       = 4;    /* fill the size & output buffer */
8671                  *pRawdata     = pSBIT->aBits[0];
8672                  *(pRawdata+1) = pSBIT->aBits[1];
8673                  *(pRawdata+2) = pSBIT->aBits[2];
8674                  *(pRawdata+3) = pSBIT->aBits[3];
8675 
8676                  break;
8677                }
8678       case 10: {                       /* jpeg gray */
8679                  iRawlen       = 1;    /* fill the size & output buffer */
8680                  *pRawdata     = pSBIT->aBits[0];
8681 
8682                  break;
8683                }
8684       case 12: {                       /* jpeg rgb */
8685                  iRawlen       = 3;    /* fill the size & output buffer */
8686                  *pRawdata     = pSBIT->aBits[0];
8687                  *(pRawdata+1) = pSBIT->aBits[1];
8688                  *(pRawdata+2) = pSBIT->aBits[2];
8689 
8690                  break;
8691                }
8692       case 14: {                       /* jpeg gray + alpha */
8693                  iRawlen       = 2;    /* fill the size & output buffer */
8694                  *pRawdata     = pSBIT->aBits[0];
8695                  *(pRawdata+1) = pSBIT->aBits[1];
8696 
8697                  break;
8698                }
8699       case 16: {                       /* jpeg rgb + alpha */
8700                  iRawlen       = 4;    /* fill the size & output buffer */
8701                  *pRawdata     = pSBIT->aBits[0];
8702                  *(pRawdata+1) = pSBIT->aBits[1];
8703                  *(pRawdata+2) = pSBIT->aBits[2];
8704                  *(pRawdata+3) = pSBIT->aBits[3];
8705 
8706                  break;
8707                }
8708     }
8709                                        /* and write it */
8710     iRetcode = write_raw_chunk (pData, pSBIT->sHeader.iChunkname,
8711                                 iRawlen, pRawdata);
8712   }
8713 
8714 #ifdef MNG_SUPPORT_TRACE
8715   MNG_TRACE (pData, MNG_FN_WRITE_SBIT, MNG_LC_END);
8716 #endif
8717 
8718   return iRetcode;
8719 }
8720 #endif
8721 
8722 /* ************************************************************************** */
8723 
8724 #ifndef MNG_SKIPCHUNK_sPLT
WRITE_CHUNK(mng_write_splt)8725 WRITE_CHUNK (mng_write_splt)
8726 {
8727   mng_spltp   pSPLT;
8728   mng_uint8p  pRawdata;
8729   mng_uint32  iRawlen;
8730   mng_retcode iRetcode;
8731   mng_uint32  iEntrieslen;
8732   mng_uint8p  pTemp;
8733 
8734 #ifdef MNG_SUPPORT_TRACE
8735   MNG_TRACE (pData, MNG_FN_WRITE_SPLT, MNG_LC_START);
8736 #endif
8737 
8738   pSPLT = (mng_spltp)pChunk;           /* address the proper chunk */
8739 
8740   pRawdata    = pData->pWritebuf+8;    /* init output buffer & size */
8741   iEntrieslen = ((pSPLT->iSampledepth >> 3) * 4 + 2) * pSPLT->iEntrycount;
8742   iRawlen     = pSPLT->iNamesize + 2 + iEntrieslen;
8743                                        /* requires large buffer ? */
8744   if (iRawlen > pData->iWritebufsize)
8745     MNG_ALLOC (pData, pRawdata, iRawlen);
8746 
8747   pTemp = pRawdata;                    /* fill the buffer */
8748 
8749   if (pSPLT->iNamesize)
8750   {
8751     MNG_COPY (pTemp, pSPLT->zName, pSPLT->iNamesize);
8752     pTemp += pSPLT->iNamesize;
8753   }
8754 
8755   *pTemp     = 0;
8756   *(pTemp+1) = pSPLT->iSampledepth;
8757   pTemp += 2;
8758 
8759   if (pSPLT->iEntrycount)
8760     MNG_COPY (pTemp, pSPLT->pEntries, iEntrieslen);
8761                                        /* and write it */
8762   iRetcode = write_raw_chunk (pData, pSPLT->sHeader.iChunkname,
8763                               iRawlen, pRawdata);
8764 
8765   if (iRawlen > pData->iWritebufsize)  /* drop the temp buffer ? */
8766     MNG_FREEX (pData, pRawdata, iRawlen);
8767 
8768 #ifdef MNG_SUPPORT_TRACE
8769   MNG_TRACE (pData, MNG_FN_WRITE_SPLT, MNG_LC_END);
8770 #endif
8771 
8772   return iRetcode;
8773 }
8774 #endif
8775 
8776 /* ************************************************************************** */
8777 
8778 #ifndef MNG_SKIPCHUNK_hIST
WRITE_CHUNK(mng_write_hist)8779 WRITE_CHUNK (mng_write_hist)
8780 {
8781   mng_histp   pHIST;
8782   mng_uint8p  pRawdata;
8783   mng_uint32  iRawlen;
8784   mng_retcode iRetcode;
8785   mng_uint8p  pTemp;
8786   mng_uint32  iX;
8787 
8788 #ifdef MNG_SUPPORT_TRACE
8789   MNG_TRACE (pData, MNG_FN_WRITE_HIST, MNG_LC_START);
8790 #endif
8791 
8792   pHIST = (mng_histp)pChunk;           /* address the proper chunk */
8793 
8794   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
8795   iRawlen  = pHIST->iEntrycount << 1;
8796 
8797   pTemp    = pRawdata;                 /* fill the output buffer */
8798 
8799   for (iX = 0; iX < pHIST->iEntrycount; iX++)
8800   {
8801     mng_put_uint16 (pTemp, pHIST->aEntries [iX]);
8802     pTemp += 2;
8803   }
8804                                        /* and write it */
8805   iRetcode = write_raw_chunk (pData, pHIST->sHeader.iChunkname,
8806                               iRawlen, pRawdata);
8807 
8808 #ifdef MNG_SUPPORT_TRACE
8809   MNG_TRACE (pData, MNG_FN_WRITE_HIST, MNG_LC_END);
8810 #endif
8811 
8812   return iRetcode;
8813 }
8814 #endif
8815 
8816 /* ************************************************************************** */
8817 
8818 #ifndef MNG_SKIPCHUNK_tIME
WRITE_CHUNK(mng_write_time)8819 WRITE_CHUNK (mng_write_time)
8820 {
8821   mng_timep   pTIME;
8822   mng_uint8p  pRawdata;
8823   mng_uint32  iRawlen;
8824   mng_retcode iRetcode;
8825 
8826 #ifdef MNG_SUPPORT_TRACE
8827   MNG_TRACE (pData, MNG_FN_WRITE_TIME, MNG_LC_START);
8828 #endif
8829 
8830   pTIME = (mng_timep)pChunk;           /* address the proper chunk */
8831 
8832   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
8833   iRawlen  = 7;
8834                                        /* fill the output buffer */
8835   mng_put_uint16 (pRawdata, pTIME->iYear);
8836 
8837   *(pRawdata+2) = pTIME->iMonth;
8838   *(pRawdata+3) = pTIME->iDay;
8839   *(pRawdata+4) = pTIME->iHour;
8840   *(pRawdata+5) = pTIME->iMinute;
8841   *(pRawdata+6) = pTIME->iSecond;
8842                                        /* and write it */
8843   iRetcode = write_raw_chunk (pData, pTIME->sHeader.iChunkname,
8844                               iRawlen, pRawdata);
8845 
8846 #ifdef MNG_SUPPORT_TRACE
8847   MNG_TRACE (pData, MNG_FN_WRITE_TIME, MNG_LC_END);
8848 #endif
8849 
8850   return iRetcode;
8851 }
8852 #endif
8853 
8854 /* ************************************************************************** */
8855 
WRITE_CHUNK(mng_write_mhdr)8856 WRITE_CHUNK (mng_write_mhdr)
8857 {
8858   mng_mhdrp   pMHDR;
8859   mng_uint8p  pRawdata;
8860   mng_uint32  iRawlen;
8861   mng_retcode iRetcode;
8862 
8863 #ifdef MNG_SUPPORT_TRACE
8864   MNG_TRACE (pData, MNG_FN_WRITE_MHDR, MNG_LC_START);
8865 #endif
8866 
8867   pMHDR = (mng_mhdrp)pChunk;           /* address the proper chunk */
8868 
8869   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
8870   iRawlen  = 28;
8871                                        /* fill the output buffer */
8872   mng_put_uint32 (pRawdata,    pMHDR->iWidth);
8873   mng_put_uint32 (pRawdata+4,  pMHDR->iHeight);
8874   mng_put_uint32 (pRawdata+8,  pMHDR->iTicks);
8875   mng_put_uint32 (pRawdata+12, pMHDR->iLayercount);
8876   mng_put_uint32 (pRawdata+16, pMHDR->iFramecount);
8877   mng_put_uint32 (pRawdata+20, pMHDR->iPlaytime);
8878   mng_put_uint32 (pRawdata+24, pMHDR->iSimplicity);
8879 
8880                                        /* and write it */
8881   iRetcode = write_raw_chunk (pData, pMHDR->sHeader.iChunkname,
8882                               iRawlen, pRawdata);
8883 
8884 #ifdef MNG_SUPPORT_TRACE
8885   MNG_TRACE (pData, MNG_FN_WRITE_MHDR, MNG_LC_END);
8886 #endif
8887 
8888   return iRetcode;
8889 }
8890 
8891 /* ************************************************************************** */
8892 
WRITE_CHUNK(mng_write_mend)8893 WRITE_CHUNK (mng_write_mend)
8894 {
8895   mng_mendp   pMEND;
8896   mng_retcode iRetcode;
8897 
8898 #ifdef MNG_SUPPORT_TRACE
8899   MNG_TRACE (pData, MNG_FN_WRITE_MEND, MNG_LC_START);
8900 #endif
8901 
8902   pMEND = (mng_mendp)pChunk;           /* address the proper chunk */
8903                                        /* and write it */
8904   iRetcode = write_raw_chunk (pData, pMEND->sHeader.iChunkname, 0, 0);
8905 
8906 #ifdef MNG_SUPPORT_TRACE
8907   MNG_TRACE (pData, MNG_FN_WRITE_MEND, MNG_LC_END);
8908 #endif
8909 
8910   return iRetcode;
8911 }
8912 
8913 /* ************************************************************************** */
8914 
WRITE_CHUNK(mng_write_loop)8915 WRITE_CHUNK (mng_write_loop)
8916 {
8917   mng_loopp   pLOOP;
8918   mng_uint8p  pRawdata;
8919   mng_uint32  iRawlen;
8920   mng_retcode iRetcode;
8921 #ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
8922   mng_uint8p  pTemp1;
8923   mng_uint32p pTemp2;
8924   mng_uint32  iX;
8925 #endif
8926 
8927 #ifdef MNG_SUPPORT_TRACE
8928   MNG_TRACE (pData, MNG_FN_WRITE_LOOP, MNG_LC_START);
8929 #endif
8930 
8931   pLOOP = (mng_loopp)pChunk;           /* address the proper chunk */
8932 
8933   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
8934   iRawlen  = 5;
8935                                        /* fill the output buffer */
8936   *pRawdata = pLOOP->iLevel;
8937   mng_put_uint32 (pRawdata+1,  pLOOP->iRepeat);
8938 
8939   if (pLOOP->iTermination)
8940   {
8941     iRawlen++;
8942     *(pRawdata+5) = pLOOP->iTermination;
8943 
8944     if ((pLOOP->iCount) ||
8945         (pLOOP->iItermin != 1) || (pLOOP->iItermax != 0x7FFFFFFFL))
8946     {
8947       iRawlen += 8;
8948 
8949       mng_put_uint32 (pRawdata+6,  pLOOP->iItermin);
8950       mng_put_uint32 (pRawdata+10, pLOOP->iItermax);
8951 
8952 #ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
8953       if (pLOOP->iCount)
8954       {
8955         iRawlen += pLOOP->iCount * 4;
8956 
8957         pTemp1 = pRawdata+14;
8958         pTemp2 = pLOOP->pSignals;
8959 
8960         for (iX = 0; iX < pLOOP->iCount; iX++)
8961         {
8962           mng_put_uint32 (pTemp1, *pTemp2);
8963 
8964           pTemp1 += 4;
8965           pTemp2++;
8966         }
8967       }
8968 #endif
8969     }
8970   }
8971                                        /* and write it */
8972   iRetcode = write_raw_chunk (pData, pLOOP->sHeader.iChunkname,
8973                               iRawlen, pRawdata);
8974 
8975 #ifdef MNG_SUPPORT_TRACE
8976   MNG_TRACE (pData, MNG_FN_WRITE_LOOP, MNG_LC_END);
8977 #endif
8978 
8979   return iRetcode;
8980 }
8981 
8982 /* ************************************************************************** */
8983 
WRITE_CHUNK(mng_write_endl)8984 WRITE_CHUNK (mng_write_endl)
8985 {
8986   mng_endlp   pENDL;
8987   mng_uint8p  pRawdata;
8988   mng_uint32  iRawlen;
8989   mng_retcode iRetcode;
8990 
8991 #ifdef MNG_SUPPORT_TRACE
8992   MNG_TRACE (pData, MNG_FN_WRITE_ENDL, MNG_LC_START);
8993 #endif
8994 
8995   pENDL     = (mng_endlp)pChunk;       /* address the proper chunk */
8996 
8997   pRawdata  = pData->pWritebuf+8;      /* init output buffer & size */
8998   iRawlen   = 1;
8999 
9000   *pRawdata = pENDL->iLevel;           /* fill the output buffer */
9001                                        /* and write it */
9002   iRetcode  = write_raw_chunk (pData, pENDL->sHeader.iChunkname,
9003                                iRawlen, pRawdata);
9004 
9005 #ifdef MNG_SUPPORT_TRACE
9006   MNG_TRACE (pData, MNG_FN_WRITE_ENDL, MNG_LC_END);
9007 #endif
9008 
9009   return iRetcode;
9010 }
9011 
9012 /* ************************************************************************** */
9013 
WRITE_CHUNK(mng_write_defi)9014 WRITE_CHUNK (mng_write_defi)
9015 {
9016   mng_defip   pDEFI;
9017   mng_uint8p  pRawdata;
9018   mng_uint32  iRawlen;
9019   mng_retcode iRetcode;
9020 
9021 #ifdef MNG_SUPPORT_TRACE
9022   MNG_TRACE (pData, MNG_FN_WRITE_DEFI, MNG_LC_START);
9023 #endif
9024 
9025   pDEFI = (mng_defip)pChunk;           /* address the proper chunk */
9026 
9027   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9028   iRawlen  = 2;
9029                                        /* fill the output buffer */
9030   mng_put_uint16 (pRawdata, pDEFI->iObjectid);
9031 
9032   if ((pDEFI->iDonotshow) || (pDEFI->iConcrete) || (pDEFI->bHasloca) || (pDEFI->bHasclip))
9033   {
9034     iRawlen++;
9035     *(pRawdata+2) = pDEFI->iDonotshow;
9036 
9037     if ((pDEFI->iConcrete) || (pDEFI->bHasloca) || (pDEFI->bHasclip))
9038     {
9039       iRawlen++;
9040       *(pRawdata+3) = pDEFI->iConcrete;
9041 
9042       if ((pDEFI->bHasloca) || (pDEFI->bHasclip))
9043       {
9044         iRawlen += 8;
9045 
9046         mng_put_uint32 (pRawdata+4, pDEFI->iXlocation);
9047         mng_put_uint32 (pRawdata+8, pDEFI->iYlocation);
9048 
9049         if (pDEFI->bHasclip)
9050         {
9051           iRawlen += 16;
9052 
9053           mng_put_uint32 (pRawdata+12, pDEFI->iLeftcb);
9054           mng_put_uint32 (pRawdata+16, pDEFI->iRightcb);
9055           mng_put_uint32 (pRawdata+20, pDEFI->iTopcb);
9056           mng_put_uint32 (pRawdata+24, pDEFI->iBottomcb);
9057         }
9058       }
9059     }
9060   }
9061                                        /* and write it */
9062   iRetcode = write_raw_chunk (pData, pDEFI->sHeader.iChunkname,
9063                               iRawlen, pRawdata);
9064 
9065 #ifdef MNG_SUPPORT_TRACE
9066   MNG_TRACE (pData, MNG_FN_WRITE_DEFI, MNG_LC_END);
9067 #endif
9068 
9069   return iRetcode;
9070 }
9071 
9072 /* ************************************************************************** */
9073 
WRITE_CHUNK(mng_write_basi)9074 WRITE_CHUNK (mng_write_basi)
9075 {
9076   mng_basip   pBASI;
9077   mng_uint8p  pRawdata;
9078   mng_uint32  iRawlen;
9079   mng_retcode iRetcode;
9080   mng_bool    bOpaque;
9081 
9082 #ifdef MNG_SUPPORT_TRACE
9083   MNG_TRACE (pData, MNG_FN_WRITE_BASI, MNG_LC_START);
9084 #endif
9085 
9086   pBASI = (mng_basip)pChunk;           /* address the proper chunk */
9087 
9088 #ifndef MNG_NO_16BIT_SUPPORT
9089   if (pBASI->iBitdepth <= 8)           /* determine opacity alpha-field */
9090 #endif
9091     bOpaque = (mng_bool)(pBASI->iAlpha == 0xFF);
9092 #ifndef MNG_NO_16BIT_SUPPORT
9093   else
9094     bOpaque = (mng_bool)(pBASI->iAlpha == 0xFFFF);
9095 #endif
9096 
9097   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9098   iRawlen  = 13;
9099                                        /* fill the output buffer */
9100   mng_put_uint32 (pRawdata,   pBASI->iWidth);
9101   mng_put_uint32 (pRawdata+4, pBASI->iHeight);
9102 
9103   *(pRawdata+8)  = pBASI->iBitdepth;
9104   *(pRawdata+9)  = pBASI->iColortype;
9105   *(pRawdata+10) = pBASI->iCompression;
9106   *(pRawdata+11) = pBASI->iFilter;
9107   *(pRawdata+12) = pBASI->iInterlace;
9108 
9109   if ((pBASI->iRed) || (pBASI->iGreen) || (pBASI->iBlue) ||
9110       (!bOpaque) || (pBASI->iViewable))
9111   {
9112     iRawlen += 6;
9113     mng_put_uint16 (pRawdata+13, pBASI->iRed);
9114     mng_put_uint16 (pRawdata+15, pBASI->iGreen);
9115     mng_put_uint16 (pRawdata+17, pBASI->iBlue);
9116 
9117     if ((!bOpaque) || (pBASI->iViewable))
9118     {
9119       iRawlen += 2;
9120       mng_put_uint16 (pRawdata+19, pBASI->iAlpha);
9121 
9122       if (pBASI->iViewable)
9123       {
9124         iRawlen++;
9125         *(pRawdata+21) = pBASI->iViewable;
9126       }
9127     }
9128   }
9129                                        /* and write it */
9130   iRetcode = write_raw_chunk (pData, pBASI->sHeader.iChunkname,
9131                               iRawlen, pRawdata);
9132 
9133 #ifdef MNG_SUPPORT_TRACE
9134   MNG_TRACE (pData, MNG_FN_WRITE_BASI, MNG_LC_END);
9135 #endif
9136 
9137   return iRetcode;
9138 }
9139 
9140 /* ************************************************************************** */
9141 
WRITE_CHUNK(mng_write_clon)9142 WRITE_CHUNK (mng_write_clon)
9143 {
9144   mng_clonp   pCLON;
9145   mng_uint8p  pRawdata;
9146   mng_uint32  iRawlen;
9147   mng_retcode iRetcode;
9148 
9149 #ifdef MNG_SUPPORT_TRACE
9150   MNG_TRACE (pData, MNG_FN_WRITE_CLON, MNG_LC_START);
9151 #endif
9152 
9153   pCLON = (mng_clonp)pChunk;           /* address the proper chunk */
9154 
9155   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9156   iRawlen  = 4;
9157                                        /* fill the output buffer */
9158   mng_put_uint16 (pRawdata,   pCLON->iSourceid);
9159   mng_put_uint16 (pRawdata+2, pCLON->iCloneid);
9160 
9161   if ((pCLON->iClonetype) || (pCLON->iDonotshow) || (pCLON->iConcrete) || (pCLON->bHasloca))
9162   {
9163     iRawlen++;
9164     *(pRawdata+4) = pCLON->iClonetype;
9165 
9166     if ((pCLON->iDonotshow) || (pCLON->iConcrete) || (pCLON->bHasloca))
9167     {
9168       iRawlen++;
9169       *(pRawdata+5) = pCLON->iDonotshow;
9170 
9171       if ((pCLON->iConcrete) || (pCLON->bHasloca))
9172       {
9173         iRawlen++;
9174         *(pRawdata+6) = pCLON->iConcrete;
9175 
9176         if (pCLON->bHasloca)
9177         {
9178           iRawlen += 9;
9179           *(pRawdata+7) = pCLON->iLocationtype;
9180           mng_put_int32 (pRawdata+8,  pCLON->iLocationx);
9181           mng_put_int32 (pRawdata+12, pCLON->iLocationy);
9182         }
9183       }
9184     }
9185   }
9186                                        /* and write it */
9187   iRetcode = write_raw_chunk (pData, pCLON->sHeader.iChunkname,
9188                               iRawlen, pRawdata);
9189 
9190 #ifdef MNG_SUPPORT_TRACE
9191   MNG_TRACE (pData, MNG_FN_WRITE_CLON, MNG_LC_END);
9192 #endif
9193 
9194   return iRetcode;
9195 }
9196 
9197 /* ************************************************************************** */
9198 
9199 #ifndef MNG_SKIPCHUNK_PAST
WRITE_CHUNK(mng_write_past)9200 WRITE_CHUNK (mng_write_past)
9201 {
9202   mng_pastp        pPAST;
9203   mng_uint8p       pRawdata;
9204   mng_uint32       iRawlen;
9205   mng_retcode      iRetcode;
9206   mng_past_sourcep pSource;
9207   mng_uint32       iX;
9208   mng_uint8p       pTemp;
9209 
9210 #ifdef MNG_SUPPORT_TRACE
9211   MNG_TRACE (pData, MNG_FN_WRITE_PAST, MNG_LC_START);
9212 #endif
9213 
9214   pPAST = (mng_pastp)pChunk;           /* address the proper chunk */
9215 
9216   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9217   iRawlen  = 11 + (30 * pPAST->iCount);
9218                                        /* requires large buffer ? */
9219   if (iRawlen > pData->iWritebufsize)
9220     MNG_ALLOC (pData, pRawdata, iRawlen);
9221                                        /* fill the output buffer */
9222   mng_put_uint16 (pRawdata,   pPAST->iDestid);
9223 
9224   *(pRawdata+2) = pPAST->iTargettype;
9225 
9226   mng_put_int32  (pRawdata+3, pPAST->iTargetx);
9227   mng_put_int32  (pRawdata+7, pPAST->iTargety);
9228 
9229   pTemp   = pRawdata+11;
9230   pSource = pPAST->pSources;
9231 
9232   for (iX = 0; iX < pPAST->iCount; iX++)
9233   {
9234     mng_put_uint16 (pTemp,    pSource->iSourceid);
9235 
9236     *(pTemp+2)  = pSource->iComposition;
9237     *(pTemp+3)  = pSource->iOrientation;
9238     *(pTemp+4)  = pSource->iOffsettype;
9239 
9240     mng_put_int32  (pTemp+5,  pSource->iOffsetx);
9241     mng_put_int32  (pTemp+9,  pSource->iOffsety);
9242 
9243     *(pTemp+13) = pSource->iBoundarytype;
9244 
9245     mng_put_int32  (pTemp+14, pSource->iBoundaryl);
9246     mng_put_int32  (pTemp+18, pSource->iBoundaryr);
9247     mng_put_int32  (pTemp+22, pSource->iBoundaryt);
9248     mng_put_int32  (pTemp+26, pSource->iBoundaryb);
9249 
9250     pSource++;
9251     pTemp += 30;
9252   }
9253                                        /* and write it */
9254   iRetcode = write_raw_chunk (pData, pPAST->sHeader.iChunkname,
9255                               iRawlen, pRawdata);
9256                                        /* free temporary buffer ? */
9257   if (iRawlen > pData->iWritebufsize)
9258     MNG_FREEX (pData, pRawdata, iRawlen);
9259 
9260 #ifdef MNG_SUPPORT_TRACE
9261   MNG_TRACE (pData, MNG_FN_WRITE_PAST, MNG_LC_END);
9262 #endif
9263 
9264   return iRetcode;
9265 }
9266 #endif
9267 
9268 /* ************************************************************************** */
9269 
WRITE_CHUNK(mng_write_disc)9270 WRITE_CHUNK (mng_write_disc)
9271 {
9272   mng_discp        pDISC;
9273   mng_uint8p       pRawdata;
9274   mng_uint32       iRawlen;
9275   mng_retcode      iRetcode;
9276   mng_uint32       iX;
9277   mng_uint8p       pTemp1;
9278   mng_uint16p      pTemp2;
9279 
9280 #ifdef MNG_SUPPORT_TRACE
9281   MNG_TRACE (pData, MNG_FN_WRITE_DISC, MNG_LC_START);
9282 #endif
9283 
9284   pDISC    = (mng_discp)pChunk;        /* address the proper chunk */
9285 
9286   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9287   iRawlen  = pDISC->iCount << 1;
9288 
9289   pTemp1   = pRawdata;                 /* fill the output buffer */
9290   pTemp2   = pDISC->pObjectids;
9291 
9292   for (iX = 0; iX < pDISC->iCount; iX++)
9293   {
9294     mng_put_uint16 (pTemp1, *pTemp2);
9295 
9296     pTemp2++;
9297     pTemp1 += 2;
9298   }
9299                                        /* and write it */
9300   iRetcode = write_raw_chunk (pData, pDISC->sHeader.iChunkname,
9301                               iRawlen, pRawdata);
9302 
9303 #ifdef MNG_SUPPORT_TRACE
9304   MNG_TRACE (pData, MNG_FN_WRITE_DISC, MNG_LC_END);
9305 #endif
9306 
9307   return iRetcode;
9308 }
9309 
9310 /* ************************************************************************** */
9311 
WRITE_CHUNK(mng_write_back)9312 WRITE_CHUNK (mng_write_back)
9313 {
9314   mng_backp   pBACK;
9315   mng_uint8p  pRawdata;
9316   mng_uint32  iRawlen;
9317   mng_retcode iRetcode;
9318 
9319 #ifdef MNG_SUPPORT_TRACE
9320   MNG_TRACE (pData, MNG_FN_WRITE_BACK, MNG_LC_START);
9321 #endif
9322 
9323   pBACK = (mng_backp)pChunk;           /* address the proper chunk */
9324 
9325   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9326   iRawlen  = 6;
9327                                        /* fill the output buffer */
9328   mng_put_uint16 (pRawdata,   pBACK->iRed);
9329   mng_put_uint16 (pRawdata+2, pBACK->iGreen);
9330   mng_put_uint16 (pRawdata+4, pBACK->iBlue);
9331 
9332   if ((pBACK->iMandatory) || (pBACK->iImageid) || (pBACK->iTile))
9333   {
9334     iRawlen++;
9335     *(pRawdata+6) = pBACK->iMandatory;
9336 
9337     if ((pBACK->iImageid) || (pBACK->iTile))
9338     {
9339       iRawlen += 2;
9340       mng_put_uint16 (pRawdata+7, pBACK->iImageid);
9341 
9342       if (pBACK->iTile)
9343       {
9344         iRawlen++;
9345         *(pRawdata+9) = pBACK->iTile;
9346       }
9347     }
9348   }
9349                                        /* and write it */
9350   iRetcode = write_raw_chunk (pData, pBACK->sHeader.iChunkname,
9351                               iRawlen, pRawdata);
9352 
9353 #ifdef MNG_SUPPORT_TRACE
9354   MNG_TRACE (pData, MNG_FN_WRITE_BACK, MNG_LC_END);
9355 #endif
9356 
9357   return iRetcode;
9358 }
9359 
9360 /* ************************************************************************** */
9361 
WRITE_CHUNK(mng_write_fram)9362 WRITE_CHUNK (mng_write_fram)
9363 {
9364   mng_framp   pFRAM;
9365   mng_uint8p  pRawdata;
9366   mng_uint32  iRawlen;
9367   mng_retcode iRetcode;
9368   mng_uint8p  pTemp;
9369   mng_uint32p pTemp2;
9370   mng_uint32  iX;
9371 
9372 #ifdef MNG_SUPPORT_TRACE
9373   MNG_TRACE (pData, MNG_FN_WRITE_FRAM, MNG_LC_START);
9374 #endif
9375 
9376   pFRAM = (mng_framp)pChunk;           /* address the proper chunk */
9377 
9378   if (pFRAM->bEmpty)                   /* empty ? */
9379     iRetcode = write_raw_chunk (pData, pFRAM->sHeader.iChunkname, 0, 0);
9380   else
9381   {
9382     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
9383     iRawlen  = 1;
9384                                        /* fill the output buffer */
9385     *pRawdata = pFRAM->iMode;
9386 
9387     if ((pFRAM->iNamesize      ) ||
9388         (pFRAM->iChangedelay   ) || (pFRAM->iChangetimeout) ||
9389         (pFRAM->iChangeclipping) || (pFRAM->iChangesyncid )    )
9390     {
9391       if (pFRAM->iNamesize)
9392         MNG_COPY (pRawdata+1, pFRAM->zName, pFRAM->iNamesize);
9393 
9394       iRawlen += pFRAM->iNamesize;
9395       pTemp = pRawdata + pFRAM->iNamesize + 1;
9396 
9397       if ((pFRAM->iChangedelay   ) || (pFRAM->iChangetimeout) ||
9398           (pFRAM->iChangeclipping) || (pFRAM->iChangesyncid )    )
9399       {
9400         *pTemp     = 0;
9401         *(pTemp+1) = pFRAM->iChangedelay;
9402         *(pTemp+2) = pFRAM->iChangetimeout;
9403         *(pTemp+3) = pFRAM->iChangeclipping;
9404         *(pTemp+4) = pFRAM->iChangesyncid;
9405 
9406         iRawlen += 5;
9407         pTemp   += 5;
9408 
9409         if (pFRAM->iChangedelay)
9410         {
9411           mng_put_uint32 (pTemp, pFRAM->iDelay);
9412           iRawlen += 4;
9413           pTemp   += 4;
9414         }
9415 
9416         if (pFRAM->iChangetimeout)
9417         {
9418           mng_put_uint32 (pTemp, pFRAM->iTimeout);
9419           iRawlen += 4;
9420           pTemp   += 4;
9421         }
9422 
9423         if (pFRAM->iChangeclipping)
9424         {
9425           *pTemp = pFRAM->iBoundarytype;
9426 
9427           mng_put_uint32 (pTemp+1,  pFRAM->iBoundaryl);
9428           mng_put_uint32 (pTemp+5,  pFRAM->iBoundaryr);
9429           mng_put_uint32 (pTemp+9,  pFRAM->iBoundaryt);
9430           mng_put_uint32 (pTemp+13, pFRAM->iBoundaryb);
9431 
9432           iRawlen += 17;
9433           pTemp   += 17;
9434         }
9435 
9436         if (pFRAM->iChangesyncid)
9437         {
9438           iRawlen += pFRAM->iCount * 4;
9439           pTemp2 = pFRAM->pSyncids;
9440 
9441           for (iX = 0; iX < pFRAM->iCount; iX++)
9442           {
9443             mng_put_uint32 (pTemp, *pTemp2);
9444 
9445             pTemp2++;
9446             pTemp += 4;
9447           }
9448         }
9449       }
9450     }
9451                                        /* and write it */
9452     iRetcode = write_raw_chunk (pData, pFRAM->sHeader.iChunkname,
9453                                 iRawlen, pRawdata);
9454   }
9455 
9456 #ifdef MNG_SUPPORT_TRACE
9457   MNG_TRACE (pData, MNG_FN_WRITE_FRAM, MNG_LC_END);
9458 #endif
9459 
9460   return iRetcode;
9461 }
9462 
9463 /* ************************************************************************** */
9464 
WRITE_CHUNK(mng_write_move)9465 WRITE_CHUNK (mng_write_move)
9466 {
9467   mng_movep   pMOVE;
9468   mng_uint8p  pRawdata;
9469   mng_uint32  iRawlen;
9470   mng_retcode iRetcode;
9471 
9472 #ifdef MNG_SUPPORT_TRACE
9473   MNG_TRACE (pData, MNG_FN_WRITE_MOVE, MNG_LC_START);
9474 #endif
9475 
9476   pMOVE = (mng_movep)pChunk;           /* address the proper chunk */
9477 
9478   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9479   iRawlen  = 13;
9480                                        /* fill the output buffer */
9481   mng_put_uint16 (pRawdata,   pMOVE->iFirstid);
9482   mng_put_uint16 (pRawdata+2, pMOVE->iLastid);
9483 
9484   *(pRawdata+4) = pMOVE->iMovetype;
9485 
9486   mng_put_int32  (pRawdata+5, pMOVE->iMovex);
9487   mng_put_int32  (pRawdata+9, pMOVE->iMovey);
9488                                        /* and write it */
9489   iRetcode = write_raw_chunk (pData, pMOVE->sHeader.iChunkname,
9490                               iRawlen, pRawdata);
9491 
9492 #ifdef MNG_SUPPORT_TRACE
9493   MNG_TRACE (pData, MNG_FN_WRITE_MOVE, MNG_LC_END);
9494 #endif
9495 
9496   return iRetcode;
9497 }
9498 
9499 /* ************************************************************************** */
9500 
WRITE_CHUNK(mng_write_clip)9501 WRITE_CHUNK (mng_write_clip)
9502 {
9503   mng_clipp   pCLIP;
9504   mng_uint8p  pRawdata;
9505   mng_uint32  iRawlen;
9506   mng_retcode iRetcode;
9507 
9508 #ifdef MNG_SUPPORT_TRACE
9509   MNG_TRACE (pData, MNG_FN_WRITE_CLIP, MNG_LC_START);
9510 #endif
9511 
9512   pCLIP = (mng_clipp)pChunk;           /* address the proper chunk */
9513 
9514   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9515   iRawlen  = 21;
9516                                        /* fill the output buffer */
9517   mng_put_uint16 (pRawdata,    pCLIP->iFirstid);
9518   mng_put_uint16 (pRawdata+2,  pCLIP->iLastid);
9519 
9520   *(pRawdata+4) = pCLIP->iCliptype;
9521 
9522   mng_put_int32  (pRawdata+5,  pCLIP->iClipl);
9523   mng_put_int32  (pRawdata+9,  pCLIP->iClipr);
9524   mng_put_int32  (pRawdata+13, pCLIP->iClipt);
9525   mng_put_int32  (pRawdata+17, pCLIP->iClipb);
9526                                        /* and write it */
9527   iRetcode = write_raw_chunk (pData, pCLIP->sHeader.iChunkname,
9528                               iRawlen, pRawdata);
9529 
9530 #ifdef MNG_SUPPORT_TRACE
9531   MNG_TRACE (pData, MNG_FN_WRITE_CLIP, MNG_LC_END);
9532 #endif
9533 
9534   return iRetcode;
9535 }
9536 
9537 /* ************************************************************************** */
9538 
WRITE_CHUNK(mng_write_show)9539 WRITE_CHUNK (mng_write_show)
9540 {
9541   mng_showp   pSHOW;
9542   mng_uint8p  pRawdata;
9543   mng_uint32  iRawlen;
9544   mng_retcode iRetcode;
9545 
9546 #ifdef MNG_SUPPORT_TRACE
9547   MNG_TRACE (pData, MNG_FN_WRITE_SHOW, MNG_LC_START);
9548 #endif
9549 
9550   pSHOW = (mng_showp)pChunk;           /* address the proper chunk */
9551 
9552   if (pSHOW->bEmpty)                   /* empty ? */
9553     iRetcode = write_raw_chunk (pData, pSHOW->sHeader.iChunkname, 0, 0);
9554   else
9555   {
9556     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
9557     iRawlen  = 2;
9558                                        /* fill the output buffer */
9559     mng_put_uint16 (pRawdata, pSHOW->iFirstid);
9560 
9561     if ((pSHOW->iLastid != pSHOW->iFirstid) || (pSHOW->iMode))
9562     {
9563       iRawlen += 2;
9564       mng_put_uint16 (pRawdata+2, pSHOW->iLastid);
9565 
9566       if (pSHOW->iMode)
9567       {
9568         iRawlen++;
9569         *(pRawdata+4) = pSHOW->iMode;
9570       }
9571     }
9572                                        /* and write it */
9573     iRetcode = write_raw_chunk (pData, pSHOW->sHeader.iChunkname,
9574                                 iRawlen, pRawdata);
9575   }
9576 
9577 #ifdef MNG_SUPPORT_TRACE
9578   MNG_TRACE (pData, MNG_FN_WRITE_SHOW, MNG_LC_END);
9579 #endif
9580 
9581   return iRetcode;
9582 }
9583 
9584 /* ************************************************************************** */
9585 
WRITE_CHUNK(mng_write_term)9586 WRITE_CHUNK (mng_write_term)
9587 {
9588   mng_termp   pTERM;
9589   mng_uint8p  pRawdata;
9590   mng_uint32  iRawlen;
9591   mng_retcode iRetcode;
9592 
9593 #ifdef MNG_SUPPORT_TRACE
9594   MNG_TRACE (pData, MNG_FN_WRITE_TERM, MNG_LC_START);
9595 #endif
9596 
9597   pTERM     = (mng_termp)pChunk;       /* address the proper chunk */
9598 
9599   pRawdata  = pData->pWritebuf+8;      /* init output buffer & size */
9600   iRawlen   = 1;
9601 
9602   *pRawdata = pTERM->iTermaction;      /* fill the output buffer */
9603 
9604   if (pTERM->iTermaction == 3)
9605   {
9606     iRawlen       = 10;
9607     *(pRawdata+1) = pTERM->iIteraction;
9608 
9609     mng_put_uint32 (pRawdata+2, pTERM->iDelay);
9610     mng_put_uint32 (pRawdata+6, pTERM->iItermax);
9611   }
9612                                        /* and write it */
9613   iRetcode = write_raw_chunk (pData, pTERM->sHeader.iChunkname,
9614                               iRawlen, pRawdata);
9615 
9616 #ifdef MNG_SUPPORT_TRACE
9617   MNG_TRACE (pData, MNG_FN_WRITE_TERM, MNG_LC_END);
9618 #endif
9619 
9620   return iRetcode;
9621 }
9622 
9623 /* ************************************************************************** */
9624 
9625 #ifndef MNG_SKIPCHUNK_SAVE
WRITE_CHUNK(mng_write_save)9626 WRITE_CHUNK (mng_write_save)
9627 {
9628   mng_savep       pSAVE;
9629   mng_uint8p      pRawdata;
9630   mng_uint32      iRawlen;
9631   mng_retcode     iRetcode;
9632   mng_save_entryp pEntry;
9633   mng_uint32      iEntrysize;
9634   mng_uint8p      pTemp;
9635   mng_uint32      iX;
9636 
9637 #ifdef MNG_SUPPORT_TRACE
9638   MNG_TRACE (pData, MNG_FN_WRITE_SAVE, MNG_LC_START);
9639 #endif
9640 
9641   pSAVE = (mng_savep)pChunk;           /* address the proper chunk */
9642 
9643   if (pSAVE->bEmpty)                   /* empty ? */
9644     iRetcode = write_raw_chunk (pData, pSAVE->sHeader.iChunkname, 0, 0);
9645   else
9646   {
9647     pRawdata  = pData->pWritebuf+8;    /* init output buffer & size */
9648     iRawlen   = 1;
9649 
9650     *pRawdata = pSAVE->iOffsettype;    /* fill the output buffer */
9651 
9652     if (pSAVE->iOffsettype == 16)
9653       iEntrysize = 25;
9654     else
9655       iEntrysize = 17;
9656 
9657     pTemp  = pRawdata+1;
9658     pEntry = pSAVE->pEntries;
9659 
9660     for (iX = 0; iX < pSAVE->iCount; iX++)
9661     {
9662       if (iX)                          /* put separator null-byte, except the first */
9663       {
9664         *pTemp = 0;
9665         pTemp++;
9666         iRawlen++;
9667       }
9668 
9669       iRawlen += iEntrysize + pEntry->iNamesize;
9670       *pTemp = pEntry->iEntrytype;
9671 
9672       if (pSAVE->iOffsettype == 16)
9673       {
9674         mng_put_uint32 (pTemp+1,  pEntry->iOffset[0]);
9675         mng_put_uint32 (pTemp+5,  pEntry->iOffset[1]);
9676         mng_put_uint32 (pTemp+9,  pEntry->iStarttime[0]);
9677         mng_put_uint32 (pTemp+13, pEntry->iStarttime[1]);
9678         mng_put_uint32 (pTemp+17, pEntry->iLayernr);
9679         mng_put_uint32 (pTemp+21, pEntry->iFramenr);
9680 
9681         pTemp += 25;
9682       }
9683       else
9684       {
9685         mng_put_uint32 (pTemp+1,  pEntry->iOffset[1]);
9686         mng_put_uint32 (pTemp+5,  pEntry->iStarttime[1]);
9687         mng_put_uint32 (pTemp+9,  pEntry->iLayernr);
9688         mng_put_uint32 (pTemp+13, pEntry->iFramenr);
9689 
9690         pTemp += 17;
9691       }
9692 
9693       if (pEntry->iNamesize)
9694       {
9695         MNG_COPY (pTemp, pEntry->zName, pEntry->iNamesize);
9696         pTemp += pEntry->iNamesize;
9697       }
9698 
9699       pEntry++;
9700     }
9701                                        /* and write it */
9702     iRetcode = write_raw_chunk (pData, pSAVE->sHeader.iChunkname,
9703                                 iRawlen, pRawdata);
9704   }
9705 
9706 #ifdef MNG_SUPPORT_TRACE
9707   MNG_TRACE (pData, MNG_FN_WRITE_SAVE, MNG_LC_END);
9708 #endif
9709 
9710   return iRetcode;
9711 }
9712 #endif
9713 
9714 /* ************************************************************************** */
9715 
9716 #ifndef MNG_SKIPCHUNK_SEEK
WRITE_CHUNK(mng_write_seek)9717 WRITE_CHUNK (mng_write_seek)
9718 {
9719   mng_seekp   pSEEK;
9720   mng_uint8p  pRawdata;
9721   mng_uint32  iRawlen;
9722   mng_retcode iRetcode;
9723 
9724 #ifdef MNG_SUPPORT_TRACE
9725   MNG_TRACE (pData, MNG_FN_WRITE_SEEK, MNG_LC_START);
9726 #endif
9727 
9728   pSEEK    = (mng_seekp)pChunk;        /* address the proper chunk */
9729 
9730   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9731   iRawlen  = pSEEK->iNamesize;
9732 
9733   if (iRawlen)                         /* fill the output buffer */
9734     MNG_COPY (pRawdata, pSEEK->zName, iRawlen);
9735                                        /* and write it */
9736   iRetcode = write_raw_chunk (pData, pSEEK->sHeader.iChunkname,
9737                               iRawlen, pRawdata);
9738 
9739 #ifdef MNG_SUPPORT_TRACE
9740   MNG_TRACE (pData, MNG_FN_WRITE_SEEK, MNG_LC_END);
9741 #endif
9742 
9743   return iRetcode;
9744 }
9745 #endif
9746 
9747 /* ************************************************************************** */
9748 
9749 #ifndef MNG_SKIPCHUNK_eXPI
WRITE_CHUNK(mng_write_expi)9750 WRITE_CHUNK (mng_write_expi)
9751 {
9752   mng_expip   pEXPI;
9753   mng_uint8p  pRawdata;
9754   mng_uint32  iRawlen;
9755   mng_retcode iRetcode;
9756 
9757 #ifdef MNG_SUPPORT_TRACE
9758   MNG_TRACE (pData, MNG_FN_WRITE_EXPI, MNG_LC_START);
9759 #endif
9760 
9761   pEXPI    = (mng_expip)pChunk;        /* address the proper chunk */
9762 
9763   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9764   iRawlen  = 2 + pEXPI->iNamesize;
9765                                        /* fill the output buffer */
9766   mng_put_uint16 (pRawdata, pEXPI->iSnapshotid);
9767 
9768   if (pEXPI->iNamesize)
9769     MNG_COPY (pRawdata+2, pEXPI->zName, pEXPI->iNamesize);
9770                                        /* and write it */
9771   iRetcode = write_raw_chunk (pData, pEXPI->sHeader.iChunkname,
9772                               iRawlen, pRawdata);
9773 
9774 #ifdef MNG_SUPPORT_TRACE
9775   MNG_TRACE (pData, MNG_FN_WRITE_EXPI, MNG_LC_END);
9776 #endif
9777 
9778   return iRetcode;
9779 }
9780 #endif
9781 
9782 /* ************************************************************************** */
9783 
9784 #ifndef MNG_SKIPCHUNK_fPRI
WRITE_CHUNK(mng_write_fpri)9785 WRITE_CHUNK (mng_write_fpri)
9786 {
9787   mng_fprip   pFPRI;
9788   mng_uint8p  pRawdata;
9789   mng_uint32  iRawlen;
9790   mng_retcode iRetcode;
9791 
9792 #ifdef MNG_SUPPORT_TRACE
9793   MNG_TRACE (pData, MNG_FN_WRITE_FPRI, MNG_LC_START);
9794 #endif
9795 
9796   pFPRI         = (mng_fprip)pChunk;   /* address the proper chunk */
9797 
9798   pRawdata      = pData->pWritebuf+8;  /* init output buffer & size */
9799   iRawlen       = 2;
9800 
9801   *pRawdata     = pFPRI->iDeltatype;   /* fill the output buffer */
9802   *(pRawdata+1) = pFPRI->iPriority;
9803                                        /* and write it */
9804   iRetcode = write_raw_chunk (pData, pFPRI->sHeader.iChunkname,
9805                               iRawlen, pRawdata);
9806 
9807 #ifdef MNG_SUPPORT_TRACE
9808   MNG_TRACE (pData, MNG_FN_WRITE_FPRI, MNG_LC_END);
9809 #endif
9810 
9811   return iRetcode;
9812 }
9813 #endif
9814 
9815 /* ************************************************************************** */
9816 
9817 #ifndef MNG_SKIPCHUNK_nEED
WRITE_CHUNK(mng_write_need)9818 WRITE_CHUNK (mng_write_need)
9819 {
9820   mng_needp   pNEED;
9821   mng_uint8p  pRawdata;
9822   mng_uint32  iRawlen;
9823   mng_retcode iRetcode;
9824 
9825 #ifdef MNG_SUPPORT_TRACE
9826   MNG_TRACE (pData, MNG_FN_WRITE_NEED, MNG_LC_START);
9827 #endif
9828 
9829   pNEED    = (mng_needp)pChunk;        /* address the proper chunk */
9830 
9831   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9832   iRawlen  = pNEED->iKeywordssize;
9833                                        /* fill the output buffer */
9834   if (pNEED->iKeywordssize)
9835     MNG_COPY (pRawdata, pNEED->zKeywords, pNEED->iKeywordssize);
9836                                        /* and write it */
9837   iRetcode = write_raw_chunk (pData, pNEED->sHeader.iChunkname,
9838                               iRawlen, pRawdata);
9839 
9840 #ifdef MNG_SUPPORT_TRACE
9841   MNG_TRACE (pData, MNG_FN_WRITE_NEED, MNG_LC_END);
9842 #endif
9843 
9844   return iRetcode;
9845 }
9846 #endif
9847 
9848 /* ************************************************************************** */
9849 
9850 #ifndef MNG_SKIPCHUNK_pHYg
WRITE_CHUNK(mng_write_phyg)9851 WRITE_CHUNK (mng_write_phyg)
9852 {
9853   mng_phygp   pPHYG;
9854   mng_uint8p  pRawdata;
9855   mng_uint32  iRawlen;
9856   mng_retcode iRetcode;
9857 
9858 #ifdef MNG_SUPPORT_TRACE
9859   MNG_TRACE (pData, MNG_FN_WRITE_PHYG, MNG_LC_START);
9860 #endif
9861 
9862   pPHYG = (mng_phygp)pChunk;           /* address the proper chunk */
9863 
9864   if (pPHYG->bEmpty)                   /* write empty ? */
9865     iRetcode = write_raw_chunk (pData, pPHYG->sHeader.iChunkname, 0, 0);
9866   else
9867   {
9868     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
9869     iRawlen  = 9;
9870                                        /* fill the output buffer */
9871     mng_put_uint32 (pRawdata,   pPHYG->iSizex);
9872     mng_put_uint32 (pRawdata+4, pPHYG->iSizey);
9873 
9874     *(pRawdata+8) = pPHYG->iUnit;
9875                                        /* and write it */
9876     iRetcode = write_raw_chunk (pData, pPHYG->sHeader.iChunkname,
9877                                 iRawlen, pRawdata);
9878   }
9879 
9880 #ifdef MNG_SUPPORT_TRACE
9881   MNG_TRACE (pData, MNG_FN_WRITE_PHYG, MNG_LC_END);
9882 #endif
9883 
9884   return iRetcode;
9885 }
9886 #endif
9887 
9888 /* ************************************************************************** */
9889 
9890 /* B004 */
9891 #ifdef MNG_INCLUDE_JNG
9892 /* B004 */
WRITE_CHUNK(mng_write_jhdr)9893 WRITE_CHUNK (mng_write_jhdr)
9894 {
9895   mng_jhdrp   pJHDR;
9896   mng_uint8p  pRawdata;
9897   mng_uint32  iRawlen;
9898   mng_retcode iRetcode;
9899 
9900 #ifdef MNG_SUPPORT_TRACE
9901   MNG_TRACE (pData, MNG_FN_WRITE_JHDR, MNG_LC_START);
9902 #endif
9903 
9904   pJHDR    = (mng_jhdrp)pChunk;        /* address the proper chunk */
9905   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
9906   iRawlen  = 16;
9907                                        /* fill the output buffer */
9908   mng_put_uint32 (pRawdata,   pJHDR->iWidth);
9909   mng_put_uint32 (pRawdata+4, pJHDR->iHeight);
9910 
9911   *(pRawdata+8)  = pJHDR->iColortype;
9912   *(pRawdata+9)  = pJHDR->iImagesampledepth;
9913   *(pRawdata+10) = pJHDR->iImagecompression;
9914   *(pRawdata+11) = pJHDR->iImageinterlace;
9915   *(pRawdata+12) = pJHDR->iAlphasampledepth;
9916   *(pRawdata+13) = pJHDR->iAlphacompression;
9917   *(pRawdata+14) = pJHDR->iAlphafilter;
9918   *(pRawdata+15) = pJHDR->iAlphainterlace;
9919                                        /* and write it */
9920   iRetcode = write_raw_chunk (pData, pJHDR->sHeader.iChunkname, iRawlen, pRawdata);
9921 
9922 #ifdef MNG_SUPPORT_TRACE
9923   MNG_TRACE (pData, MNG_FN_WRITE_JHDR, MNG_LC_END);
9924 #endif
9925 
9926   return iRetcode;
9927 }
9928 #else
9929 #define write_jhdr 0
9930 /* B004 */
9931 #endif /* MNG_INCLUDE_JNG */
9932 /* B004 */
9933 
9934 /* ************************************************************************** */
9935 
9936 #ifdef MNG_INCLUDE_JNG
WRITE_CHUNK(mng_write_jdaa)9937 WRITE_CHUNK (mng_write_jdaa)
9938 {
9939   mng_jdatp   pJDAA;
9940   mng_retcode iRetcode;
9941 
9942 #ifdef MNG_SUPPORT_TRACE
9943   MNG_TRACE (pData, MNG_FN_WRITE_JDAA, MNG_LC_START);
9944 #endif
9945 
9946   pJDAA = (mng_jdaap)pChunk;           /* address the proper chunk */
9947 
9948   if (pJDAA->bEmpty)                   /* and write it */
9949     iRetcode = write_raw_chunk (pData, pJDAA->sHeader.iChunkname, 0, 0);
9950   else
9951     iRetcode = write_raw_chunk (pData, pJDAA->sHeader.iChunkname,
9952                                 pJDAA->iDatasize, pJDAA->pData);
9953 
9954 #ifdef MNG_SUPPORT_TRACE
9955   MNG_TRACE (pData, MNG_FN_WRITE_JDAA, MNG_LC_END);
9956 #endif
9957 
9958   return iRetcode;
9959 }
9960 #else
9961 #define write_jdaa 0
9962 #endif /* MNG_INCLUDE_JNG */
9963 
9964 /* ************************************************************************** */
9965 
9966 /* B004 */
9967 #ifdef MNG_INCLUDE_JNG
9968 /* B004 */
WRITE_CHUNK(mng_write_jdat)9969 WRITE_CHUNK (mng_write_jdat)
9970 {
9971   mng_jdatp   pJDAT;
9972   mng_retcode iRetcode;
9973 
9974 #ifdef MNG_SUPPORT_TRACE
9975   MNG_TRACE (pData, MNG_FN_WRITE_JDAT, MNG_LC_START);
9976 #endif
9977 
9978   pJDAT = (mng_jdatp)pChunk;           /* address the proper chunk */
9979 
9980   if (pJDAT->bEmpty)                   /* and write it */
9981     iRetcode = write_raw_chunk (pData, pJDAT->sHeader.iChunkname, 0, 0);
9982   else
9983     iRetcode = write_raw_chunk (pData, pJDAT->sHeader.iChunkname,
9984                                 pJDAT->iDatasize, pJDAT->pData);
9985 
9986 #ifdef MNG_SUPPORT_TRACE
9987   MNG_TRACE (pData, MNG_FN_WRITE_JDAT, MNG_LC_END);
9988 #endif
9989 
9990   return iRetcode;
9991 }
9992 #else
9993 #define write_jdat 0
9994 /* B004 */
9995 #endif /* MNG_INCLUDE_JNG */
9996 /* B004 */
9997 
9998 /* ************************************************************************** */
9999 
10000 /* B004 */
10001 #ifdef MNG_INCLUDE_JNG
10002 /* B004 */
WRITE_CHUNK(mng_write_jsep)10003 WRITE_CHUNK (mng_write_jsep)
10004 {
10005   mng_jsepp   pJSEP;
10006   mng_retcode iRetcode;
10007 
10008 #ifdef MNG_SUPPORT_TRACE
10009   MNG_TRACE (pData, MNG_FN_WRITE_JSEP, MNG_LC_START);
10010 #endif
10011 
10012   pJSEP = (mng_jsepp)pChunk;           /* address the proper chunk */
10013                                        /* and write it */
10014   iRetcode = write_raw_chunk (pData, pJSEP->sHeader.iChunkname, 0, 0);
10015 
10016 #ifdef MNG_SUPPORT_TRACE
10017   MNG_TRACE (pData, MNG_FN_WRITE_JSEP, MNG_LC_END);
10018 #endif
10019 
10020   return iRetcode;
10021 }
10022 #else
10023 #define write_jsep 0
10024 /* B004 */
10025 #endif /* MNG_INCLUDE_JNG */
10026 /* B004 */
10027 
10028 /* ************************************************************************** */
10029 
10030 #ifndef MNG_NO_DELTA_PNG
WRITE_CHUNK(mng_write_dhdr)10031 WRITE_CHUNK (mng_write_dhdr)
10032 {
10033   mng_dhdrp   pDHDR;
10034   mng_uint8p  pRawdata;
10035   mng_uint32  iRawlen;
10036   mng_retcode iRetcode;
10037 
10038 #ifdef MNG_SUPPORT_TRACE
10039   MNG_TRACE (pData, MNG_FN_WRITE_DHDR, MNG_LC_START);
10040 #endif
10041 
10042   pDHDR    = (mng_dhdrp)pChunk;        /* address the proper chunk */
10043 
10044   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
10045   iRawlen  = 4;
10046                                        /* fill the output buffer */
10047   mng_put_uint16 (pRawdata, pDHDR->iObjectid);
10048 
10049   *(pRawdata+2) = pDHDR->iImagetype;
10050   *(pRawdata+3) = pDHDR->iDeltatype;
10051 
10052   if (pDHDR->iDeltatype != 7)
10053   {
10054     iRawlen += 8;
10055     mng_put_uint32 (pRawdata+4, pDHDR->iBlockwidth);
10056     mng_put_uint32 (pRawdata+8, pDHDR->iBlockheight);
10057 
10058     if (pDHDR->iDeltatype != 0)
10059     {
10060       iRawlen += 8;
10061       mng_put_uint32 (pRawdata+12, pDHDR->iBlockx);
10062       mng_put_uint32 (pRawdata+16, pDHDR->iBlocky);
10063     }
10064   }
10065                                        /* and write it */
10066   iRetcode = write_raw_chunk (pData, pDHDR->sHeader.iChunkname,
10067                               iRawlen, pRawdata);
10068 
10069 #ifdef MNG_SUPPORT_TRACE
10070   MNG_TRACE (pData, MNG_FN_WRITE_DHDR, MNG_LC_END);
10071 #endif
10072 
10073   return iRetcode;
10074 }
10075 #endif
10076 
10077 /* ************************************************************************** */
10078 
10079 #ifndef MNG_NO_DELTA_PNG
WRITE_CHUNK(mng_write_prom)10080 WRITE_CHUNK (mng_write_prom)
10081 {
10082   mng_promp   pPROM;
10083   mng_uint8p  pRawdata;
10084   mng_uint32  iRawlen;
10085   mng_retcode iRetcode;
10086 
10087 #ifdef MNG_SUPPORT_TRACE
10088   MNG_TRACE (pData, MNG_FN_WRITE_PROM, MNG_LC_START);
10089 #endif
10090 
10091   pPROM    = (mng_promp)pChunk;        /* address the proper chunk */
10092 
10093   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
10094   iRawlen  = 3;
10095 
10096   *pRawdata     = pPROM->iColortype;   /* fill the output buffer */
10097   *(pRawdata+1) = pPROM->iSampledepth;
10098   *(pRawdata+2) = pPROM->iFilltype;
10099                                        /* and write it */
10100   iRetcode = write_raw_chunk (pData, pPROM->sHeader.iChunkname,
10101                               iRawlen, pRawdata);
10102 
10103 #ifdef MNG_SUPPORT_TRACE
10104   MNG_TRACE (pData, MNG_FN_WRITE_PROM, MNG_LC_END);
10105 #endif
10106 
10107   return iRetcode;
10108 }
10109 #endif
10110 
10111 /* ************************************************************************** */
10112 
10113 #ifndef MNG_NO_DELTA_PNG
WRITE_CHUNK(mng_write_ipng)10114 WRITE_CHUNK (mng_write_ipng)
10115 {
10116   mng_ipngp   pIPNG;
10117   mng_retcode iRetcode;
10118 
10119 #ifdef MNG_SUPPORT_TRACE
10120   MNG_TRACE (pData, MNG_FN_WRITE_IPNG, MNG_LC_START);
10121 #endif
10122 
10123   pIPNG = (mng_ipngp)pChunk;           /* address the proper chunk */
10124                                        /* and write it */
10125   iRetcode = write_raw_chunk (pData, pIPNG->sHeader.iChunkname, 0, 0);
10126 
10127 #ifdef MNG_SUPPORT_TRACE
10128   MNG_TRACE (pData, MNG_FN_WRITE_IPNG, MNG_LC_END);
10129 #endif
10130 
10131   return iRetcode;
10132 }
10133 #endif
10134 
10135 /* ************************************************************************** */
10136 
10137 #ifndef MNG_NO_DELTA_PNG
WRITE_CHUNK(mng_write_pplt)10138 WRITE_CHUNK (mng_write_pplt)
10139 {
10140   mng_ppltp       pPPLT;
10141   mng_uint8p      pRawdata;
10142   mng_uint32      iRawlen;
10143   mng_retcode     iRetcode;
10144   mng_pplt_entryp pEntry;
10145   mng_uint8p      pTemp;
10146   mng_uint32      iX;
10147   mng_bool        bHasgroup;
10148   mng_uint8p      pLastid = 0;
10149 
10150 #ifdef MNG_SUPPORT_TRACE
10151   MNG_TRACE (pData, MNG_FN_WRITE_PPLT, MNG_LC_START);
10152 #endif
10153 
10154   pPPLT = (mng_ppltp)pChunk;           /* address the proper chunk */
10155 
10156   pRawdata  = pData->pWritebuf+8;      /* init output buffer & size */
10157   iRawlen   = 1;
10158 
10159   *pRawdata = pPPLT->iDeltatype;       /* fill the output buffer */
10160 
10161   pTemp     = pRawdata+1;
10162   bHasgroup = MNG_FALSE;
10163 
10164   for (iX = 0; iX < pPPLT->iCount; iX++)
10165   {
10166     pEntry = &pPPLT->aEntries[iX];
10167 
10168     if (pEntry->bUsed)                 /* valid entry ? */
10169     {
10170       if (!bHasgroup)                  /* start a new group ? */
10171       {
10172         bHasgroup  = MNG_TRUE;
10173         pLastid    = pTemp+1;
10174 
10175         *pTemp     = (mng_uint8)iX;
10176         *(pTemp+1) = 0;
10177 
10178         pTemp += 2;
10179         iRawlen += 2;
10180       }
10181 
10182       switch (pPPLT->iDeltatype)       /* add group-entry depending on type */
10183       {
10184         case 0: ;
10185         case 1: {
10186                   *pTemp     = pEntry->iRed;
10187                   *(pTemp+1) = pEntry->iGreen;
10188                   *(pTemp+2) = pEntry->iBlue;
10189 
10190                   pTemp += 3;
10191                   iRawlen += 3;
10192 
10193                   break;
10194                 }
10195 
10196         case 2: ;
10197         case 3: {
10198                   *pTemp     = pEntry->iAlpha;
10199 
10200                   pTemp++;
10201                   iRawlen++;
10202 
10203                   break;
10204                 }
10205 
10206         case 4: ;
10207         case 5: {
10208                   *pTemp     = pEntry->iRed;
10209                   *(pTemp+1) = pEntry->iGreen;
10210                   *(pTemp+2) = pEntry->iBlue;
10211                   *(pTemp+3) = pEntry->iAlpha;
10212 
10213                   pTemp += 4;
10214                   iRawlen += 4;
10215 
10216                   break;
10217                 }
10218 
10219       }
10220     }
10221     else
10222     {
10223       if (bHasgroup)                   /* finish off a group ? */
10224         *pLastid = (mng_uint8)(iX-1);
10225 
10226       bHasgroup = MNG_FALSE;
10227     }
10228   }
10229 
10230   if (bHasgroup)                       /* last group unfinished ? */
10231     *pLastid = (mng_uint8)(pPPLT->iCount-1);
10232                                        /* write the output buffer */
10233   iRetcode = write_raw_chunk (pData, pPPLT->sHeader.iChunkname,
10234                               iRawlen, pRawdata);
10235 
10236 #ifdef MNG_SUPPORT_TRACE
10237   MNG_TRACE (pData, MNG_FN_WRITE_PPLT, MNG_LC_END);
10238 #endif
10239 
10240   return iRetcode;
10241 }
10242 #endif
10243 
10244 /* ************************************************************************** */
10245 
10246 #ifndef MNG_NO_DELTA_PNG
10247 #ifdef MNG_INCLUDE_JNG
WRITE_CHUNK(mng_write_ijng)10248 WRITE_CHUNK (mng_write_ijng)
10249 {
10250   mng_ijngp   pIJNG;
10251   mng_retcode iRetcode;
10252 
10253 #ifdef MNG_SUPPORT_TRACE
10254   MNG_TRACE (pData, MNG_FN_WRITE_IJNG, MNG_LC_START);
10255 #endif
10256 
10257   pIJNG = (mng_ijngp)pChunk;           /* address the proper chunk */
10258                                        /* and write it */
10259   iRetcode = write_raw_chunk (pData, pIJNG->sHeader.iChunkname, 0, 0);
10260 
10261 #ifdef MNG_SUPPORT_TRACE
10262   MNG_TRACE (pData, MNG_FN_WRITE_IJNG, MNG_LC_END);
10263 #endif
10264 
10265   return iRetcode;
10266 }
10267 #endif
10268 #endif
10269 
10270 /* ************************************************************************** */
10271 
10272 #ifndef MNG_NO_DELTA_PNG
WRITE_CHUNK(mng_write_drop)10273 WRITE_CHUNK (mng_write_drop)
10274 {
10275   mng_dropp        pDROP;
10276   mng_uint8p       pRawdata;
10277   mng_uint32       iRawlen;
10278   mng_retcode      iRetcode;
10279   mng_uint32       iX;
10280   mng_uint8p       pTemp1;
10281   mng_chunkidp     pTemp2;
10282 
10283 #ifdef MNG_SUPPORT_TRACE
10284   MNG_TRACE (pData, MNG_FN_WRITE_DROP, MNG_LC_START);
10285 #endif
10286 
10287   pDROP    = (mng_dropp)pChunk;        /* address the proper chunk */
10288 
10289   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
10290   iRawlen  = pDROP->iCount << 2;
10291 
10292   pTemp1   = pRawdata;                 /* fill the output buffer */
10293   pTemp2   = pDROP->pChunknames;
10294 
10295   for (iX = 0; iX < pDROP->iCount; iX++)
10296   {
10297     mng_put_uint32 (pTemp1, (mng_uint32)*pTemp2);
10298 
10299     pTemp2++;
10300     pTemp1 += 4;
10301   }
10302                                        /* and write it */
10303   iRetcode = write_raw_chunk (pData, pDROP->sHeader.iChunkname,
10304                               iRawlen, pRawdata);
10305 
10306 #ifdef MNG_SUPPORT_TRACE
10307   MNG_TRACE (pData, MNG_FN_WRITE_DROP, MNG_LC_END);
10308 #endif
10309 
10310   return iRetcode;
10311 }
10312 #endif
10313 
10314 /* ************************************************************************** */
10315 
10316 #ifndef MNG_NO_DELTA_PNG
10317 #ifndef MNG_SKIPCHUNK_DBYK
WRITE_CHUNK(mng_write_dbyk)10318 WRITE_CHUNK (mng_write_dbyk)
10319 {
10320   mng_dbykp   pDBYK;
10321   mng_uint8p  pRawdata;
10322   mng_uint32  iRawlen;
10323   mng_retcode iRetcode;
10324 
10325 #ifdef MNG_SUPPORT_TRACE
10326   MNG_TRACE (pData, MNG_FN_WRITE_DBYK, MNG_LC_START);
10327 #endif
10328 
10329   pDBYK = (mng_dbykp)pChunk;           /* address the proper chunk */
10330 
10331   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
10332   iRawlen  = 5 + pDBYK->iKeywordssize;
10333                                        /* fill the output buffer */
10334   mng_put_uint32 (pRawdata, pDBYK->iChunkname);
10335   *(pRawdata+4) = pDBYK->iPolarity;
10336 
10337   if (pDBYK->iKeywordssize)
10338     MNG_COPY (pRawdata+5, pDBYK->zKeywords, pDBYK->iKeywordssize);
10339                                        /* and write it */
10340   iRetcode = write_raw_chunk (pData, pDBYK->sHeader.iChunkname,
10341                               iRawlen, pRawdata);
10342 
10343 #ifdef MNG_SUPPORT_TRACE
10344   MNG_TRACE (pData, MNG_FN_WRITE_DBYK, MNG_LC_END);
10345 #endif
10346 
10347   return iRetcode;
10348 }
10349 #endif
10350 #endif
10351 
10352 /* ************************************************************************** */
10353 
10354 #ifndef MNG_NO_DELTA_PNG
10355 #ifndef MNG_SKIPCHUNK_ORDR
WRITE_CHUNK(mng_write_ordr)10356 WRITE_CHUNK (mng_write_ordr)
10357 {
10358   mng_ordrp       pORDR;
10359   mng_uint8p      pRawdata;
10360   mng_uint32      iRawlen;
10361   mng_retcode     iRetcode;
10362   mng_uint8p      pTemp;
10363   mng_ordr_entryp pEntry;
10364   mng_uint32      iX;
10365 
10366 #ifdef MNG_SUPPORT_TRACE
10367   MNG_TRACE (pData, MNG_FN_WRITE_ORDR, MNG_LC_START);
10368 #endif
10369 
10370   pORDR    = (mng_ordrp)pChunk;        /* address the proper chunk */
10371 
10372   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
10373   iRawlen  = pORDR->iCount * 5;
10374 
10375   pTemp    = pRawdata;                 /* fill the output buffer */
10376   pEntry   = pORDR->pEntries;
10377 
10378   for (iX = 0; iX < pORDR->iCount; iX++)
10379   {
10380     mng_put_uint32 (pTemp, pEntry->iChunkname);
10381     *(pTemp+4) = pEntry->iOrdertype;
10382     pTemp += 5;
10383     pEntry++;
10384   }
10385                                        /* and write it */
10386   iRetcode = write_raw_chunk (pData, pORDR->sHeader.iChunkname,
10387                               iRawlen, pRawdata);
10388 
10389 #ifdef MNG_SUPPORT_TRACE
10390   MNG_TRACE (pData, MNG_FN_WRITE_ORDR, MNG_LC_END);
10391 #endif
10392 
10393   return iRetcode;
10394 }
10395 #endif
10396 #endif
10397 
10398 /* ************************************************************************** */
10399 
WRITE_CHUNK(mng_write_magn)10400 WRITE_CHUNK (mng_write_magn)
10401 {
10402   mng_magnp   pMAGN;
10403   mng_uint8p  pRawdata;
10404   mng_uint32  iRawlen;
10405   mng_retcode iRetcode;
10406 
10407 #ifdef MNG_SUPPORT_TRACE
10408   MNG_TRACE (pData, MNG_FN_WRITE_MAGN, MNG_LC_START);
10409 #endif
10410 
10411   pMAGN    = (mng_magnp)pChunk;        /* address the proper chunk */
10412 
10413   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
10414   iRawlen  = 18;
10415                                        /* fill the output buffer */
10416   mng_put_uint16 (pRawdata,    pMAGN->iFirstid);
10417   mng_put_uint16 (pRawdata+2,  pMAGN->iLastid);
10418   *(pRawdata+4) = pMAGN->iMethodX;
10419   mng_put_uint16 (pRawdata+5,  pMAGN->iMX);
10420   mng_put_uint16 (pRawdata+7,  pMAGN->iMY);
10421   mng_put_uint16 (pRawdata+9,  pMAGN->iML);
10422   mng_put_uint16 (pRawdata+11, pMAGN->iMR);
10423   mng_put_uint16 (pRawdata+13, pMAGN->iMT);
10424   mng_put_uint16 (pRawdata+15, pMAGN->iMB);
10425   *(pRawdata+17) = pMAGN->iMethodY;
10426                                        /* optimize length */
10427   if (pMAGN->iMethodY == pMAGN->iMethodX)
10428   {
10429     iRawlen--;
10430 
10431     if (pMAGN->iMB == pMAGN->iMY)
10432     {
10433       iRawlen -= 2;
10434 
10435       if (pMAGN->iMT == pMAGN->iMY)
10436       {
10437         iRawlen -= 2;
10438 
10439         if (pMAGN->iMR == pMAGN->iMX)
10440         {
10441           iRawlen -= 2;
10442 
10443           if (pMAGN->iML == pMAGN->iMX)
10444           {
10445             iRawlen -= 2;
10446 
10447             if (pMAGN->iMY == pMAGN->iMX)
10448             {
10449               iRawlen -= 2;
10450 
10451               if (pMAGN->iMX == 1)
10452               {
10453                 iRawlen -= 2;
10454 
10455                 if (pMAGN->iMethodX == 0)
10456                 {
10457                   iRawlen--;
10458 
10459                   if (pMAGN->iLastid == pMAGN->iFirstid)
10460                   {
10461                     iRawlen -= 2;
10462 
10463                     if (pMAGN->iFirstid == 0)
10464                       iRawlen = 0;
10465 
10466                   }
10467                 }
10468               }
10469             }
10470           }
10471         }
10472       }
10473     }
10474   }
10475                                        /* and write it */
10476   iRetcode = write_raw_chunk (pData, pMAGN->sHeader.iChunkname,
10477                               iRawlen, pRawdata);
10478 
10479 #ifdef MNG_SUPPORT_TRACE
10480   MNG_TRACE (pData, MNG_FN_WRITE_MAGN, MNG_LC_END);
10481 #endif
10482 
10483   return iRetcode;
10484 }
10485 
10486 /* ************************************************************************** */
10487 
10488 #ifdef MNG_INCLUDE_MPNG_PROPOSAL
WRITE_CHUNK(mng_write_mpng)10489 WRITE_CHUNK (mng_write_mpng)
10490 {
10491   mng_mpngp   pMPNG;
10492   mng_uint8p  pRawdata;
10493   mng_uint32  iRawlen;
10494   mng_retcode iRetcode;
10495   mng_uint8p  pBuf = 0;
10496   mng_uint32  iBuflen;
10497   mng_uint32  iReallen;
10498 
10499 #ifdef MNG_SUPPORT_TRACE
10500   MNG_TRACE (pData, MNG_FN_WRITE_MPNG, MNG_LC_START);
10501 #endif
10502 
10503   pMPNG = (mng_mpngp)pChunk;           /* address the proper chunk */
10504                                        /* compress the frame structures */
10505   iRetcode = deflate_buffer (pData, (mng_uint8p)pMPNG->pFrames, pMPNG->iFramessize,
10506                              &pBuf, &iBuflen, &iReallen);
10507 
10508   if (!iRetcode)                       /* all ok ? */
10509   {
10510     pRawdata = pData->pWritebuf+8;     /* init output buffer & size */
10511     iRawlen  = 15 + iReallen;
10512                                        /* requires large buffer ? */
10513     if (iRawlen > pData->iWritebufsize)
10514       MNG_ALLOC (pData, pRawdata, iRawlen);
10515                                        /* fill the buffer */
10516     mng_put_uint32 (pRawdata,    pMPNG->iFramewidth);
10517     mng_put_uint32 (pRawdata+4,  pMPNG->iFrameheight);
10518     mng_put_uint16 (pRawdata+8,  pMPNG->iNumplays);
10519     mng_put_uint16 (pRawdata+10, pMPNG->iTickspersec);
10520     *(pRawdata+12) = pMPNG->iCompressionmethod;
10521 
10522     if (iReallen)
10523       MNG_COPY (pRawdata+13, pBuf, iReallen);
10524                                        /* and write it */
10525     iRetcode = write_raw_chunk (pData, pMPNG->sHeader.iChunkname,
10526                                 iRawlen, pRawdata);
10527                                        /* drop the temp buffer ? */
10528     if (iRawlen > pData->iWritebufsize)
10529       MNG_FREEX (pData, pRawdata, iRawlen);
10530   }
10531 
10532   MNG_FREEX (pData, pBuf, iBuflen);    /* always drop the compression buffer */
10533 
10534 #ifdef MNG_SUPPORT_TRACE
10535   MNG_TRACE (pData, MNG_FN_WRITE_MPNG, MNG_LC_END);
10536 #endif
10537 
10538   return iRetcode;
10539 }
10540 #endif
10541 
10542 /* ************************************************************************** */
10543 
10544 #ifdef MNG_INCLUDE_ANG_PROPOSAL
WRITE_CHUNK(mng_write_ahdr)10545 WRITE_CHUNK (mng_write_ahdr)
10546 {
10547   mng_ahdrp   pAHDR;
10548   mng_uint8p  pRawdata;
10549   mng_uint32  iRawlen;
10550   mng_retcode iRetcode;
10551 
10552 #ifdef MNG_SUPPORT_TRACE
10553   MNG_TRACE (pData, MNG_FN_WRITE_AHDR, MNG_LC_START);
10554 #endif
10555 
10556   pAHDR    = (mng_ahdrp)pChunk;        /* address the proper chunk */
10557   pRawdata = pData->pWritebuf+8;       /* init output buffer & size */
10558   iRawlen  = 22;
10559                                        /* fill the buffer */
10560   mng_put_uint32 (pRawdata,    pAHDR->iNumframes);
10561   mng_put_uint32 (pRawdata+4,  pAHDR->iTickspersec);
10562   mng_put_uint32 (pRawdata+8,  pAHDR->iNumplays);
10563   mng_put_uint32 (pRawdata+12, pAHDR->iTilewidth);
10564   mng_put_uint32 (pRawdata+16, pAHDR->iTileheight);
10565   *(pRawdata+20) = pAHDR->iInterlace;
10566   *(pRawdata+21) = pAHDR->iStillused;
10567                                        /* and write it */
10568   iRetcode = write_raw_chunk (pData, pAHDR->sHeader.iChunkname,
10569                               iRawlen, pRawdata);
10570 
10571 #ifdef MNG_SUPPORT_TRACE
10572   MNG_TRACE (pData, MNG_FN_WRITE_AHDR, MNG_LC_END);
10573 #endif
10574 
10575   return iRetcode;
10576 }
10577 #endif
10578 
10579 /* ************************************************************************** */
10580 
10581 #ifdef MNG_INCLUDE_ANG_PROPOSAL
WRITE_CHUNK(mng_write_adat)10582 WRITE_CHUNK (mng_write_adat)
10583 {
10584 
10585   /* TODO: something */
10586 
10587   return MNG_NOERROR;
10588 }
10589 #endif
10590 
10591 /* ************************************************************************** */
10592 
10593 #ifndef MNG_SKIPCHUNK_evNT
WRITE_CHUNK(mng_write_evnt)10594 WRITE_CHUNK (mng_write_evnt)
10595 {
10596   mng_evntp       pEVNT;
10597   mng_uint8p      pRawdata;
10598   mng_uint32      iRawlen;
10599   mng_retcode     iRetcode;
10600   mng_evnt_entryp pEntry;
10601   mng_uint8p      pTemp;
10602   mng_uint32      iX;
10603   mng_uint32      iNamesize;
10604 
10605 #ifdef MNG_SUPPORT_TRACE
10606   MNG_TRACE (pData, MNG_FN_WRITE_EVNT, MNG_LC_START);
10607 #endif
10608 
10609   pEVNT = (mng_evntp)pChunk;           /* address the proper chunk */
10610 
10611   if (!pEVNT->iCount)                  /* empty ? */
10612     iRetcode = write_raw_chunk (pData, pEVNT->sHeader.iChunkname, 0, 0);
10613   else
10614   {
10615     pRawdata  = pData->pWritebuf+8;    /* init output buffer & size */
10616     iRawlen   = 0;
10617     pTemp     = pRawdata;
10618     pEntry    = pEVNT->pEntries;
10619 
10620     for (iX = 0; iX < pEVNT->iCount; iX++)
10621     {
10622       if (iX)                          /* put separator null-byte, except the first */
10623       {
10624         *pTemp = 0;
10625         pTemp++;
10626         iRawlen++;
10627       }
10628 
10629       *pTemp     = pEntry->iEventtype;
10630       *(pTemp+1) = pEntry->iMasktype;
10631       pTemp   += 2;
10632       iRawlen += 2;
10633 
10634       switch (pEntry->iMasktype)
10635       {
10636         case 1 :
10637           {
10638             mng_put_int32 (pTemp, pEntry->iLeft);
10639             mng_put_int32 (pTemp+4, pEntry->iRight);
10640             mng_put_int32 (pTemp+8, pEntry->iTop);
10641             mng_put_int32 (pTemp+12, pEntry->iBottom);
10642             pTemp   += 16;
10643             iRawlen += 16;
10644             break;
10645           }
10646         case 2 :
10647           {
10648             mng_put_uint16 (pTemp, pEntry->iObjectid);
10649             pTemp   += 2;
10650             iRawlen += 2;
10651             break;
10652           }
10653         case 3 :
10654           {
10655             mng_put_uint16 (pTemp, pEntry->iObjectid);
10656             *(pTemp+2) = pEntry->iIndex;
10657             pTemp   += 3;
10658             iRawlen += 3;
10659             break;
10660           }
10661         case 4 :
10662           {
10663             mng_put_int32 (pTemp, pEntry->iLeft);
10664             mng_put_int32 (pTemp+4, pEntry->iRight);
10665             mng_put_int32 (pTemp+8, pEntry->iTop);
10666             mng_put_int32 (pTemp+12, pEntry->iBottom);
10667             mng_put_uint16 (pTemp+16, pEntry->iObjectid);
10668             pTemp   += 18;
10669             iRawlen += 18;
10670             break;
10671           }
10672         case 5 :
10673           {
10674             mng_put_int32 (pTemp, pEntry->iLeft);
10675             mng_put_int32 (pTemp+4, pEntry->iRight);
10676             mng_put_int32 (pTemp+8, pEntry->iTop);
10677             mng_put_int32 (pTemp+12, pEntry->iBottom);
10678             mng_put_uint16 (pTemp+16, pEntry->iObjectid);
10679             *(pTemp+18) = pEntry->iIndex;
10680             pTemp   += 19;
10681             iRawlen += 19;
10682             break;
10683           }
10684       }
10685 
10686       iNamesize = pEntry->iSegmentnamesize;
10687 
10688       if (iNamesize)
10689       {
10690         MNG_COPY (pTemp, pEntry->zSegmentname, iNamesize);
10691         pTemp   += iNamesize;
10692         iRawlen += iNamesize;
10693       }
10694 
10695       pEntry++;
10696     }
10697                                        /* and write it */
10698     iRetcode = write_raw_chunk (pData, pEVNT->sHeader.iChunkname,
10699                                 iRawlen, pRawdata);
10700   }
10701 
10702 #ifdef MNG_SUPPORT_TRACE
10703   MNG_TRACE (pData, MNG_FN_WRITE_EVNT, MNG_LC_END);
10704 #endif
10705 
10706   return iRetcode;
10707 }
10708 #endif
10709 
10710 /* ************************************************************************** */
10711 
WRITE_CHUNK(mng_write_unknown)10712 WRITE_CHUNK (mng_write_unknown)
10713 {
10714   mng_unknown_chunkp pUnknown;
10715   mng_retcode        iRetcode;
10716 
10717 #ifdef MNG_SUPPORT_TRACE
10718   MNG_TRACE (pData, MNG_FN_WRITE_UNKNOWN, MNG_LC_START);
10719 #endif
10720                                        /* address the proper chunk */
10721   pUnknown = (mng_unknown_chunkp)pChunk;
10722                                        /* and write it */
10723   iRetcode = write_raw_chunk (pData, pUnknown->sHeader.iChunkname,
10724                               pUnknown->iDatasize, pUnknown->pData);
10725 
10726 #ifdef MNG_SUPPORT_TRACE
10727   MNG_TRACE (pData, MNG_FN_WRITE_UNKNOWN, MNG_LC_END);
10728 #endif
10729 
10730   return iRetcode;
10731 }
10732 
10733 /* ************************************************************************** */
10734 
10735 #endif /* MNG_INCLUDE_WRITE_PROCS */
10736 
10737 /* ************************************************************************** */
10738 /* * end of file                                                            * */
10739 /* ************************************************************************** */
10740 
10741