1 /* ************************************************************************** */
2 /* *             For conditions of distribution and use,                    * */
3 /* *                see copyright notice in libmng.h                        * */
4 /* ************************************************************************** */
5 /* *                                                                        * */
6 /* * project   : libmng                                                     * */
7 /* * file      : libmng_read.c             copyright (c) 2000-2007 G.Juyn   * */
8 /* * version   : 1.0.10                                                     * */
9 /* *                                                                        * */
10 /* * purpose   : Read logic (implementation)                                * */
11 /* *                                                                        * */
12 /* * author    : G.Juyn                                                     * */
13 /* *                                                                        * */
14 /* * comment   : implementation of the high-level read logic                * */
15 /* *                                                                        * */
16 /* * changes   : 0.5.1 - 05/08/2000 - G.Juyn                                * */
17 /* *             - changed strict-ANSI stuff                                * */
18 /* *             0.5.1 - 05/11/2000 - G.Juyn                                * */
19 /* *             - added callback error-reporting support                   * */
20 /* *             0.5.1 - 05/12/2000 - G.Juyn                                * */
21 /* *             - changed trace to macro for callback error-reporting      * */
22 /* *                                                                        * */
23 /* *             0.5.2 - 05/19/2000 - G.Juyn                                * */
24 /* *             - cleaned up some code regarding mixed support             * */
25 /* *             0.5.2 - 05/20/2000 - G.Juyn                                * */
26 /* *             - added support for JNG                                    * */
27 /* *             0.5.2 - 05/31/2000 - G.Juyn                                * */
28 /* *             - fixed up punctuation (contribution by Tim Rowley)        * */
29 /* *                                                                        * */
30 /* *             0.5.3 - 06/16/2000 - G.Juyn                                * */
31 /* *             - changed progressive-display processing                   * */
32 /* *                                                                        * */
33 /* *             0.9.1 - 07/08/2000 - G.Juyn                                * */
34 /* *             - changed read-processing for improved I/O-suspension      * */
35 /* *             0.9.1 - 07/14/2000 - G.Juyn                                * */
36 /* *             - changed EOF processing behavior                          * */
37 /* *             0.9.1 - 07/14/2000 - G.Juyn                                * */
38 /* *             - changed default readbuffer size from 1024 to 4200        * */
39 /* *                                                                        * */
40 /* *             0.9.2 - 07/27/2000 - G.Juyn                                * */
41 /* *             - B110320 - fixed GCC warning about mix-sized pointer math * */
42 /* *             0.9.2 - 07/31/2000 - G.Juyn                                * */
43 /* *             - B110546 - fixed for improperly returning UNEXPECTEDEOF   * */
44 /* *             0.9.2 - 08/04/2000 - G.Juyn                                * */
45 /* *             - B111096 - fixed large-buffer read-suspension             * */
46 /* *             0.9.2 - 08/05/2000 - G.Juyn                                * */
47 /* *             - changed file-prefixes                                    * */
48 /* *                                                                        * */
49 /* *             0.9.3 - 08/26/2000 - G.Juyn                                * */
50 /* *             - added MAGN chunk                                         * */
51 /* *             0.9.3 - 10/11/2000 - G.Juyn                                * */
52 /* *             - removed test-MaGN                                        * */
53 /* *             0.9.3 - 10/16/2000 - G.Juyn                                * */
54 /* *             - added support for JDAA                                   * */
55 /* *                                                                        * */
56 /* *             0.9.5 - 01/23/2001 - G.Juyn                                * */
57 /* *             - fixed timing-problem with switching framing_modes        * */
58 /* *                                                                        * */
59 /* *             1.0.4 - 06/22/2002 - G.Juyn                                * */
60 /* *             - B495443 - incorrect suspend check in read_databuffer     * */
61 /* *                                                                        * */
62 /* *             1.0.5 - 07/04/2002 - G.Juyn                                * */
63 /* *             - added errorcode for extreme chunk-sizes                  * */
64 /* *             1.0.5 - 07/08/2002 - G.Juyn                                * */
65 /* *             - B578572 - removed eMNGma hack (thanks Dimitri!)          * */
66 /* *             1.0.5 - 07/16/2002 - G.Juyn                                * */
67 /* *             - B581625 - large chunks fail with suspension reads        * */
68 /* *             1.0.5 - 08/19/2002 - G.Juyn                                * */
69 /* *             - B597134 - libmng pollutes the linker namespace           * */
70 /* *             - added HLAPI function to copy chunks                      * */
71 /* *             1.0.5 - 09/16/2002 - G.Juyn                                * */
72 /* *             - added event handling for dynamic MNG                     * */
73 /* *                                                                        * */
74 /* *             1.0.6 - 05/25/2003 - G.R-P                                 * */
75 /* *             - added MNG_SKIPCHUNK_cHNK footprint optimizations         * */
76 /* *             1.0.6 - 07/07/2003 - G.R-P                                 * */
77 /* *             - added MNG_NO_DELTA_PNG reduction                         * */
78 /* *             - skip additional code when MNG_INCLUDE_JNG is not enabled * */
79 /* *             1.0.6 - 07/29/2003 - G.R-P                                 * */
80 /* *             - added conditionals around PAST chunk support             * */
81 /* *             1.0.6 - 08/17/2003 - G.R-P                                 * */
82 /* *             - added conditionals around non-VLC chunk support          * */
83 /* *                                                                        * */
84 /* *             1.0.7 - 03/10/2004 - G.R-P                                 * */
85 /* *             - added conditionals around openstream/closestream         * */
86 /* *                                                                        * */
87 /* *             1.0.8 - 04/08/2004 - G.Juyn                                * */
88 /* *             - added CRC existence & checking flags                     * */
89 /* *             1.0.8 - 04/11/2004 - G.Juyn                                * */
90 /* *             - added data-push mechanisms for specialized decoders      * */
91 /* *             1.0.8 - 07/06/2004 - G.R-P                                 * */
92 /* *             - defend against using undefined closestream function      * */
93 /* *             1.0.8 - 07/28/2004 - G.R-P                                 * */
94 /* *             - added check for extreme chunk-lengths                    * */
95 /* *                                                                        * */
96 /* *             1.0.9 - 09/16/2004 - G.Juyn                                * */
97 /* *             - fixed chunk pushing mechanism                            * */
98 /* *             1.0.9 - 12/05/2004 - G.Juyn                                * */
99 /* *             - added conditional MNG_OPTIMIZE_CHUNKINITFREE             * */
100 /* *             1.0.9 - 12/06/2004 - G.Juyn                                * */
101 /* *             - added conditional MNG_OPTIMIZE_CHUNKASSIGN               * */
102 /* *             - added conditional MNG_OPTIMIZE_CHUNKREADER               * */
103 /* *             1.0.9 - 12/20/2004 - G.Juyn                                * */
104 /* *             - cleaned up macro-invocations (thanks to D. Airlie)       * */
105 /* *             1.0.9 - 12/31/2004 - G.R-P                                 * */
106 /* *             - removed stray characters from #ifdef directive           * */
107 /* *                                                                        * */
108 /* *             1.0.10 - 04/08/2007 - G.Juyn                               * */
109 /* *             - added support for mPNG proposal                          * */
110 /* *                                                                        * */
111 /* ************************************************************************** */
112 
113 #include "libmng.h"
114 #include "libmng_data.h"
115 #include "libmng_error.h"
116 #include "libmng_trace.h"
117 #ifdef __BORLANDC__
118 #pragma hdrstop
119 #endif
120 #include "libmng_memory.h"
121 #include "libmng_objects.h"
122 #include "libmng_object_prc.h"
123 #include "libmng_chunks.h"
124 #ifdef MNG_OPTIMIZE_CHUNKREADER
125 #include "libmng_chunk_descr.h"
126 #endif
127 #include "libmng_chunk_prc.h"
128 #include "libmng_chunk_io.h"
129 #include "libmng_display.h"
130 #include "libmng_read.h"
131 
132 #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
133 #pragma option -A                      /* force ANSI-C */
134 #endif
135 
136 /* ************************************************************************** */
137 
138 #ifdef MNG_INCLUDE_READ_PROCS
139 
140 /* ************************************************************************** */
141 
mng_process_eof(mng_datap pData)142 mng_retcode mng_process_eof (mng_datap pData)
143 {
144   if (!pData->bEOF)                    /* haven't closed the stream yet ? */
145   {
146     pData->bEOF = MNG_TRUE;            /* now we do! */
147 
148 #ifndef MNG_NO_OPEN_CLOSE_STREAM
149     if (pData->fClosestream && !pData->fClosestream ((mng_handle)pData))
150     {
151       MNG_ERROR (pData, MNG_APPIOERROR);
152     }
153 #endif
154   }
155 
156   return MNG_NOERROR;
157 }
158 
159 /* ************************************************************************** */
160 
mng_release_pushdata(mng_datap pData)161 mng_retcode mng_release_pushdata (mng_datap pData)
162 {
163   mng_pushdatap pFirst  = pData->pFirstpushdata;
164   mng_pushdatap pNext   = pFirst->pNext;
165 
166 #ifdef MNG_SUPPORT_TRACE
167   MNG_TRACE (pData, MNG_FN_RELEASE_PUSHDATA, MNG_LC_START);
168 #endif
169 
170   pData->pFirstpushdata = pNext;       /* next becomes the first */
171 
172   if (!pNext)                          /* no next? => no last! */
173     pData->pLastpushdata = MNG_NULL;
174                                        /* buffer owned and release callback defined? */
175   if ((pFirst->bOwned) && (pData->fReleasedata))
176     pData->fReleasedata ((mng_handle)pData, pFirst->pData, pFirst->iLength);
177   else                                 /* otherwise use internal free mechanism */
178     MNG_FREEX (pData, pFirst->pData, pFirst->iLength);
179                                        /* and free it */
180   MNG_FREEX (pData, pFirst, sizeof(mng_pushdata));
181 
182 #ifdef MNG_SUPPORT_TRACE
183   MNG_TRACE (pData, MNG_FN_RELEASE_PUSHDATA, MNG_LC_END);
184 #endif
185 
186   return MNG_NOERROR;
187 }
188 
189 /* ************************************************************************** */
190 
mng_release_pushchunk(mng_datap pData)191 mng_retcode mng_release_pushchunk (mng_datap pData)
192 {
193   mng_pushdatap pFirst  = pData->pFirstpushchunk;
194   mng_pushdatap pNext   = pFirst->pNext;
195 
196 #ifdef MNG_SUPPORT_TRACE
197   MNG_TRACE (pData, MNG_FN_RELEASE_PUSHCHUNK, MNG_LC_START);
198 #endif
199 
200   pData->pFirstpushchunk = pNext;      /* next becomes the first */
201 
202   if (!pNext)                          /* no next? => no last! */
203     pData->pLastpushchunk = MNG_NULL;
204                                        /* buffer owned and release callback defined? */
205   if ((pFirst->bOwned) && (pData->fReleasedata))
206     pData->fReleasedata ((mng_handle)pData, pFirst->pData, pFirst->iLength);
207   else                                 /* otherwise use internal free mechanism */
208     MNG_FREEX (pData, pFirst->pData, pFirst->iLength);
209                                        /* and free it */
210   MNG_FREEX (pData, pFirst, sizeof(mng_pushdata));
211 
212 #ifdef MNG_SUPPORT_TRACE
213   MNG_TRACE (pData, MNG_FN_RELEASE_PUSHCHUNK, MNG_LC_END);
214 #endif
215 
216   return MNG_NOERROR;
217 }
218 
219 /* ************************************************************************** */
220 
read_data(mng_datap pData,mng_uint8p pBuf,mng_uint32 iSize,mng_uint32 * iRead)221 MNG_LOCAL mng_retcode read_data (mng_datap    pData,
222                                  mng_uint8p   pBuf,
223                                  mng_uint32   iSize,
224                                  mng_uint32 * iRead)
225 {
226   mng_retcode   iRetcode;
227   mng_uint32    iTempsize = iSize;
228   mng_uint8p    pTempbuf  = pBuf;
229   mng_pushdatap pPush     = pData->pFirstpushdata;
230   mng_uint32    iPushsize = 0;
231   *iRead                  = 0;         /* nothing yet */
232 
233 #ifdef MNG_SUPPORT_TRACE
234   MNG_TRACE (pData, MNG_FN_READ_DATA, MNG_LC_START);
235 #endif
236 
237   while (pPush)                        /* calculate size of pushed data */
238   {
239     iPushsize += pPush->iRemaining;
240     pPush      = pPush->pNext;
241   }
242 
243   if (iTempsize <= iPushsize)          /* got enough push data? */
244   {
245     while (iTempsize)
246     {
247       pPush = pData->pFirstpushdata;
248                                        /* enough data remaining in this buffer? */
249       if (pPush->iRemaining <= iTempsize)
250       {                                /* no: then copy what we've got */
251         MNG_COPY (pTempbuf, pPush->pDatanext, pPush->iRemaining);
252                                        /* move pointers & lengths */
253         pTempbuf  += pPush->iRemaining;
254         *iRead    += pPush->iRemaining;
255         iTempsize -= pPush->iRemaining;
256                                        /* release the depleted buffer */
257         iRetcode = mng_release_pushdata (pData);
258         if (iRetcode)
259           return iRetcode;
260       }
261       else
262       {                                /* copy the needed bytes */
263         MNG_COPY (pTempbuf, pPush->pDatanext, iTempsize);
264                                        /* move pointers & lengths */
265         pPush->iRemaining -= iTempsize;
266         pPush->pDatanext  += iTempsize;
267         pTempbuf          += iTempsize;
268         *iRead            += iTempsize;
269         iTempsize         = 0;         /* all done!!! */
270       }
271     }
272   }
273   else
274   {
275     mng_uint32 iTempread = 0;
276                                        /* get it from the app then */
277     if (!pData->fReaddata (((mng_handle)pData), pTempbuf, iTempsize, &iTempread))
278       MNG_ERROR (pData, MNG_APPIOERROR);
279 
280     *iRead += iTempread;
281   }
282 
283 #ifdef MNG_SUPPORT_TRACE
284   MNG_TRACE (pData, MNG_FN_READ_DATA, MNG_LC_END);
285 #endif
286 
287   return MNG_NOERROR;
288 }
289 
290 /* ************************************************************************** */
291 
read_databuffer(mng_datap pData,mng_uint8p pBuf,mng_uint8p * pBufnext,mng_uint32 iSize,mng_uint32 * iRead)292 MNG_LOCAL mng_retcode read_databuffer (mng_datap    pData,
293                                        mng_uint8p   pBuf,
294                                        mng_uint8p * pBufnext,
295                                        mng_uint32   iSize,
296                                        mng_uint32 * iRead)
297 {
298   mng_retcode iRetcode;
299 
300 #ifdef MNG_SUPPORT_TRACE
301   MNG_TRACE (pData, MNG_FN_READ_DATABUFFER, MNG_LC_START);
302 #endif
303 
304   if (pData->bSuspensionmode)
305   {
306     mng_uint8p pTemp;
307     mng_uint32 iTemp;
308 
309     *iRead = 0;                        /* let's be negative about the outcome */
310 
311     if (!pData->pSuspendbuf)           /* need to create a suspension buffer ? */
312     {
313       pData->iSuspendbufsize = MNG_SUSPENDBUFFERSIZE;
314                                        /* so, create it */
315       MNG_ALLOC (pData, pData->pSuspendbuf, pData->iSuspendbufsize);
316 
317       pData->iSuspendbufleft = 0;      /* make sure to fill it first time */
318       pData->pSuspendbufnext = pData->pSuspendbuf;
319     }
320                                        /* more than our buffer can hold ? */
321     if (iSize > pData->iSuspendbufsize)
322     {
323       mng_uint32 iRemain;
324 
325       if (!*pBufnext)                  /* first time ? */
326       {
327         if (pData->iSuspendbufleft)    /* do we have some data left ? */
328         {                              /* then copy it */
329           MNG_COPY (pBuf, pData->pSuspendbufnext, pData->iSuspendbufleft);
330                                        /* fixup variables */
331           *pBufnext              = pBuf + pData->iSuspendbufleft;
332           pData->pSuspendbufnext = pData->pSuspendbuf;
333           pData->iSuspendbufleft = 0;
334         }
335         else
336         {
337           *pBufnext              = pBuf;
338         }
339       }
340                                        /* calculate how much to get */
341       iRemain = iSize - (mng_uint32)(*pBufnext - pBuf);
342                                        /* let's go get it */
343       iRetcode = read_data (pData, *pBufnext, iRemain, &iTemp);
344       if (iRetcode)
345         return iRetcode;
346                                        /* first read after suspension return 0 means EOF */
347       if ((pData->iSuspendpoint) && (iTemp == 0))
348       {                                /* that makes it final */
349         mng_retcode iRetcode = mng_process_eof (pData);
350         if (iRetcode)                  /* on error bail out */
351           return iRetcode;
352                                        /* indicate the source is depleted */
353         *iRead = iSize - iRemain + iTemp;
354       }
355       else
356       {
357         if (iTemp < iRemain)           /* suspension required ? */
358         {
359           *pBufnext         = *pBufnext + iTemp;
360           pData->bSuspended = MNG_TRUE;
361         }
362         else
363         {
364           *iRead = iSize;              /* got it all now ! */
365         }
366       }
367     }
368     else
369     {                                  /* need to read some more ? */
370       while ((!pData->bSuspended) && (!pData->bEOF) && (iSize > pData->iSuspendbufleft))
371       {                                /* not enough space left in buffer ? */
372         if (pData->iSuspendbufsize - pData->iSuspendbufleft -
373             (mng_uint32)(pData->pSuspendbufnext - pData->pSuspendbuf) <
374                                                           MNG_SUSPENDREQUESTSIZE)
375         {
376           if (pData->iSuspendbufleft)  /* then lets shift (if there's anything left) */
377             MNG_COPY (pData->pSuspendbuf, pData->pSuspendbufnext, pData->iSuspendbufleft);
378                                        /* adjust running pointer */
379           pData->pSuspendbufnext = pData->pSuspendbuf;
380         }
381                                        /* still not enough room ? */
382         if (pData->iSuspendbufsize - pData->iSuspendbufleft < MNG_SUSPENDREQUESTSIZE)
383           MNG_ERROR (pData, MNG_INTERNALERROR);
384                                        /* now read some more data */
385         pTemp = pData->pSuspendbufnext + pData->iSuspendbufleft;
386 
387         iRetcode = read_data (pData, pTemp, MNG_SUSPENDREQUESTSIZE, &iTemp);
388         if (iRetcode)
389           return iRetcode;
390                                        /* adjust fill-counter */
391         pData->iSuspendbufleft += iTemp;
392                                        /* first read after suspension returning 0 means EOF */
393         if ((pData->iSuspendpoint) && (iTemp == 0))
394         {                              /* that makes it final */
395           mng_retcode iRetcode = mng_process_eof (pData);
396           if (iRetcode)                /* on error bail out */
397             return iRetcode;
398 
399           if (pData->iSuspendbufleft)  /* return the leftover scraps */
400             MNG_COPY (pBuf, pData->pSuspendbufnext, pData->iSuspendbufleft);
401                                        /* and indicate so */
402           *iRead = pData->iSuspendbufleft;
403           pData->pSuspendbufnext = pData->pSuspendbuf;
404           pData->iSuspendbufleft = 0;
405         }
406         else
407         {                              /* suspension required ? */
408           if ((iSize > pData->iSuspendbufleft) && (iTemp < MNG_SUSPENDREQUESTSIZE))
409             pData->bSuspended = MNG_TRUE;
410 
411         }
412 
413         pData->iSuspendpoint = 0;      /* reset it here in case we loop back */
414       }
415 
416       if ((!pData->bSuspended) && (!pData->bEOF))
417       {                                /* return the data ! */
418         MNG_COPY (pBuf, pData->pSuspendbufnext, iSize);
419 
420         *iRead = iSize;                /* returned it all */
421                                        /* adjust suspension-buffer variables */
422         pData->pSuspendbufnext += iSize;
423         pData->iSuspendbufleft -= iSize;
424       }
425     }
426   }
427   else
428   {
429     iRetcode = read_data (pData, (mng_ptr)pBuf, iSize, iRead);
430     if (iRetcode)
431       return iRetcode;
432     if (*iRead == 0)                   /* suspension required ? */
433       pData->bSuspended = MNG_TRUE;
434   }
435 
436   pData->iSuspendpoint = 0;            /* safely reset it here ! */
437 
438 #ifdef MNG_SUPPORT_TRACE
439   MNG_TRACE (pData, MNG_FN_READ_DATABUFFER, MNG_LC_END);
440 #endif
441 
442   return MNG_NOERROR;
443 }
444 
445 /* ************************************************************************** */
446 
process_raw_chunk(mng_datap pData,mng_uint8p pBuf,mng_uint32 iBuflen)447 MNG_LOCAL mng_retcode process_raw_chunk (mng_datap  pData,
448                                          mng_uint8p pBuf,
449                                          mng_uint32 iBuflen)
450 {
451 
452 #ifndef MNG_OPTIMIZE_CHUNKREADER
453   /* the table-idea & binary search code was adapted from
454      libpng 1.1.0 (pngread.c) */
455   /* NOTE1: the table must remain sorted by chunkname, otherwise the binary
456      search will break !!! (ps. watch upper-/lower-case chunknames !!) */
457   /* NOTE2: the layout must remain equal to the header part of all the
458      chunk-structures (yes, that means even the pNext and pPrev fields;
459      it's wasting a bit of space, but hey, the code is a lot easier) */
460 
461 #ifdef MNG_OPTIMIZE_CHUNKINITFREE
462   mng_chunk_header mng_chunk_unknown = {MNG_UINT_HUH, mng_init_general, mng_free_unknown,
463                                         mng_read_unknown, mng_write_unknown, mng_assign_unknown, 0, 0, sizeof(mng_unknown_chunk)};
464 #else
465   mng_chunk_header mng_chunk_unknown = {MNG_UINT_HUH, mng_init_unknown, mng_free_unknown,
466                                         mng_read_unknown, mng_write_unknown, mng_assign_unknown, 0, 0};
467 #endif
468 
469 #ifdef MNG_OPTIMIZE_CHUNKINITFREE
470 
471   mng_chunk_header mng_chunk_table [] =
472   {
473 #ifndef MNG_SKIPCHUNK_BACK
474     {MNG_UINT_BACK, mng_init_general, mng_free_general, mng_read_back, mng_write_back, mng_assign_general, 0, 0, sizeof(mng_back)},
475 #endif
476 #ifndef MNG_SKIPCHUNK_BASI
477     {MNG_UINT_BASI, mng_init_general, mng_free_general, mng_read_basi, mng_write_basi, mng_assign_general, 0, 0, sizeof(mng_basi)},
478 #endif
479 #ifndef MNG_SKIPCHUNK_CLIP
480     {MNG_UINT_CLIP, mng_init_general, mng_free_general, mng_read_clip, mng_write_clip, mng_assign_general, 0, 0, sizeof(mng_clip)},
481 #endif
482 #ifndef MNG_SKIPCHUNK_CLON
483     {MNG_UINT_CLON, mng_init_general, mng_free_general, mng_read_clon, mng_write_clon, mng_assign_general, 0, 0, sizeof(mng_clon)},
484 #endif
485 #ifndef MNG_NO_DELTA_PNG
486 #ifndef MNG_SKIPCHUNK_DBYK
487     {MNG_UINT_DBYK, mng_init_general, mng_free_dbyk,    mng_read_dbyk, mng_write_dbyk, mng_assign_dbyk,    0, 0, sizeof(mng_dbyk)},
488 #endif
489 #endif
490 #ifndef MNG_SKIPCHUNK_DEFI
491     {MNG_UINT_DEFI, mng_init_general, mng_free_general, mng_read_defi, mng_write_defi, mng_assign_general, 0, 0, sizeof(mng_defi)},
492 #endif
493 #ifndef MNG_NO_DELTA_PNG
494     {MNG_UINT_DHDR, mng_init_general, mng_free_general, mng_read_dhdr, mng_write_dhdr, mng_assign_general, 0, 0, sizeof(mng_dhdr)},
495 #endif
496 #ifndef MNG_SKIPCHUNK_DISC
497     {MNG_UINT_DISC, mng_init_general, mng_free_disc,    mng_read_disc, mng_write_disc, mng_assign_disc,    0, 0, sizeof(mng_disc)},
498 #endif
499 #ifndef MNG_NO_DELTA_PNG
500 #ifndef MNG_SKIPCHUNK_DROP
501     {MNG_UINT_DROP, mng_init_general, mng_free_drop,    mng_read_drop, mng_write_drop, mng_assign_drop,    0, 0, sizeof(mng_drop)},
502 #endif
503 #endif
504 #ifndef MNG_SKIPCHUNK_LOOP
505     {MNG_UINT_ENDL, mng_init_general, mng_free_general, mng_read_endl, mng_write_endl, mng_assign_general, 0, 0, sizeof(mng_endl)},
506 #endif
507 #ifndef MNG_SKIPCHUNK_FRAM
508     {MNG_UINT_FRAM, mng_init_general, mng_free_fram,    mng_read_fram, mng_write_fram, mng_assign_fram,    0, 0, sizeof(mng_fram)},
509 #endif
510     {MNG_UINT_IDAT, mng_init_general, mng_free_idat,    mng_read_idat, mng_write_idat, mng_assign_idat,    0, 0, sizeof(mng_idat)},  /* 12-th element! */
511     {MNG_UINT_IEND, mng_init_general, mng_free_general, mng_read_iend, mng_write_iend, mng_assign_general, 0, 0, sizeof(mng_iend)},
512     {MNG_UINT_IHDR, mng_init_general, mng_free_general, mng_read_ihdr, mng_write_ihdr, mng_assign_general, 0, 0, sizeof(mng_ihdr)},
513 #ifndef MNG_NO_DELTA_PNG
514 #ifdef MNG_INCLUDE_JNG
515     {MNG_UINT_IJNG, mng_init_general, mng_free_general, mng_read_ijng, mng_write_ijng, mng_assign_general, 0, 0, sizeof(mng_ijng)},
516 #endif
517     {MNG_UINT_IPNG, mng_init_general, mng_free_general, mng_read_ipng, mng_write_ipng, mng_assign_general, 0, 0, sizeof(mng_ipng)},
518 #endif
519 #ifdef MNG_INCLUDE_JNG
520     {MNG_UINT_JDAA, mng_init_general, mng_free_jdaa,    mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa,    0, 0, sizeof(mng_jdaa)},
521     {MNG_UINT_JDAT, mng_init_general, mng_free_jdat,    mng_read_jdat, mng_write_jdat, mng_assign_jdat,    0, 0, sizeof(mng_jdat)},
522     {MNG_UINT_JHDR, mng_init_general, mng_free_general, mng_read_jhdr, mng_write_jhdr, mng_assign_general, 0, 0, sizeof(mng_jhdr)},
523     {MNG_UINT_JSEP, mng_init_general, mng_free_general, mng_read_jsep, mng_write_jsep, mng_assign_general, 0, 0, sizeof(mng_jsep)},
524     {MNG_UINT_JdAA, mng_init_general, mng_free_jdaa,    mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa,    0, 0, sizeof(mng_jdaa)},
525 #endif
526 #ifndef MNG_SKIPCHUNK_LOOP
527     {MNG_UINT_LOOP, mng_init_general, mng_free_loop,    mng_read_loop, mng_write_loop, mng_assign_loop,    0, 0, sizeof(mng_loop)},
528 #endif
529 #ifndef MNG_SKIPCHUNK_MAGN
530     {MNG_UINT_MAGN, mng_init_general, mng_free_general, mng_read_magn, mng_write_magn, mng_assign_general, 0, 0, sizeof(mng_magn)},
531 #endif
532     {MNG_UINT_MEND, mng_init_general, mng_free_general, mng_read_mend, mng_write_mend, mng_assign_general, 0, 0, sizeof(mng_mend)},
533     {MNG_UINT_MHDR, mng_init_general, mng_free_general, mng_read_mhdr, mng_write_mhdr, mng_assign_general, 0, 0, sizeof(mng_mhdr)},
534 #ifndef MNG_SKIPCHUNK_MOVE
535     {MNG_UINT_MOVE, mng_init_general, mng_free_general, mng_read_move, mng_write_move, mng_assign_general, 0, 0, sizeof(mng_move)},
536 #endif
537 #ifndef MNG_NO_DELTA_PNG
538 #ifndef MNG_SKIPCHUNK_ORDR
539     {MNG_UINT_ORDR, mng_init_general, mng_free_ordr,    mng_read_ordr, mng_write_ordr, mng_assign_ordr,    0, 0, sizeof(mng_ordr)},
540 #endif
541 #endif
542 #ifndef MNG_SKIPCHUNK_PAST
543     {MNG_UINT_PAST, mng_init_general, mng_free_past,    mng_read_past, mng_write_past, mng_assign_past,    0, 0, sizeof(mng_past)},
544 #endif
545     {MNG_UINT_PLTE, mng_init_general, mng_free_general, mng_read_plte, mng_write_plte, mng_assign_general, 0, 0, sizeof(mng_plte)},
546 #ifndef MNG_NO_DELTA_PNG
547     {MNG_UINT_PPLT, mng_init_general, mng_free_general, mng_read_pplt, mng_write_pplt, mng_assign_general, 0, 0, sizeof(mng_pplt)},
548     {MNG_UINT_PROM, mng_init_general, mng_free_general, mng_read_prom, mng_write_prom, mng_assign_general, 0, 0, sizeof(mng_prom)},
549 #endif
550 #ifndef MNG_SKIPCHUNK_SAVE
551     {MNG_UINT_SAVE, mng_init_general, mng_free_save,    mng_read_save, mng_write_save, mng_assign_save,    0, 0, sizeof(mng_save)},
552 #endif
553 #ifndef MNG_SKIPCHUNK_SEEK
554     {MNG_UINT_SEEK, mng_init_general, mng_free_seek,    mng_read_seek, mng_write_seek, mng_assign_seek,    0, 0, sizeof(mng_seek)},
555 #endif
556 #ifndef MNG_SKIPCHUNK_SHOW
557     {MNG_UINT_SHOW, mng_init_general, mng_free_general, mng_read_show, mng_write_show, mng_assign_general, 0, 0, sizeof(mng_show)},
558 #endif
559 #ifndef MNG_SKIPCHUNK_TERM
560     {MNG_UINT_TERM, mng_init_general, mng_free_general, mng_read_term, mng_write_term, mng_assign_general, 0, 0, sizeof(mng_term)},
561 #endif
562 #ifndef MNG_SKIPCHUNK_bKGD
563     {MNG_UINT_bKGD, mng_init_general, mng_free_general, mng_read_bkgd, mng_write_bkgd, mng_assign_general, 0, 0, sizeof(mng_bkgd)},
564 #endif
565 #ifndef MNG_SKIPCHUNK_cHRM
566     {MNG_UINT_cHRM, mng_init_general, mng_free_general, mng_read_chrm, mng_write_chrm, mng_assign_general, 0, 0, sizeof(mng_chrm)},
567 #endif
568 #ifndef MNG_SKIPCHUNK_eXPI
569     {MNG_UINT_eXPI, mng_init_general, mng_free_expi,    mng_read_expi, mng_write_expi, mng_assign_expi,    0, 0, sizeof(mng_expi)},
570 #endif
571 #ifndef MNG_SKIPCHUNK_evNT
572     {MNG_UINT_evNT, mng_init_general, mng_free_evnt,    mng_read_evnt, mng_write_evnt, mng_assign_evnt,    0, 0, sizeof(mng_evnt)},
573 #endif
574 #ifndef MNG_SKIPCHUNK_fPRI
575     {MNG_UINT_fPRI, mng_init_general, mng_free_general, mng_read_fpri, mng_write_fpri, mng_assign_general, 0, 0, sizeof(mng_fpri)},
576 #endif
577 #ifndef MNG_SKIPCHUNK_gAMA
578     {MNG_UINT_gAMA, mng_init_general, mng_free_general, mng_read_gama, mng_write_gama, mng_assign_general, 0, 0, sizeof(mng_gama)},
579 #endif
580 #ifndef MNG_SKIPCHUNK_hIST
581     {MNG_UINT_hIST, mng_init_general, mng_free_general, mng_read_hist, mng_write_hist, mng_assign_general, 0, 0, sizeof(mng_hist)},
582 #endif
583 #ifndef MNG_SKIPCHUNK_iCCP
584     {MNG_UINT_iCCP, mng_init_general, mng_free_iccp,    mng_read_iccp, mng_write_iccp, mng_assign_iccp,    0, 0, sizeof(mng_iccp)},
585 #endif
586 #ifndef MNG_SKIPCHUNK_iTXt
587     {MNG_UINT_iTXt, mng_init_general, mng_free_itxt,    mng_read_itxt, mng_write_itxt, mng_assign_itxt,    0, 0, sizeof(mng_itxt)},
588 #endif
589 #ifdef MNG_INCLUDE_MPNG_PROPOSAL
590     {MNG_UINT_mpNG, mng_init_general, mng_free_mpng,    mng_read_mpng, mng_write_mpng, mng_assign_mpng,    0, 0, sizeof(mng_mpng)},
591 #endif
592 #ifndef MNG_SKIPCHUNK_nEED
593     {MNG_UINT_nEED, mng_init_general, mng_free_need,    mng_read_need, mng_write_need, mng_assign_need,    0, 0, sizeof(mng_need)},
594 #endif
595 /* TODO:     {MNG_UINT_oFFs, 0, 0, 0, 0, 0, 0},  */
596 /* TODO:     {MNG_UINT_pCAL, 0, 0, 0, 0, 0, 0},  */
597 #ifndef MNG_SKIPCHUNK_pHYg
598     {MNG_UINT_pHYg, mng_init_general, mng_free_general, mng_read_phyg, mng_write_phyg, mng_assign_general, 0, 0, sizeof(mng_phyg)},
599 #endif
600 #ifndef MNG_SKIPCHUNK_pHYs
601     {MNG_UINT_pHYs, mng_init_general, mng_free_general, mng_read_phys, mng_write_phys, mng_assign_general, 0, 0, sizeof(mng_phys)},
602 #endif
603 #ifndef MNG_SKIPCHUNK_sBIT
604     {MNG_UINT_sBIT, mng_init_general, mng_free_general, mng_read_sbit, mng_write_sbit, mng_assign_general, 0, 0, sizeof(mng_sbit)},
605 #endif
606 /* TODO:     {MNG_UINT_sCAL, 0, 0, 0, 0, 0, 0},  */
607 #ifndef MNG_SKIPCHUNK_sPLT
608     {MNG_UINT_sPLT, mng_init_general, mng_free_splt,    mng_read_splt, mng_write_splt, mng_assign_splt,    0, 0, sizeof(mng_splt)},
609 #endif
610     {MNG_UINT_sRGB, mng_init_general, mng_free_general, mng_read_srgb, mng_write_srgb, mng_assign_general, 0, 0, sizeof(mng_srgb)},
611 #ifndef MNG_SKIPCHUNK_tEXt
612     {MNG_UINT_tEXt, mng_init_general, mng_free_text,    mng_read_text, mng_write_text, mng_assign_text,    0, 0, sizeof(mng_text)},
613 #endif
614 #ifndef MNG_SKIPCHUNK_tIME
615     {MNG_UINT_tIME, mng_init_general, mng_free_general, mng_read_time, mng_write_time, mng_assign_general, 0, 0, sizeof(mng_time)},
616 #endif
617     {MNG_UINT_tRNS, mng_init_general, mng_free_general, mng_read_trns, mng_write_trns, mng_assign_general, 0, 0, sizeof(mng_trns)},
618 #ifndef MNG_SKIPCHUNK_zTXt
619     {MNG_UINT_zTXt, mng_init_general, mng_free_ztxt,    mng_read_ztxt, mng_write_ztxt, mng_assign_ztxt,    0, 0, sizeof(mng_ztxt)},
620 #endif
621   };
622 
623 #else                        /* MNG_OPTIMIZE_CHUNKINITFREE */
624 
625   mng_chunk_header mng_chunk_table [] =
626   {
627 #ifndef MNG_SKIPCHUNK_BACK
628     {MNG_UINT_BACK, mng_init_back, mng_free_back, mng_read_back, mng_write_back, mng_assign_back, 0, 0},
629 #endif
630 #ifndef MNG_SKIPCHUNK_BASI
631     {MNG_UINT_BASI, mng_init_basi, mng_free_basi, mng_read_basi, mng_write_basi, mng_assign_basi, 0, 0},
632 #endif
633 #ifndef MNG_SKIPCHUNK_CLIP
634     {MNG_UINT_CLIP, mng_init_clip, mng_free_clip, mng_read_clip, mng_write_clip, mng_assign_clip, 0, 0},
635 #endif
636 #ifndef MNG_SKIPCHUNK_CLON
637     {MNG_UINT_CLON, mng_init_clon, mng_free_clon, mng_read_clon, mng_write_clon, mng_assign_clon, 0, 0},
638 #endif
639 #ifndef MNG_NO_DELTA_PNG
640 #ifndef MNG_SKIPCHUNK_DBYK
641     {MNG_UINT_DBYK, mng_init_dbyk, mng_free_dbyk, mng_read_dbyk, mng_write_dbyk, mng_assign_dbyk, 0, 0},
642 #endif
643 #endif
644 #ifndef MNG_SKIPCHUNK_DEFI
645     {MNG_UINT_DEFI, mng_init_defi, mng_free_defi, mng_read_defi, mng_write_defi, mng_assign_defi, 0, 0},
646 #endif
647 #ifndef MNG_NO_DELTA_PNG
648     {MNG_UINT_DHDR, mng_init_dhdr, mng_free_dhdr, mng_read_dhdr, mng_write_dhdr, mng_assign_dhdr, 0, 0},
649 #endif
650 #ifndef MNG_SKIPCHUNK_DISC
651     {MNG_UINT_DISC, mng_init_disc, mng_free_disc, mng_read_disc, mng_write_disc, mng_assign_disc, 0, 0},
652 #endif
653 #ifndef MNG_NO_DELTA_PNG
654 #ifndef MNG_SKIPCHUNK_DROP
655     {MNG_UINT_DROP, mng_init_drop, mng_free_drop, mng_read_drop, mng_write_drop, mng_assign_drop, 0, 0},
656 #endif
657 #endif
658 #ifndef MNG_SKIPCHUNK_LOOP
659     {MNG_UINT_ENDL, mng_init_endl, mng_free_endl, mng_read_endl, mng_write_endl, mng_assign_endl, 0, 0},
660 #endif
661 #ifndef MNG_SKIPCHUNK_FRAM
662     {MNG_UINT_FRAM, mng_init_fram, mng_free_fram, mng_read_fram, mng_write_fram, mng_assign_fram, 0, 0},
663 #endif
664     {MNG_UINT_IDAT, mng_init_idat, mng_free_idat, mng_read_idat, mng_write_idat, mng_assign_idat, 0, 0},  /* 12-th element! */
665     {MNG_UINT_IEND, mng_init_iend, mng_free_iend, mng_read_iend, mng_write_iend, mng_assign_iend, 0, 0},
666     {MNG_UINT_IHDR, mng_init_ihdr, mng_free_ihdr, mng_read_ihdr, mng_write_ihdr, mng_assign_ihdr, 0, 0},
667 #ifndef MNG_NO_DELTA_PNG
668 #ifdef MNG_INCLUDE_JNG
669     {MNG_UINT_IJNG, mng_init_ijng, mng_free_ijng, mng_read_ijng, mng_write_ijng, mng_assign_ijng, 0, 0},
670 #endif
671     {MNG_UINT_IPNG, mng_init_ipng, mng_free_ipng, mng_read_ipng, mng_write_ipng, mng_assign_ipng, 0, 0},
672 #endif
673 #ifdef MNG_INCLUDE_JNG
674     {MNG_UINT_JDAA, mng_init_jdaa, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0},
675     {MNG_UINT_JDAT, mng_init_jdat, mng_free_jdat, mng_read_jdat, mng_write_jdat, mng_assign_jdat, 0, 0},
676     {MNG_UINT_JHDR, mng_init_jhdr, mng_free_jhdr, mng_read_jhdr, mng_write_jhdr, mng_assign_jhdr, 0, 0},
677     {MNG_UINT_JSEP, mng_init_jsep, mng_free_jsep, mng_read_jsep, mng_write_jsep, mng_assign_jsep, 0, 0},
678     {MNG_UINT_JdAA, mng_init_jdaa, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0},
679 #endif
680 #ifndef MNG_SKIPCHUNK_LOOP
681     {MNG_UINT_LOOP, mng_init_loop, mng_free_loop, mng_read_loop, mng_write_loop, mng_assign_loop, 0, 0},
682 #endif
683 #ifndef MNG_SKIPCHUNK_MAGN
684     {MNG_UINT_MAGN, mng_init_magn, mng_free_magn, mng_read_magn, mng_write_magn, mng_assign_magn, 0, 0},
685 #endif
686     {MNG_UINT_MEND, mng_init_mend, mng_free_mend, mng_read_mend, mng_write_mend, mng_assign_mend, 0, 0},
687     {MNG_UINT_MHDR, mng_init_mhdr, mng_free_mhdr, mng_read_mhdr, mng_write_mhdr, mng_assign_mhdr, 0, 0},
688 #ifndef MNG_SKIPCHUNK_MOVE
689     {MNG_UINT_MOVE, mng_init_move, mng_free_move, mng_read_move, mng_write_move, mng_assign_move, 0, 0},
690 #endif
691 #ifndef MNG_NO_DELTA_PNG
692 #ifndef MNG_SKIPCHUNK_ORDR
693     {MNG_UINT_ORDR, mng_init_ordr, mng_free_ordr, mng_read_ordr, mng_write_ordr, mng_assign_ordr, 0, 0},
694 #endif
695 #endif
696 #ifndef MNG_SKIPCHUNK_PAST
697     {MNG_UINT_PAST, mng_init_past, mng_free_past, mng_read_past, mng_write_past, mng_assign_past, 0, 0},
698 #endif
699     {MNG_UINT_PLTE, mng_init_plte, mng_free_plte, mng_read_plte, mng_write_plte, mng_assign_plte, 0, 0},
700 #ifndef MNG_NO_DELTA_PNG
701     {MNG_UINT_PPLT, mng_init_pplt, mng_free_pplt, mng_read_pplt, mng_write_pplt, mng_assign_pplt, 0, 0},
702     {MNG_UINT_PROM, mng_init_prom, mng_free_prom, mng_read_prom, mng_write_prom, mng_assign_prom, 0, 0},
703 #endif
704 #ifndef MNG_SKIPCHUNK_SAVE
705     {MNG_UINT_SAVE, mng_init_save, mng_free_save, mng_read_save, mng_write_save, mng_assign_save, 0, 0},
706 #endif
707 #ifndef MNG_SKIPCHUNK_SEEK
708     {MNG_UINT_SEEK, mng_init_seek, mng_free_seek, mng_read_seek, mng_write_seek, mng_assign_seek, 0, 0},
709 #endif
710 #ifndef MNG_SKIPCHUNK_SHOW
711     {MNG_UINT_SHOW, mng_init_show, mng_free_show, mng_read_show, mng_write_show, mng_assign_show, 0, 0},
712 #endif
713 #ifndef MNG_SKIPCHUNK_TERM
714     {MNG_UINT_TERM, mng_init_term, mng_free_term, mng_read_term, mng_write_term, mng_assign_term, 0, 0},
715 #endif
716 #ifndef MNG_SKIPCHUNK_bKGD
717     {MNG_UINT_bKGD, mng_init_bkgd, mng_free_bkgd, mng_read_bkgd, mng_write_bkgd, mng_assign_bkgd, 0, 0},
718 #endif
719 #ifndef MNG_SKIPCHUNK_cHRM
720     {MNG_UINT_cHRM, mng_init_chrm, mng_free_chrm, mng_read_chrm, mng_write_chrm, mng_assign_chrm, 0, 0},
721 #endif
722 #ifndef MNG_SKIPCHUNK_eXPI
723     {MNG_UINT_eXPI, mng_init_expi, mng_free_expi, mng_read_expi, mng_write_expi, mng_assign_expi, 0, 0},
724 #endif
725 #ifndef MNG_SKIPCHUNK_evNT
726     {MNG_UINT_evNT, mng_init_evnt, mng_free_evnt, mng_read_evnt, mng_write_evnt, mng_assign_evnt, 0, 0},
727 #endif
728 #ifndef MNG_SKIPCHUNK_fPRI
729     {MNG_UINT_fPRI, mng_init_fpri, mng_free_fpri, mng_read_fpri, mng_write_fpri, mng_assign_fpri, 0, 0},
730 #endif
731 #ifndef MNG_SKIPCHUNK_gAMA
732     {MNG_UINT_gAMA, mng_init_gama, mng_free_gama, mng_read_gama, mng_write_gama, mng_assign_gama, 0, 0},
733 #endif
734 #ifndef MNG_SKIPCHUNK_hIST
735     {MNG_UINT_hIST, mng_init_hist, mng_free_hist, mng_read_hist, mng_write_hist, mng_assign_hist, 0, 0},
736 #endif
737 #ifndef MNG_SKIPCHUNK_iCCP
738     {MNG_UINT_iCCP, mng_init_iccp, mng_free_iccp, mng_read_iccp, mng_write_iccp, mng_assign_iccp, 0, 0},
739 #endif
740 #ifndef MNG_SKIPCHUNK_iTXt
741     {MNG_UINT_iTXt, mng_init_itxt, mng_free_itxt, mng_read_itxt, mng_write_itxt, mng_assign_itxt, 0, 0},
742 #endif
743 #ifndef MNG_SKIPCHUNK_nEED
744     {MNG_UINT_nEED, mng_init_need, mng_free_need, mng_read_need, mng_write_need, mng_assign_need, 0, 0},
745 #endif
746 /* TODO:     {MNG_UINT_oFFs, 0, 0, 0, 0, 0, 0},  */
747 /* TODO:     {MNG_UINT_pCAL, 0, 0, 0, 0, 0, 0},  */
748 #ifndef MNG_SKIPCHUNK_pHYg
749     {MNG_UINT_pHYg, mng_init_phyg, mng_free_phyg, mng_read_phyg, mng_write_phyg, mng_assign_phyg, 0, 0},
750 #endif
751 #ifndef MNG_SKIPCHUNK_pHYs
752     {MNG_UINT_pHYs, mng_init_phys, mng_free_phys, mng_read_phys, mng_write_phys, mng_assign_phys, 0, 0},
753 #endif
754 #ifndef MNG_SKIPCHUNK_sBIT
755     {MNG_UINT_sBIT, mng_init_sbit, mng_free_sbit, mng_read_sbit, mng_write_sbit, mng_assign_sbit, 0, 0},
756 #endif
757 /* TODO:     {MNG_UINT_sCAL, 0, 0, 0, 0, 0, 0},  */
758 #ifndef MNG_SKIPCHUNK_sPLT
759     {MNG_UINT_sPLT, mng_init_splt, mng_free_splt, mng_read_splt, mng_write_splt, mng_assign_splt, 0, 0},
760 #endif
761     {MNG_UINT_sRGB, mng_init_srgb, mng_free_srgb, mng_read_srgb, mng_write_srgb, mng_assign_srgb, 0, 0},
762 #ifndef MNG_SKIPCHUNK_tEXt
763     {MNG_UINT_tEXt, mng_init_text, mng_free_text, mng_read_text, mng_write_text, mng_assign_text, 0, 0},
764 #endif
765 #ifndef MNG_SKIPCHUNK_tIME
766     {MNG_UINT_tIME, mng_init_time, mng_free_time, mng_read_time, mng_write_time, mng_assign_time, 0, 0},
767 #endif
768     {MNG_UINT_tRNS, mng_init_trns, mng_free_trns, mng_read_trns, mng_write_trns, mng_assign_trns, 0, 0},
769 #ifndef MNG_SKIPCHUNK_zTXt
770     {MNG_UINT_zTXt, mng_init_ztxt, mng_free_ztxt, mng_read_ztxt, mng_write_ztxt, mng_assign_ztxt, 0, 0},
771 #endif
772   };
773 
774 #endif                       /* MNG_OPTIMIZE_CHUNKINITFREE */
775 
776                                        /* binary search variables */
777   mng_int32         iTop, iLower, iUpper, iMiddle;
778   mng_chunk_headerp pEntry;            /* pointer to found entry */
779 #else
780   mng_chunk_header  sEntry;            /* temp chunk-header */
781 #endif /* MNG_OPTIMIZE_CHUNKREADER */
782 
783   mng_chunkid       iChunkname;        /* the chunk's tag */
784   mng_chunkp        pChunk;            /* chunk structure (if #define MNG_STORE_CHUNKS) */
785   mng_retcode       iRetcode;          /* temporary error-code */
786 
787 #ifdef MNG_SUPPORT_TRACE
788   MNG_TRACE (pData, MNG_FN_PROCESS_RAW_CHUNK, MNG_LC_START);
789 #endif
790                                        /* reset timer indicator on read-cycle */
791   if ((pData->bReading) && (!pData->bDisplaying))
792     pData->bTimerset = MNG_FALSE;
793                                        /* get the chunkname */
794   iChunkname = (mng_chunkid)(mng_get_uint32 (pBuf));
795 
796   pBuf += sizeof (mng_chunkid);        /* adjust the buffer */
797   iBuflen -= sizeof (mng_chunkid);
798   pChunk = 0;
799 
800 #ifndef MNG_OPTIMIZE_CHUNKREADER
801                                        /* determine max index of table */
802   iTop = (sizeof (mng_chunk_table) / sizeof (mng_chunk_table [0])) - 1;
803 
804   /* binary search; with 54 chunks, worst-case is 7 comparisons */
805   iLower  = 0;
806 #ifndef MNG_NO_DELTA_PNG
807   iMiddle = 11;                        /* start with the IDAT entry */
808 #else
809   iMiddle = 8;
810 #endif
811   iUpper  = iTop;
812   pEntry  = 0;                         /* no goods yet! */
813 
814   do                                   /* the binary search itself */
815     {
816       if (mng_chunk_table [iMiddle].iChunkname < iChunkname)
817         iLower = iMiddle + 1;
818       else if (mng_chunk_table [iMiddle].iChunkname > iChunkname)
819         iUpper = iMiddle - 1;
820       else
821       {
822         pEntry = &mng_chunk_table [iMiddle];
823         break;
824       }
825 
826       iMiddle = (iLower + iUpper) >> 1;
827     }
828   while (iLower <= iUpper);
829 
830   if (!pEntry)                         /* unknown chunk ? */
831     pEntry = &mng_chunk_unknown;       /* make it so! */
832 
833 #else /* MNG_OPTIMIZE_CHUNKREADER */
834 
835   mng_get_chunkheader (iChunkname, &sEntry);
836 
837 #endif /* MNG_OPTIMIZE_CHUNKREADER */
838 
839   pData->iChunkname = iChunkname;      /* keep track of where we are */
840   pData->iChunkseq++;
841 
842 #ifndef MNG_OPTIMIZE_CHUNKREADER
843   if (pEntry->fRead)                   /* read-callback available ? */
844   {
845     iRetcode = pEntry->fRead (pData, pEntry, iBuflen, (mng_ptr)pBuf, &pChunk);
846 
847     if (!iRetcode)                     /* everything oke ? */
848     {                                  /* remember unknown chunk's id */
849       if ((pChunk) && (pEntry->iChunkname == MNG_UINT_HUH))
850         ((mng_chunk_headerp)pChunk)->iChunkname = iChunkname;
851     }
852   }
853 #else /* MNG_OPTIMIZE_CHUNKREADER */
854   if (sEntry.fRead)                    /* read-callback available ? */
855   {
856     iRetcode = sEntry.fRead (pData, &sEntry, iBuflen, (mng_ptr)pBuf, &pChunk);
857 
858 #ifndef MNG_OPTIMIZE_CHUNKREADER
859     if (!iRetcode)                     /* everything oke ? */
860     {                                  /* remember unknown chunk's id */
861       if ((pChunk) && (sEntry.iChunkname == MNG_UINT_HUH))
862         ((mng_chunk_headerp)pChunk)->iChunkname = iChunkname;
863     }
864 #endif
865   }
866 #endif /* MNG_OPTIMIZE_CHUNKREADER */
867   else
868     iRetcode = MNG_NOERROR;
869 
870   if (pChunk)                          /* store this chunk ? */
871     mng_add_chunk (pData, pChunk);     /* do it */
872 
873 #ifdef MNG_INCLUDE_JNG                 /* implicit EOF ? */
874   if ((!pData->bHasMHDR) && (!pData->bHasIHDR) && (!pData->bHasJHDR))
875 #else
876   if ((!pData->bHasMHDR) && (!pData->bHasIHDR))
877 #endif
878     iRetcode = mng_process_eof (pData);/* then do some EOF processing */
879 
880   if (iRetcode)                        /* on error bail out */
881     return iRetcode;
882 
883 #ifdef MNG_SUPPORT_TRACE
884   MNG_TRACE (pData, MNG_FN_PROCESS_RAW_CHUNK, MNG_LC_END);
885 #endif
886 
887   return MNG_NOERROR;
888 }
889 
890 /* ************************************************************************** */
891 
check_chunk_crc(mng_datap pData,mng_uint8p pBuf,mng_uint32 iBuflen)892 MNG_LOCAL mng_retcode check_chunk_crc (mng_datap  pData,
893                                        mng_uint8p pBuf,
894                                        mng_uint32 iBuflen)
895 {
896   mng_uint32  iCrc;                    /* calculated CRC */
897   mng_bool    bDiscard = MNG_FALSE;
898   mng_retcode iRetcode = MNG_NOERROR;
899 
900 #ifdef MNG_SUPPORT_TRACE
901   MNG_TRACE (pData, MNG_FN_READ_CHUNK_CRC, MNG_LC_START);
902 #endif
903 
904   if (pData->iCrcmode & MNG_CRC_INPUT) /* crc included ? */
905   {
906     mng_bool bCritical = (mng_bool)((*pBuf & 0x20) == 0);
907     mng_uint32 iL = iBuflen - (mng_uint32)(sizeof (iCrc));
908 
909     if (((bCritical ) && (pData->iCrcmode & MNG_CRC_CRITICAL )) ||
910         ((!bCritical) && (pData->iCrcmode & MNG_CRC_ANCILLARY)))
911     {                                  /* calculate the crc */
912       iCrc = mng_crc (pData, pBuf, iL);
913                                        /* and check it */
914       if (!(iCrc == mng_get_uint32 (pBuf + iL)))
915       {
916         mng_bool bWarning = MNG_FALSE;
917         mng_bool bError   = MNG_FALSE;
918 
919         if (bCritical)
920         {
921           switch (pData->iCrcmode & MNG_CRC_CRITICAL)
922           {
923             case MNG_CRC_CRITICAL_WARNING  : { bWarning = MNG_TRUE; break; }
924             case MNG_CRC_CRITICAL_ERROR    : { bError   = MNG_TRUE; break; }
925           }
926         }
927         else
928         {
929           switch (pData->iCrcmode & MNG_CRC_ANCILLARY)
930           {
931             case MNG_CRC_ANCILLARY_DISCARD : { bDiscard = MNG_TRUE; break; }
932             case MNG_CRC_ANCILLARY_WARNING : { bWarning = MNG_TRUE; break; }
933             case MNG_CRC_ANCILLARY_ERROR   : { bError   = MNG_TRUE; break; }
934           }
935         }
936 
937         if (bWarning)
938           MNG_WARNING (pData, MNG_INVALIDCRC);
939         if (bError)
940           MNG_ERROR (pData, MNG_INVALIDCRC);
941       }
942     }
943 
944     if (!bDiscard)                     /* still processing ? */
945       iRetcode = process_raw_chunk (pData, pBuf, iL);
946   }
947   else
948   {                                    /* no crc => straight onto processing */
949     iRetcode = process_raw_chunk (pData, pBuf, iBuflen);
950   }
951 
952 #ifdef MNG_SUPPORT_TRACE
953   MNG_TRACE (pData, MNG_FN_READ_CHUNK_CRC, MNG_LC_END);
954 #endif
955 
956   return iRetcode;
957 }
958 
959 /* ************************************************************************** */
960 
read_chunk(mng_datap pData)961 MNG_LOCAL mng_retcode read_chunk (mng_datap  pData)
962 {
963   mng_uint32  iBufmax   = pData->iReadbufsize;
964   mng_uint8p  pBuf      = pData->pReadbuf;
965   mng_uint32  iBuflen   = 0;           /* number of bytes requested */
966   mng_uint32  iRead     = 0;           /* number of bytes read */
967   mng_retcode iRetcode  = MNG_NOERROR;
968 
969 #ifdef MNG_SUPPORT_TRACE
970   MNG_TRACE (pData, MNG_FN_READ_CHUNK, MNG_LC_START);
971 #endif
972 
973 #ifdef MNG_SUPPORT_DISPLAY
974   if (pData->pCurraniobj)              /* processing an animation object ? */
975   {
976     do                                 /* process it then */
977     {
978       iRetcode = ((mng_object_headerp)pData->pCurraniobj)->fProcess (pData, pData->pCurraniobj);
979                                        /* refresh needed ? */
980 /*      if ((!iRetcode) && (!pData->bTimerset) && (pData->bNeedrefresh))
981         iRetcode = display_progressive_refresh (pData, 1); */
982                                        /* can we advance to next object ? */
983       if ((!iRetcode) && (pData->pCurraniobj) &&
984           (!pData->bTimerset) && (!pData->bSectionwait))
985       {                                /* reset timer indicator on read-cycle */
986         if ((pData->bReading) && (!pData->bDisplaying))
987           pData->bTimerset = MNG_FALSE;
988 
989         pData->pCurraniobj = ((mng_object_headerp)pData->pCurraniobj)->pNext;
990                                        /* TERM processing to be done ? */
991         if ((!pData->pCurraniobj) && (pData->bHasTERM) && (!pData->bHasMHDR))
992           iRetcode = mng_process_display_mend (pData);
993       }
994     }                                  /* until error or a break or no more objects */
995     while ((!iRetcode) && (pData->pCurraniobj) &&
996            (!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bFreezing));
997   }
998   else
999   {
1000     if (pData->iBreakpoint)            /* do we need to finish something first ? */
1001     {
1002       switch (pData->iBreakpoint)      /* return to broken display routine */
1003       {
1004 #ifndef MNG_SKIPCHUNK_FRAM
1005         case  1 : { iRetcode = mng_process_display_fram2 (pData); break; }
1006 #endif
1007         case  2 : { iRetcode = mng_process_display_ihdr  (pData); break; }
1008 #ifndef MNG_SKIPCHUNK_SHOW
1009         case  3 : ;                     /* same as 4 !!! */
1010         case  4 : { iRetcode = mng_process_display_show  (pData); break; }
1011 #endif
1012 #ifndef MNG_SKIPCHUNK_CLON
1013         case  5 : { iRetcode = mng_process_display_clon2 (pData); break; }
1014 #endif
1015 #ifdef MNG_INCLUDE_JNG
1016         case  7 : { iRetcode = mng_process_display_jhdr  (pData); break; }
1017 #endif
1018         case  6 : ;                     /* same as 8 !!! */
1019         case  8 : { iRetcode = mng_process_display_iend  (pData); break; }
1020 #ifndef MNG_SKIPCHUNK_MAGN
1021         case  9 : { iRetcode = mng_process_display_magn2 (pData); break; }
1022 #endif
1023         case 10 : { iRetcode = mng_process_display_mend2 (pData); break; }
1024 #ifndef MNG_SKIPCHUNK_PAST
1025         case 11 : { iRetcode = mng_process_display_past2 (pData); break; }
1026 #endif
1027       }
1028     }
1029   }
1030 
1031   if (iRetcode)                        /* on error bail out */
1032     return iRetcode;
1033 
1034 #endif /* MNG_SUPPORT_DISPLAY */
1035                                        /* can we continue processing now, or do we */
1036                                        /* need to wait for the timer to finish (again) ? */
1037 #ifdef MNG_SUPPORT_DISPLAY
1038   if ((!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bEOF))
1039 #else
1040   if (!pData->bEOF)
1041 #endif
1042   {
1043 #ifdef MNG_SUPPORT_DISPLAY
1044                                        /* freezing in progress ? */
1045     if ((pData->bFreezing) && (pData->iSuspendpoint == 0))
1046       pData->bRunning = MNG_FALSE;     /* then this is the right moment to do it */
1047 #endif
1048 
1049     if (pData->iSuspendpoint <= 2)
1050     {
1051       iBuflen  = sizeof (mng_uint32);  /* read length */
1052       iRetcode = read_databuffer (pData, pBuf, &pData->pReadbufnext, iBuflen, &iRead);
1053 
1054       if (iRetcode)                    /* bail on errors */
1055         return iRetcode;
1056 
1057       if (pData->bSuspended)           /* suspended ? */
1058         pData->iSuspendpoint = 2;
1059       else                             /* save the length */
1060       {
1061         pData->iChunklen = mng_get_uint32 (pBuf);
1062         if (pData->iChunklen > 0x7ffffff)
1063            return MNG_INVALIDLENGTH;
1064       }
1065 
1066     }
1067 
1068     if (!pData->bSuspended)            /* still going ? */
1069     {                                  /* previously suspended or not eof ? */
1070       if ((pData->iSuspendpoint > 2) || (iRead == iBuflen))
1071       {                                /* determine length chunkname + data (+ crc) */
1072         if (pData->iCrcmode & MNG_CRC_INPUT)
1073           iBuflen = pData->iChunklen + (mng_uint32)(sizeof (mng_chunkid) + sizeof (mng_uint32));
1074         else
1075           iBuflen = pData->iChunklen + (mng_uint32)(sizeof (mng_chunkid));
1076 
1077                                        /* do we have enough data in the current push buffer ? */
1078         if ((pData->pFirstpushdata) && (iBuflen <= pData->pFirstpushdata->iRemaining))
1079         {
1080           mng_pushdatap pPush  = pData->pFirstpushdata;
1081           pBuf                 = pPush->pDatanext;
1082           pPush->pDatanext    += iBuflen;
1083           pPush->iRemaining   -= iBuflen;
1084           pData->iSuspendpoint = 0;    /* safely reset this here ! */
1085 
1086           iRetcode = check_chunk_crc (pData, pBuf, iBuflen);
1087           if (iRetcode)
1088             return iRetcode;
1089 
1090           if (!pPush->iRemaining)      /* buffer depleted? then release it */
1091             iRetcode = mng_release_pushdata (pData);
1092         }
1093         else
1094         {
1095           if (iBuflen < iBufmax)       /* does it fit in default buffer ? */
1096           {                            /* note that we don't use the full size
1097                                           so there's always a zero-byte at the
1098                                           very end !!! */
1099             iRetcode = read_databuffer (pData, pBuf, &pData->pReadbufnext, iBuflen, &iRead);
1100             if (iRetcode)              /* bail on errors */
1101               return iRetcode;
1102 
1103             if (pData->bSuspended)     /* suspended ? */
1104               pData->iSuspendpoint = 3;
1105             else
1106             {
1107               if (iRead != iBuflen)    /* did we get all the data ? */
1108                 MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
1109               iRetcode = check_chunk_crc (pData, pBuf, iBuflen);
1110             }
1111           }
1112           else
1113           {
1114             if (iBuflen > 16777216)    /* is the length incredible? */
1115               MNG_ERROR (pData, MNG_IMPROBABLELENGTH);
1116 
1117             if (!pData->iSuspendpoint) /* create additional large buffer ? */
1118             {                          /* again reserve space for the last zero-byte */
1119               pData->iLargebufsize = iBuflen + 1;
1120               pData->pLargebufnext = MNG_NULL;
1121               MNG_ALLOC (pData, pData->pLargebuf, pData->iLargebufsize);
1122             }
1123 
1124             iRetcode = read_databuffer (pData, pData->pLargebuf, &pData->pLargebufnext, iBuflen, &iRead);
1125             if (iRetcode)
1126               return iRetcode;
1127 
1128             if (pData->bSuspended)     /* suspended ? */
1129               pData->iSuspendpoint = 4;
1130             else
1131             {
1132               if (iRead != iBuflen)    /* did we get all the data ? */
1133                 MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
1134               iRetcode = check_chunk_crc (pData, pData->pLargebuf, iBuflen);
1135                                        /* cleanup additional large buffer */
1136               MNG_FREE (pData, pData->pLargebuf, pData->iLargebufsize);
1137             }
1138           }
1139         }
1140 
1141         if (iRetcode)                  /* on error bail out */
1142           return iRetcode;
1143 
1144       }
1145       else
1146       {                                /* that's final */
1147         iRetcode = mng_process_eof (pData);
1148 
1149         if (iRetcode)                  /* on error bail out */
1150           return iRetcode;
1151 
1152         if ((iRead != 0) ||            /* did we get an unexpected eof ? */
1153 #ifdef MNG_INCLUDE_JNG
1154             (pData->bHasIHDR || pData->bHasMHDR || pData->bHasJHDR))
1155 #else
1156             (pData->bHasIHDR || pData->bHasMHDR))
1157 #endif
1158           MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
1159       }
1160     }
1161   }
1162 
1163 #ifdef MNG_SUPPORT_DISPLAY             /* refresh needed ? */
1164   if ((!pData->bTimerset) && (!pData->bSuspended) && (pData->bNeedrefresh))
1165   {
1166     iRetcode = mng_display_progressive_refresh (pData, 1);
1167 
1168     if (iRetcode)                      /* on error bail out */
1169       return iRetcode;
1170   }
1171 #endif
1172 
1173 #ifdef MNG_SUPPORT_TRACE
1174   MNG_TRACE (pData, MNG_FN_READ_CHUNK, MNG_LC_END);
1175 #endif
1176 
1177   return MNG_NOERROR;
1178 }
1179 
1180 /* ************************************************************************** */
1181 
process_pushedchunk(mng_datap pData)1182 MNG_LOCAL mng_retcode process_pushedchunk (mng_datap pData)
1183 {
1184   mng_pushdatap pPush;
1185   mng_retcode   iRetcode = MNG_NOERROR;
1186 
1187 #ifdef MNG_SUPPORT_DISPLAY
1188   if (pData->pCurraniobj)              /* processing an animation object ? */
1189   {
1190     do                                 /* process it then */
1191     {
1192       iRetcode = ((mng_object_headerp)pData->pCurraniobj)->fProcess (pData, pData->pCurraniobj);
1193                                        /* refresh needed ? */
1194 /*      if ((!iRetcode) && (!pData->bTimerset) && (pData->bNeedrefresh))
1195         iRetcode = display_progressive_refresh (pData, 1); */
1196                                        /* can we advance to next object ? */
1197       if ((!iRetcode) && (pData->pCurraniobj) &&
1198           (!pData->bTimerset) && (!pData->bSectionwait))
1199       {                                /* reset timer indicator on read-cycle */
1200         if ((pData->bReading) && (!pData->bDisplaying))
1201           pData->bTimerset = MNG_FALSE;
1202 
1203         pData->pCurraniobj = ((mng_object_headerp)pData->pCurraniobj)->pNext;
1204                                        /* TERM processing to be done ? */
1205         if ((!pData->pCurraniobj) && (pData->bHasTERM) && (!pData->bHasMHDR))
1206           iRetcode = mng_process_display_mend (pData);
1207       }
1208     }                                  /* until error or a break or no more objects */
1209     while ((!iRetcode) && (pData->pCurraniobj) &&
1210            (!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bFreezing));
1211   }
1212   else
1213   {
1214     if (pData->iBreakpoint)            /* do we need to finish something first ? */
1215     {
1216       switch (pData->iBreakpoint)      /* return to broken display routine */
1217       {
1218 #ifndef MNG_SKIPCHUNK_FRAM
1219         case  1 : { iRetcode = mng_process_display_fram2 (pData); break; }
1220 #endif
1221         case  2 : { iRetcode = mng_process_display_ihdr  (pData); break; }
1222 #ifndef MNG_SKIPCHUNK_SHOW
1223         case  3 : ;                     /* same as 4 !!! */
1224         case  4 : { iRetcode = mng_process_display_show  (pData); break; }
1225 #endif
1226 #ifndef MNG_SKIPCHUNK_CLON
1227         case  5 : { iRetcode = mng_process_display_clon2 (pData); break; }
1228 #endif
1229 #ifdef MNG_INCLUDE_JNG
1230         case  7 : { iRetcode = mng_process_display_jhdr  (pData); break; }
1231 #endif
1232         case  6 : ;                     /* same as 8 !!! */
1233         case  8 : { iRetcode = mng_process_display_iend  (pData); break; }
1234 #ifndef MNG_SKIPCHUNK_MAGN
1235         case  9 : { iRetcode = mng_process_display_magn2 (pData); break; }
1236 #endif
1237         case 10 : { iRetcode = mng_process_display_mend2 (pData); break; }
1238 #ifndef MNG_SKIPCHUNK_PAST
1239         case 11 : { iRetcode = mng_process_display_past2 (pData); break; }
1240 #endif
1241       }
1242     }
1243   }
1244 
1245   if (iRetcode)                        /* on error bail out */
1246     return iRetcode;
1247 
1248 #endif /* MNG_SUPPORT_DISPLAY */
1249                                        /* can we continue processing now, or do we */
1250                                        /* need to wait for the timer to finish (again) ? */
1251 #ifdef MNG_SUPPORT_DISPLAY
1252   if ((!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bEOF))
1253 #else
1254   if (!pData->bEOF)
1255 #endif
1256   {
1257     pData->iSuspendpoint = 0;            /* safely reset it here ! */
1258     pPush = pData->pFirstpushchunk;
1259 
1260     iRetcode = process_raw_chunk (pData, pPush->pData, pPush->iLength);
1261     if (iRetcode)
1262       return iRetcode;
1263 
1264 #ifdef MNG_SUPPORT_DISPLAY             /* refresh needed ? */
1265     if ((!pData->bTimerset) && (!pData->bSuspended) && (pData->bNeedrefresh))
1266     {
1267       iRetcode = mng_display_progressive_refresh (pData, 1);
1268       if (iRetcode)                      /* on error bail out */
1269         return iRetcode;
1270     }
1271 #endif
1272   }
1273 
1274   return mng_release_pushchunk (pData);
1275 }
1276 
1277 /* ************************************************************************** */
1278 
mng_read_graphic(mng_datap pData)1279 mng_retcode mng_read_graphic (mng_datap pData)
1280 {
1281   mng_uint32  iBuflen;                 /* number of bytes requested */
1282   mng_uint32  iRead;                   /* number of bytes read */
1283   mng_retcode iRetcode;                /* temporary error-code */
1284 
1285 #ifdef MNG_SUPPORT_TRACE
1286   MNG_TRACE (pData, MNG_FN_READ_GRAPHIC, MNG_LC_START);
1287 #endif
1288 
1289   if (!pData->pReadbuf)                /* buffer allocated ? */
1290   {
1291     pData->iReadbufsize = 4200;        /* allocate a default read buffer */
1292     MNG_ALLOC (pData, pData->pReadbuf, pData->iReadbufsize);
1293   }
1294                                        /* haven't processed the signature ? */
1295   if ((!pData->bHavesig) || (pData->iSuspendpoint == 1))
1296   {
1297     iBuflen = 2 * sizeof (mng_uint32); /* read signature */
1298 
1299     iRetcode = read_databuffer (pData, pData->pReadbuf, &pData->pReadbufnext, iBuflen, &iRead);
1300 
1301     if (iRetcode)
1302       return iRetcode;
1303 
1304     if (pData->bSuspended)             /* input suspension ? */
1305       pData->iSuspendpoint = 1;
1306     else
1307     {
1308       if (iRead != iBuflen)            /* full signature received ? */
1309         MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
1310                                        /* is it a valid signature ? */
1311       if (mng_get_uint32 (pData->pReadbuf) == PNG_SIG)
1312         pData->eSigtype = mng_it_png;
1313       else
1314 #ifdef MNG_INCLUDE_JNG
1315       if (mng_get_uint32 (pData->pReadbuf) == JNG_SIG)
1316         pData->eSigtype = mng_it_jng;
1317       else
1318 #endif
1319       if (mng_get_uint32 (pData->pReadbuf) == MNG_SIG)
1320         pData->eSigtype = mng_it_mng;
1321       else
1322         MNG_ERROR (pData, MNG_INVALIDSIG);
1323                                        /* all of it ? */
1324       if (mng_get_uint32 (pData->pReadbuf+4) != POST_SIG)
1325         MNG_ERROR (pData, MNG_INVALIDSIG);
1326 
1327       pData->bHavesig = MNG_TRUE;
1328     }
1329   }
1330 
1331   if (!pData->bSuspended)              /* still going ? */
1332   {
1333     do
1334     {                                  /* reset timer during mng_read() ? */
1335       if ((pData->bReading) && (!pData->bDisplaying))
1336         pData->bTimerset = MNG_FALSE;
1337 
1338       if (pData->pFirstpushchunk)      /* chunks pushed ? */
1339         iRetcode = process_pushedchunk (pData); /* process the pushed chunk */
1340       else
1341         iRetcode = read_chunk (pData); /* read & process a chunk */
1342 
1343       if (iRetcode)                    /* on error bail out */
1344         return iRetcode;
1345     }
1346 #ifdef MNG_SUPPORT_DISPLAY             /* until EOF or a break-request */
1347     while (((!pData->bEOF) || (pData->pCurraniobj)) &&
1348            (!pData->bSuspended) && (!pData->bSectionwait) &&
1349            ((!pData->bTimerset) || ((pData->bReading) && (!pData->bDisplaying))));
1350 #else
1351     while ((!pData->bEOF) && (!pData->bSuspended));
1352 #endif
1353   }
1354 
1355 #ifdef MNG_SUPPORT_TRACE
1356   MNG_TRACE (pData, MNG_FN_READ_GRAPHIC, MNG_LC_END);
1357 #endif
1358 
1359   return MNG_NOERROR;
1360 }
1361 
1362 /* ************************************************************************** */
1363 
1364 #endif /* MNG_INCLUDE_READ_PROCS */
1365 
1366 /* ************************************************************************** */
1367 /* * end of file                                                            * */
1368 /* ************************************************************************** */
1369 
1370