]> icculus.org git repositories - btb/d2x.git/blob - iff/iff.c
function prototypes
[btb/d2x.git] / iff / iff.c
1 /* $Id: iff.c,v 1.7 2003-10-04 03:14:47 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Routines for reading and writing IFF files
18  *
19  * Old Log:
20  * Revision 1.2  1995/05/12  11:54:43  allender
21  * changed memory stuff again
22  *
23  * Revision 1.1  1995/05/05  08:59:41  allender
24  * Initial revision
25  *
26  * Revision 1.43  1994/12/08  19:03:17  john
27  * Added code to use cfile.
28  *
29  * Revision 1.42  1994/12/08  17:45:32  john
30  * Put back in cfile stuff.
31  *
32  * Revision 1.41  1994/11/19  16:41:06  matt
33  * Took out unused code
34  *
35  * Revision 1.40  1994/11/07  21:26:39  matt
36  * Added new function iff_read_into_bitmap()
37  *
38  * Revision 1.39  1994/10/27  00:12:03  john
39  * Used nocfile
40  *
41  * Revision 1.38  1994/08/10  19:49:58  matt
42  * Fixed bitmaps in ILBM format with masking (stencil) on.
43  *
44  * Revision 1.37  1994/06/02  18:53:17  matt
45  * Clear flags & selector in new bitmap structure
46  *
47  * Revision 1.36  1994/05/17  14:00:33  matt
48  * Fixed bug with odd-width deltas & odd-length body chunks
49  *
50  * Revision 1.35  1994/05/16  20:38:55  matt
51  * Made anim brushes work when odd width
52  *
53  * Revision 1.34  1994/05/06  19:37:26  matt
54  * Improved error handling and checking
55  *
56  * Revision 1.33  1994/04/27  20:57:07  matt
57  * Fixed problem with RLE decompression and odd-width bitmap
58  * Added more error checking
59  *
60  * Revision 1.32  1994/04/16  21:44:19  matt
61  * Fixed bug introduced last version
62  *
63  * Revision 1.31  1994/04/16  20:12:40  matt
64  * Made masked (stenciled) bitmaps work
65  *
66  * Revision 1.30  1994/04/13  23:46:16  matt
67  * Added function, iff_errormsg(), which returns ptr to error message.
68  *
69  * Revision 1.29  1994/04/13  23:27:25  matt
70  * Put in support for anim brushes (.abm files)
71  *
72  * Revision 1.28  1994/04/13  16:33:31  matt
73  * Cleaned up file read code, adding fake_file structure (FFILE), which
74  * cleanly implements reading the entire file into a buffer and then reading
75  * out of that buffer.
76  *
77  * Revision 1.27  1994/04/06  23:07:43  matt
78  * Cleaned up code; added prototype (but no new code) for anim brush read
79  *
80  * Revision 1.26  1994/03/19  02:51:52  matt
81  * Really did what I said I did last revision.
82  *
83  * Revision 1.25  1994/03/19  02:16:07  matt
84  * Made work ILBMs which didn't have 8 planes
85  *
86  * Revision 1.24  1994/03/15  14:45:26  matt
87  * When error, only free memory if has been allocated
88  *
89  * Revision 1.23  1994/02/18  12:39:05  john
90  * Made code read from buffer.
91  *
92  * Revision 1.22  1994/02/15  18:15:26  john
93  * Took out cfile attempt (too slow)
94  *
95  * Revision 1.21  1994/02/15  13:17:48  john
96  * added assert to cfseek.
97  *
98  * Revision 1.20  1994/02/15  13:13:11  john
99  * Made iff code work normally.
100  *
101  * Revision 1.19  1994/02/15  12:51:07  john
102  * crappy inbetween version.
103  *
104  * Revision 1.18  1994/02/10  18:31:32  matt
105  * Changed 'if DEBUG_ON' to 'ifndef NDEBUG'
106  *
107  * Revision 1.17  1994/01/24  11:51:26  john
108  * Made write routine write transparency info.
109  *
110  * Revision 1.16  1994/01/22  14:41:11  john
111  * Fixed bug with declareations.
112  *
113  * Revision 1.15  1994/01/22  14:23:00  john
114  * Added global vars to check transparency
115  *
116  * Revision 1.14  1993/12/08  19:00:42  matt
117  * Changed while loop to memset
118  *
119  * Revision 1.13  1993/12/08  17:23:51  mike
120  * Speedup by converting while...getc to fread.
121  *
122  * Revision 1.12  1993/12/08  12:37:35  mike
123  * Optimize parse_body.
124  *
125  * Revision 1.11  1993/12/05  17:30:14  matt
126  * Made bitmaps with width <= 64 not compress
127  *
128  * Revision 1.10  1993/12/03  12:24:51  matt
129  * Fixed TINY chunk when bitmap was part of a larger bitmap
130  *
131  * Revision 1.9  1993/11/22  17:26:43  matt
132  * iff write now writes out a tiny chunk
133  *
134  * Revision 1.8  1993/11/21  22:04:13  matt
135  * Fixed error with non-compressed bitmaps
136  * Added Yuan's code to free raw data if we get an error parsing the body
137  *
138  * Revision 1.7  1993/11/11  12:12:12  yuan
139  * Changed mallocs to MALLOCs.
140  *
141  * Revision 1.6  1993/11/01  19:02:23  matt
142  * Fixed a couple bugs in rle compression
143  *
144  * Revision 1.5  1993/10/27  12:47:39  john
145  * *** empty log message ***
146  *
147  * Revision 1.4  1993/10/27  12:37:31  yuan
148  * Added mem.h
149  *
150  * Revision 1.3  1993/09/22  19:16:57  matt
151  * Added new error type, IFF_CORRUPT, for internally bad IFF files.
152  *
153  * Revision 1.2  1993/09/08  19:24:16  matt
154  * Fixed bug in RLE compression
155  * Changed a bunch of unimportant values like aspect and page size when writing
156  * Added new error condition, IFF_BAD_BM_TYPE
157  * Make sub-bitmaps work correctly
158  * Added compile flag to turn compression off (COMPRESS)
159  *
160  * Revision 1.1  1993/09/08  14:24:15  matt
161  * Initial revision
162  *
163  *
164  */
165
166 #ifdef HAVE_CONFIG_H
167 #include <conf.h>
168 #endif
169
170 #ifdef RCS
171 static char rcsid[] = "$Id: iff.c,v 1.7 2003-10-04 03:14:47 btb Exp $";
172 #endif
173
174 #define COMPRESS                1       //do the RLE or not? (for debugging mostly)
175 #define WRITE_TINY      0       //should we write a TINY chunk?
176
177 #define MIN_COMPRESS_WIDTH      65      //don't compress if less than this wide
178
179 #include <stdio.h>
180 #include <stdlib.h>
181 #include <string.h>
182
183 #include "u_mem.h"
184 #include "iff.h"
185
186 //#include "nocfile.h"
187 #include "cfile.h"
188 #include "error.h"
189
190 //Internal constants and structures for this library
191
192 //Type values for bitmaps
193 #define TYPE_PBM                0
194 #define TYPE_ILBM               1
195
196 //Compression types
197 #define cmpNone 0
198 #define cmpByteRun1     1
199
200 //Masking types
201 #define mskNone 0
202 #define mskHasMask      1
203 #define mskHasTransparentColor 2
204
205 //Palette entry structure
206 typedef struct pal_entry {
207         sbyte r,g,b;
208 } pal_entry;
209
210 //structure of the header in the file
211 typedef struct iff_bitmap_header {
212         short w,h;                                              //width and height of this bitmap
213         short x,y;                                              //generally unused
214         short type;                                             //see types above
215         short transparentcolor;         //which color is transparent (if any)
216         short pagewidth,pageheight; //width & height of source screen
217         sbyte nplanes;              //number of planes (8 for 256 color image)
218         sbyte masking,compression;  //see constants above
219         sbyte xaspect,yaspect;      //aspect ratio (usually 5/6)
220         pal_entry palette[256];         //the palette for this bitmap
221         ubyte *raw_data;                                //ptr to array of data
222         short row_size;                         //offset to next row
223 } iff_bitmap_header;
224
225 ubyte iff_transparent_color;
226 ubyte iff_has_transparency;     // 0=no transparency, 1=iff_transparent_color is valid
227
228 typedef struct fake_file {
229         ubyte *data;
230         int position;
231         int length;
232 } FFILE;
233
234 #define MIN(a,b) ((a<b)?a:b)
235
236 #define MAKE_SIG(a,b,c,d) (((long)(a)<<24)+((long)(b)<<16)+((c)<<8)+(d))
237
238 #define form_sig MAKE_SIG('F','O','R','M')
239 #define ilbm_sig MAKE_SIG('I','L','B','M')
240 #define body_sig MAKE_SIG('B','O','D','Y')
241 #define pbm_sig  MAKE_SIG('P','B','M',' ')
242 #define bmhd_sig MAKE_SIG('B','M','H','D')
243 #define anhd_sig MAKE_SIG('A','N','H','D')
244 #define cmap_sig MAKE_SIG('C','M','A','P')
245 #define tiny_sig MAKE_SIG('T','I','N','Y')
246 #define anim_sig MAKE_SIG('A','N','I','M')
247 #define dlta_sig MAKE_SIG('D','L','T','A')
248
249 #ifndef NDEBUG
250 //void printsig(long s)
251 //{
252 //      char *t=(char *) &s;
253 //
254 ///*  printf("%c%c%c%c",*(&s+3),*(&s+2),*(&s+1),s);*/
255 //      printf("%c%c%c%c",t[3],t[2],t[1],t[0]);
256 //}
257 #endif
258
259 long get_sig(FFILE *f)
260 {
261         char s[4];
262
263 //      if ((s[3]=cfgetc(f))==EOF) return(EOF);
264 //      if ((s[2]=cfgetc(f))==EOF) return(EOF);
265 //      if ((s[1]=cfgetc(f))==EOF) return(EOF);
266 //      if ((s[0]=cfgetc(f))==EOF) return(EOF);
267
268 #ifndef WORDS_BIGENDIAN
269         if (f->position>=f->length) return EOF;
270         s[3] = f->data[f->position++];
271         if (f->position>=f->length) return EOF;
272         s[2] = f->data[f->position++];
273         if (f->position>=f->length) return EOF;
274         s[1] = f->data[f->position++];
275         if (f->position>=f->length) return EOF;
276         s[0] = f->data[f->position++];
277 #else
278         if (f->position>=f->length) return EOF;
279         s[0] = f->data[f->position++];
280         if (f->position>=f->length) return EOF;
281         s[1] = f->data[f->position++];
282         if (f->position>=f->length) return EOF;
283         s[2] = f->data[f->position++];
284         if (f->position>=f->length) return EOF;
285         s[3] = f->data[f->position++];
286 #endif
287
288         return(*((long *) s));
289 }
290
291 int put_sig(long sig,FILE *f)
292 {
293         char *s = (char *) &sig;
294
295         fputc(s[3],f);
296         fputc(s[2],f);
297         fputc(s[1],f);
298         return fputc(s[0],f);
299
300 }
301         
302 char get_byte(FFILE *f)
303 {
304         //return cfgetc(f);
305         return f->data[f->position++];
306 }
307
308 int put_byte(unsigned char c,FILE *f)
309 {
310         return fputc(c,f);
311 }
312
313 int get_word(FFILE *f)
314 {
315         unsigned char c0,c1;
316
317 //      c1=cfgetc(f);
318 //      c0=cfgetc(f);
319
320         if (f->position>=f->length) return EOF;
321         c1 = f->data[f->position++];
322         if (f->position>=f->length) return EOF;
323         c0 = f->data[f->position++];
324
325         if (c0==0xff) return(EOF);
326
327         return(((int)c1<<8) + c0);
328
329 }
330
331 int put_word(int n,FILE *f)
332 {
333         unsigned char c0,c1;
334
335         c0 = (n & 0xff00) >> 8;
336         c1 = n & 0xff;
337
338         put_byte(c0,f);
339         return put_byte(c1,f);
340 }
341
342 int put_long(long n,FILE *f)
343 {
344         int n0,n1;
345
346         n0 = (int) ((n & 0xffff0000l) >> 16);
347         n1 = (int) (n & 0xffff);
348
349         put_word(n0,f);
350         return put_word(n1,f);
351
352 }
353
354 long get_long(FFILE *f)
355 {
356         unsigned char c0,c1,c2,c3;
357
358         //c3=cfgetc(f);
359         //c2=cfgetc(f);
360         //c1=cfgetc(f);
361         //c0=cfgetc(f);
362
363         if (f->position>=f->length) return EOF;
364         c3 = f->data[f->position++];
365         if (f->position>=f->length) return EOF;
366         c2 = f->data[f->position++];
367         if (f->position>=f->length) return EOF;
368         c1 = f->data[f->position++];
369         if (f->position>=f->length) return EOF;
370         c0 = f->data[f->position++];
371
372 //printf("get_long %x %x %x %x\n",c3,c2,c1,c0);
373
374 //  if (c0==0xff) return(EOF);
375
376         return(((long)c3<<24) + ((long)c2<<16) + ((long)c1<<8) + c0);
377
378 }
379
380 int parse_bmhd(FFILE *ifile,long len,iff_bitmap_header *bmheader)
381 {
382         len++;  /* so no "parm not used" warning */
383
384 //  debug("parsing bmhd len=%ld\n",len);
385
386         bmheader->w = get_word(ifile);
387         bmheader->h = get_word(ifile);
388         bmheader->x = get_word(ifile);
389         bmheader->y = get_word(ifile);
390
391         bmheader->nplanes = get_byte(ifile);
392         bmheader->masking = get_byte(ifile);
393         bmheader->compression = get_byte(ifile);
394         get_byte(ifile);        /* skip pad */
395
396         bmheader->transparentcolor = get_word(ifile);
397         bmheader->xaspect = get_byte(ifile);
398         bmheader->yaspect = get_byte(ifile);
399
400         bmheader->pagewidth = get_word(ifile);
401         bmheader->pageheight = get_word(ifile);
402
403         iff_transparent_color = bmheader->transparentcolor;
404
405         iff_has_transparency = 0;
406
407         if (bmheader->masking == mskHasTransparentColor)
408                 iff_has_transparency = 1;
409
410         else if (bmheader->masking != mskNone && bmheader->masking != mskHasMask)
411                 return IFF_UNKNOWN_MASK;
412
413 //  debug("w,h=%d,%d x,y=%d,%d\n",w,h,x,y);
414 //  debug("nplanes=%d, masking=%d ,compression=%d, transcolor=%d\n",nplanes,masking,compression,transparentcolor);
415
416         return IFF_NO_ERROR;
417 }
418
419
420 //  the buffer pointed to by raw_data is stuffed with a pointer to decompressed pixel data
421 int parse_body(FFILE *ifile,long len,iff_bitmap_header *bmheader)
422 {
423         unsigned char  *p=bmheader->raw_data;
424         int width,depth;
425         signed char n;
426         int nn,wid_cnt,end_cnt,plane;
427         char ignore=0;
428         unsigned char *data_end;
429         int end_pos;
430         #ifndef NDEBUG
431         int row_count=0;
432         #endif
433
434         width=0;
435         depth=0;
436
437         end_pos = ifile->position + len;
438         if (len&1)
439                 end_pos++;
440
441         if (bmheader->type == TYPE_PBM) {
442                 width=bmheader->w;
443                 depth=1;
444         } else if (bmheader->type == TYPE_ILBM) {
445                 width = (bmheader->w+7)/8;
446                 depth=bmheader->nplanes;
447         }
448
449         end_cnt = (width&1)?-1:0;
450
451         data_end = p + width*bmheader->h*depth;
452
453         if (bmheader->compression == cmpNone) {        /* no compression */
454                 int y;
455
456                 for (y=bmheader->h;y;y--) {
457                         int x;
458 //                      for (x=bmheader->w;x;x--) *p++=cfgetc(ifile);
459 //                      cfread(p, bmheader->w, 1, ifile);
460 //                      p += bmheader->w;
461
462                         for (x=0;x<width*depth;x++)
463                                 *p++=ifile->data[ifile->position++];
464
465                         if (bmheader->masking == mskHasMask)
466                                 ifile->position += width;                               //skip mask!
467
468 //                      if (bmheader->w & 1) ignore = cfgetc(ifile);
469                         if (bmheader->w & 1) ifile->position++;
470                 }
471
472                 //cnt = len - bmheader->h * ((bmheader->w+1)&~1);
473
474         }
475         else if (bmheader->compression == cmpByteRun1)
476                 for (wid_cnt=width,plane=0;ifile->position<end_pos && p<data_end;) {
477                         unsigned char c;
478
479 //                      if (old_cnt-cnt > 2048) {
480 //              printf(".");
481 //                              old_cnt=cnt;
482 //                      }
483
484                         if (wid_cnt == end_cnt) {
485                                 wid_cnt = width;
486                                 plane++;
487                                 if ((bmheader->masking == mskHasMask && plane==depth+1) ||
488                                     (bmheader->masking != mskHasMask && plane==depth))
489                                         plane=0;
490                         }
491
492                         Assert(wid_cnt > end_cnt);
493
494                         //n=cfgetc(ifile);
495                         n=ifile->data[ifile->position++];
496
497                         if (n >= 0) {                       // copy next n+1 bytes from source, they are not compressed
498                                 nn = (int) n+1;
499                                 wid_cnt -= nn;
500                                 if (wid_cnt==-1) {--nn; Assert(width&1);}
501                                 if (plane==depth)       //masking row
502                                         ifile->position += nn;
503                                 else
504                                         while (nn--) *p++=ifile->data[ifile->position++];
505                                 if (wid_cnt==-1) ifile->position++;
506                         }
507                         else if (n>=-127) {             // next -n + 1 bytes are following byte
508                                 c=ifile->data[ifile->position++];
509                                 nn = (int) -n+1;
510                                 wid_cnt -= nn;
511                                 if (wid_cnt==-1) {--nn; Assert(width&1);}
512                                 if (plane!=depth)       //not masking row
513                                         {memset(p,c,nn); p+=nn;}
514                         }
515
516                         #ifndef NDEBUG
517                         if ((p-bmheader->raw_data) % width == 0)
518                                         row_count++;
519
520                         Assert((p-bmheader->raw_data) - (width*row_count) < width);
521                         #endif
522
523                 }
524
525         if (p!=data_end)                                //if we don't have the whole bitmap...
526                 return IFF_CORRUPT;             //...the give an error
527
528         //Pretend we read the whole chuck, because if we didn't, it's because
529         //we didn't read the last mask like or the last rle record for padding
530         //or whatever and it's not important, because we check to make sure
531         //we got the while bitmap, and that's what really counts.
532
533         ifile->position = end_pos;
534         
535         if (ignore) ignore++;   // haha, suppress the evil warning message
536
537         return IFF_NO_ERROR;
538 }
539
540 //modify passed bitmap
541 int parse_delta(FFILE *ifile,long len,iff_bitmap_header *bmheader)
542 {
543         unsigned char  *p=bmheader->raw_data;
544         int y;
545         long chunk_end = ifile->position + len;
546
547         get_long(ifile);                //longword, seems to be equal to 4.  Don't know what it is
548
549         for (y=0;y<bmheader->h;y++) {
550                 ubyte n_items;
551                 int cnt = bmheader->w;
552                 ubyte code;
553
554                 n_items = get_byte(ifile);
555
556                 while (n_items--) {
557
558                         code = get_byte(ifile);
559
560                         if (code==0) {                          //repeat
561                                 ubyte rep,val;
562
563                                 rep = get_byte(ifile);
564                                 val = get_byte(ifile);
565
566                                 cnt -= rep;
567                                 if (cnt==-1)
568                                         rep--;
569                                 while (rep--)
570                                         *p++ = val;
571                         }
572                         else if (code > 0x80) { //skip
573                                 cnt -= (code-0x80);
574                                 p += (code-0x80);
575                                 if (cnt==-1)
576                                         p--;
577                         }
578                         else {                                          //literal
579                                 cnt -= code;
580                                 if (cnt==-1)
581                                         code--;
582
583                                 while (code--)
584                                         *p++ = get_byte(ifile);
585
586                                 if (cnt==-1)
587                                         get_byte(ifile);
588                         }
589
590                 }
591
592                 if (cnt == -1) {
593                         if (!bmheader->w&1)
594                                 return IFF_CORRUPT;
595                 }
596                 else if (cnt)
597                         return IFF_CORRUPT;
598         }
599
600         if (ifile->position == chunk_end-1)             //pad
601                 ifile->position++;
602
603         if (ifile->position != chunk_end)
604                 return IFF_CORRUPT;
605         else
606                 return IFF_NO_ERROR;
607 }
608
609 //  the buffer pointed to by raw_data is stuffed with a pointer to bitplane pixel data
610 void skip_chunk(FFILE *ifile,long len)
611 {
612         //int c,i;
613         int ilen;
614         ilen = (len+1) & ~1;
615
616 //printf( "Skipping %d chunk\n", ilen );
617
618         ifile->position += ilen;
619
620         if (ifile->position >= ifile->length )  {
621                 ifile->position = ifile->length;
622         }
623
624
625 //      for (i=0; i<ilen; i++ )
626 //              c = cfgetc(ifile);
627         //Assert(cfseek(ifile,ilen,SEEK_CUR)==0);
628 }
629
630 //read an ILBM or PBM file
631 // Pass pointer to opened file, and to empty bitmap_header structure, and form length
632 int iff_parse_ilbm_pbm(FFILE *ifile,long form_type,iff_bitmap_header *bmheader,int form_len,grs_bitmap *prev_bm)
633 {
634         long sig,len;
635         //char ignore=0;
636         long start_pos,end_pos;
637
638         start_pos = ifile->position;
639         end_pos = start_pos-4+form_len;
640
641 //      printf(" %ld ",form_len);
642 //      printsig(form_type);
643 //      printf("\n");
644
645                         if (form_type == pbm_sig)
646                                 bmheader->type = TYPE_PBM;
647                         else
648                                 bmheader->type = TYPE_ILBM;
649
650                         while ((ifile->position < end_pos) && (sig=get_sig(ifile)) != EOF) {
651
652                                 len=get_long(ifile);
653                                 if (len==EOF) break;
654
655 //              printf(" ");
656 //              printsig(sig);
657 //              printf(" %ld\n",len);
658
659                                 switch (sig) {
660
661                                         case bmhd_sig: {
662                                                 int ret;
663                                                 int save_w=bmheader->w,save_h=bmheader->h;
664
665                                                 //printf("Parsing header\n");
666
667                                                 ret = parse_bmhd(ifile,len,bmheader);
668
669                                                 if (ret != IFF_NO_ERROR)
670                                                         return ret;
671
672                                                 if (bmheader->raw_data) {
673
674                                                         if (save_w != bmheader->w  ||  save_h != bmheader->h)
675                                                                 return IFF_BM_MISMATCH;
676
677                                                 }
678                                                 else {
679
680                                                         MALLOC( bmheader->raw_data, ubyte, bmheader->w * bmheader->h );
681                                                         if (!bmheader->raw_data)
682                                                                 return IFF_NO_MEM;
683                                                 }
684
685                                                 break;
686
687                                         }
688
689                                         case anhd_sig:
690
691                                                 if (!prev_bm) return IFF_CORRUPT;
692
693                                                 bmheader->w = prev_bm->bm_w;
694                                                 bmheader->h = prev_bm->bm_h;
695                                                 bmheader->type = prev_bm->bm_type;
696
697                                                 MALLOC( bmheader->raw_data, ubyte, bmheader->w * bmheader->h );
698
699                                                 memcpy(bmheader->raw_data, prev_bm->bm_data, bmheader->w * bmheader->h );
700                                                 skip_chunk(ifile,len);
701
702                                                 break;
703
704                                         case cmap_sig:
705                                         {
706                                                 int ncolors=(int) (len/3),cnum;
707                                                 unsigned char r,g,b;
708
709                                                 //printf("Parsing RGB map\n");
710                                                 for (cnum=0;cnum<ncolors;cnum++) {
711 //                                                      r=cfgetc(ifile);
712 //                                                      g=cfgetc(ifile);
713 //                                                      b=cfgetc(ifile);
714                                                         r = ifile->data[ifile->position++];
715                                                         g = ifile->data[ifile->position++];
716                                                         b = ifile->data[ifile->position++];
717                                                         r >>= 2; bmheader->palette[cnum].r = r;
718                                                         g >>= 2; bmheader->palette[cnum].g = g;
719                                                         b >>= 2; bmheader->palette[cnum].b = b;
720                                                 }
721                                                 //if (len & 1) ignore = cfgetc(ifile);
722                                                 if (len & 1 ) ifile->position++;
723
724                                                 break;
725                                         }
726
727                                         case body_sig:
728                                         {
729                                                 int r;
730                                                 //printf("Parsing body\n");
731                                                 if ((r=parse_body(ifile,len,bmheader))!=IFF_NO_ERROR)
732                                                         return r;
733                                                 break;
734                                         }
735                                         case dlta_sig:
736                                         {
737                                                 int r;
738                                                 if ((r=parse_delta(ifile,len,bmheader))!=IFF_NO_ERROR)
739                                                         return r;
740                                                 break;
741                                         }
742                                         default:
743                                                 skip_chunk(ifile,len);
744                                                 break;
745                                 }
746                         }
747
748         //if (ignore) ignore++;
749
750         if (ifile->position != start_pos-4+form_len)
751                 return IFF_CORRUPT;
752
753         return IFF_NO_ERROR;    /* ok! */
754 }
755
756 //convert an ILBM file to a PBM file
757 int convert_ilbm_to_pbm(iff_bitmap_header *bmheader)
758 {
759         int x,y,p;
760         sbyte *new_data, *destptr, *rowptr;
761         int bytes_per_row,byteofs;
762         ubyte checkmask,newbyte,setbit;
763
764         MALLOC(new_data, sbyte, bmheader->w * bmheader->h);
765         if (new_data == NULL) return IFF_NO_MEM;
766
767         destptr = new_data;
768
769         bytes_per_row = 2*((bmheader->w+15)/16);
770
771         for (y=0;y<bmheader->h;y++) {
772
773                 rowptr = &bmheader->raw_data[y * bytes_per_row * bmheader->nplanes];
774
775                 for (x=0,checkmask=0x80;x<bmheader->w;x++) {
776
777                         byteofs = x >> 3;
778
779                         for (p=newbyte=0,setbit=1;p<bmheader->nplanes;p++) {
780
781                                 if (rowptr[bytes_per_row * p + byteofs] & checkmask)
782                                         newbyte |= setbit;
783
784                                 setbit <<= 1;
785                         }
786
787                         *destptr++ = newbyte;
788
789                         if ((checkmask >>= 1) == 0) checkmask=0x80;
790                 }
791
792         }
793
794         d_free(bmheader->raw_data);
795         bmheader->raw_data = new_data;
796
797         bmheader->type = TYPE_PBM;
798
799         return IFF_NO_ERROR;
800 }
801
802 #define INDEX_TO_15BPP(i) ((short)((((palptr[(i)].r/2)&31)<<10)+(((palptr[(i)].g/2)&31)<<5)+((palptr[(i)].b/2 )&31)))
803
804 int convert_rgb15(grs_bitmap *bm,iff_bitmap_header *bmheader)
805 {
806         ushort *new_data;
807         int x,y;
808         int newptr = 0;
809         pal_entry *palptr;
810
811         palptr = bmheader->palette;
812
813 //        if ((new_data = d_malloc(bm->bm_w * bm->bm_h * 2)) == NULL)
814 //            {ret=IFF_NO_MEM; goto done;}
815        MALLOC(new_data, ushort, bm->bm_w * bm->bm_h * 2);
816        if (new_data == NULL)
817            return IFF_NO_MEM;
818
819         for (y=0; y<bm->bm_h; y++) {
820
821                 for (x=0; x<bmheader->w; x++)
822                         new_data[newptr++] = INDEX_TO_15BPP(bmheader->raw_data[y*bmheader->w+x]);
823
824         }
825
826         d_free(bm->bm_data);                            //get rid of old-style data
827         bm->bm_data = (ubyte *) new_data;                       //..and point to new data
828
829         bm->bm_rowsize *= 2;                            //two bytes per row
830
831         return IFF_NO_ERROR;
832
833 }
834
835 //read in a entire file into a fake file structure
836 int open_fake_file(char *ifilename,FFILE *ffile)
837 {
838         CFILE *ifile;
839         int ret;
840
841         //printf( "Reading %s\n", ifilename );
842
843         ffile->data=NULL;
844
845         if ((ifile = cfopen(ifilename,"rb")) == NULL) return IFF_NO_FILE;
846
847         ffile->length = cfilelength(ifile);
848
849         MALLOC(ffile->data,ubyte,ffile->length);
850
851         if (cfread(ffile->data, 1, ffile->length, ifile) < ffile->length)
852                 ret = IFF_READ_ERROR;
853         else
854                 ret = IFF_NO_ERROR;
855
856         ffile->position = 0;
857
858         if (ifile) cfclose(ifile);
859
860         return ret;
861 }
862
863 void close_fake_file(FFILE *f)
864 {
865         if (f->data)
866                 d_free(f->data);
867
868         f->data = NULL;
869 }
870
871 //copy an iff header structure to a grs_bitmap structure
872 void copy_iff_to_grs(grs_bitmap *bm,iff_bitmap_header *bmheader)
873 {
874         bm->bm_x = bm->bm_y = 0;
875         bm->bm_w = bmheader->w;
876         bm->bm_h = bmheader->h;
877         bm->bm_type = bmheader->type;
878         bm->bm_rowsize = bmheader->w;
879         bm->bm_data = bmheader->raw_data;
880
881         bm->bm_flags = bm->bm_handle = 0;
882         
883 }
884
885 //if bm->bm_data is set, use it (making sure w & h are correct), else
886 //allocate the memory
887 int iff_parse_bitmap(FFILE *ifile, grs_bitmap *bm, int bitmap_type, sbyte *palette, grs_bitmap *prev_bm)
888 {
889         int ret;                        //return code
890         iff_bitmap_header bmheader;
891         long sig,form_len;
892         long form_type;
893
894         bmheader.raw_data = bm->bm_data;
895
896         if (bmheader.raw_data) {
897                 bmheader.w = bm->bm_w;
898                 bmheader.h = bm->bm_h;
899         }
900
901         sig=get_sig(ifile);
902
903         if (sig != form_sig) {
904                 return IFF_NOT_IFF;
905         }
906
907         form_len = get_long(ifile);
908
909         form_type = get_sig(ifile);
910
911         if (form_type == anim_sig)
912                 ret = IFF_FORM_ANIM;
913         else if ((form_type == pbm_sig) || (form_type == ilbm_sig))
914                 ret = iff_parse_ilbm_pbm(ifile,form_type,&bmheader,form_len,prev_bm);
915         else
916                 ret = IFF_UNKNOWN_FORM;
917
918         if (ret != IFF_NO_ERROR) {              //got an error parsing
919                 if (bmheader.raw_data) d_free(bmheader.raw_data);
920                 return ret;
921         }
922
923         //If IFF file is ILBM, convert to PPB
924         if (bmheader.type == TYPE_ILBM) {
925
926                 ret = convert_ilbm_to_pbm(&bmheader);
927
928                 if (ret != IFF_NO_ERROR)
929                         return ret;
930         }
931
932         //Copy data from iff_bitmap_header structure into grs_bitmap structure
933
934         copy_iff_to_grs(bm,&bmheader);
935
936 #ifndef MACINTOSH
937         if (palette) memcpy(palette,&bmheader.palette,sizeof(bmheader.palette));
938 #else
939 //      if (palette) memcpy(palette,&bmheader.palette, 768);                    // pal_entry is 4 bytes on mac
940         if (palette) {
941                 ubyte *c;
942                 int i;
943                 
944                 c = palette;
945                 for (i = 0; i < 256; i++) {
946                         *c++ = bmheader.palette[i].r;
947                         *c++ = bmheader.palette[i].g;
948                         *c++ = bmheader.palette[i].b;
949                 }
950         }
951 #endif
952
953         //Now do post-process if required
954
955         if (bitmap_type == BM_RGB15) {
956                 ret = convert_rgb15(bm,&bmheader);
957                 if (ret != IFF_NO_ERROR)
958                         return ret;
959         }
960
961         return ret;
962
963 }
964
965 //returns error codes - see IFF.H.  see GR.H for bitmap_type
966 int iff_read_bitmap(char *ifilename,grs_bitmap *bm,int bitmap_type,ubyte *palette)
967 {
968         int ret;                        //return code
969         FFILE ifile;
970
971         ret = open_fake_file(ifilename,&ifile);         //read in entire file
972         if (ret == IFF_NO_ERROR) {
973                 bm->bm_data = NULL;
974                 ret = iff_parse_bitmap(&ifile,bm,bitmap_type,palette,NULL);
975         }
976
977         if (ifile.data) d_free(ifile.data);
978
979         close_fake_file(&ifile);
980
981         return ret;
982
983
984 }
985
986 //like iff_read_bitmap(), but reads into a bitmap that already exists,
987 //without allocating memory for the bitmap.
988 int iff_read_into_bitmap(char *ifilename, grs_bitmap *bm, sbyte *palette)
989 {
990         int ret;                        //return code
991         FFILE ifile;
992
993         ret = open_fake_file(ifilename,&ifile);         //read in entire file
994         if (ret == IFF_NO_ERROR) {
995                 ret = iff_parse_bitmap(&ifile,bm,bm->bm_type,palette,NULL);
996         }
997
998         if (ifile.data) d_free(ifile.data);
999
1000         close_fake_file(&ifile);
1001
1002         return ret;
1003
1004
1005 }
1006
1007 #define BMHD_SIZE 20
1008
1009 int write_bmhd(FILE *ofile,iff_bitmap_header *bitmap_header)
1010 {
1011         put_sig(bmhd_sig,ofile);
1012         put_long((long) BMHD_SIZE,ofile);
1013
1014         put_word(bitmap_header->w,ofile);
1015         put_word(bitmap_header->h,ofile);
1016         put_word(bitmap_header->x,ofile);
1017         put_word(bitmap_header->y,ofile);
1018
1019         put_byte(bitmap_header->nplanes,ofile);
1020         put_byte(bitmap_header->masking,ofile);
1021         put_byte(bitmap_header->compression,ofile);
1022         put_byte(0,ofile);      /* pad */
1023
1024         put_word(bitmap_header->transparentcolor,ofile);
1025         put_byte(bitmap_header->xaspect,ofile);
1026         put_byte(bitmap_header->yaspect,ofile);
1027
1028         put_word(bitmap_header->pagewidth,ofile);
1029         put_word(bitmap_header->pageheight,ofile);
1030
1031         return IFF_NO_ERROR;
1032
1033 }
1034
1035 int write_pal(FILE *ofile,iff_bitmap_header *bitmap_header)
1036 {
1037         int     i;
1038
1039         int n_colors = 1<<bitmap_header->nplanes;
1040
1041         put_sig(cmap_sig,ofile);
1042 //      put_long(sizeof(pal_entry) * n_colors,ofile);
1043         put_long(3 * n_colors,ofile);
1044
1045 //printf("new write pal %d %d\n",3,n_colors);
1046
1047         for (i=0; i<256; i++) {
1048                 unsigned char r,g,b;
1049                 r = bitmap_header->palette[i].r * 4 + (bitmap_header->palette[i].r?3:0);
1050                 g = bitmap_header->palette[i].g * 4 + (bitmap_header->palette[i].g?3:0);
1051                 b = bitmap_header->palette[i].b * 4 + (bitmap_header->palette[i].b?3:0);
1052                 fputc(r,ofile);
1053                 fputc(g,ofile);
1054                 fputc(b,ofile);
1055         }
1056
1057 //printf("write pal %d %d\n",sizeof(pal_entry),n_colors);
1058 //      fwrite(bitmap_header->palette,sizeof(pal_entry),n_colors,ofile);
1059
1060         return IFF_NO_ERROR;
1061 }
1062
1063 int rle_span(ubyte *dest,ubyte *src,int len)
1064 {
1065         int n,lit_cnt,rep_cnt;
1066         ubyte last,*cnt_ptr,*dptr;
1067
1068         cnt_ptr=0;
1069
1070         dptr = dest;
1071
1072         last=src[0]; lit_cnt=1;
1073
1074         for (n=1;n<len;n++) {
1075
1076                 if (src[n] == last) {
1077
1078                         rep_cnt = 2;
1079
1080                         n++;
1081                         while (n<len && rep_cnt<128 && src[n]==last) {n++; rep_cnt++;}
1082
1083                         if (rep_cnt > 2 || lit_cnt < 2) {
1084
1085                                 if (lit_cnt > 1) {*cnt_ptr = lit_cnt-2; --dptr;}                //save old lit count
1086                                 *dptr++ = -(rep_cnt-1);
1087                                 *dptr++ = last;
1088                                 last = src[n];
1089                                 lit_cnt = (n<len)?1:0;
1090
1091                                 continue;               //go to next char
1092                         } else n--;
1093
1094                 }
1095
1096                 {
1097
1098                         if (lit_cnt==1) {
1099                                 cnt_ptr = dptr++;               //save place for count
1100                                 *dptr++=last;                   //store first char
1101                         }
1102
1103                         *dptr++ = last = src[n];
1104
1105                         if (lit_cnt == 127) {
1106                                 *cnt_ptr = lit_cnt;
1107                                 //cnt_ptr = dptr++;
1108                                 lit_cnt = 1;
1109                                 last = src[++n];
1110                         }
1111                         else lit_cnt++;
1112                 }
1113
1114
1115         }
1116
1117         if (lit_cnt==1) {
1118                 *dptr++ = 0;
1119                 *dptr++=last;                   //store first char
1120         }
1121         else if (lit_cnt > 1)
1122                 *cnt_ptr = lit_cnt-1;
1123
1124         return dptr-dest;
1125 }
1126
1127 #define EVEN(a) ((a+1)&0xfffffffel)
1128
1129 //returns length of chunk
1130 int write_body(FILE *ofile,iff_bitmap_header *bitmap_header,int compression_on)
1131 {
1132         int w=bitmap_header->w,h=bitmap_header->h;
1133         int y,odd=w&1;
1134         long len = EVEN(w) * h,newlen,total_len=0;
1135         ubyte *p=bitmap_header->raw_data,*new_span;
1136         long save_pos;
1137
1138         put_sig(body_sig,ofile);
1139         save_pos = ftell(ofile);
1140         put_long(len,ofile);
1141
1142     //if (! (new_span = d_malloc(bitmap_header->w+(bitmap_header->w/128+2)*2))) return IFF_NO_MEM;
1143         MALLOC( new_span, ubyte, bitmap_header->w + (bitmap_header->w/128+2)*2);
1144         if (new_span == NULL) return IFF_NO_MEM;
1145
1146         for (y=bitmap_header->h;y--;) {
1147
1148                 if (compression_on) {
1149                         total_len += newlen = rle_span(new_span,p,bitmap_header->w+odd);
1150                         fwrite(new_span,newlen,1,ofile);
1151                 }
1152                 else
1153                         fwrite(p,bitmap_header->w+odd,1,ofile);
1154
1155                 p+=bitmap_header->row_size;     //bitmap_header->w;
1156         }
1157
1158         if (compression_on) {           //write actual data length
1159                 Assert(fseek(ofile,save_pos,SEEK_SET)==0);
1160                 put_long(total_len,ofile);
1161                 Assert(fseek(ofile,total_len,SEEK_CUR)==0);
1162                 if (total_len&1) fputc(0,ofile);                //pad to even
1163         }
1164
1165         d_free(new_span);
1166
1167         return ((compression_on) ? (EVEN(total_len)+8) : (len+8));
1168
1169 }
1170
1171 #if WRITE_TINY
1172 //write a small representation of a bitmap. returns size
1173 int write_tiny(CFILE *ofile,iff_bitmap_header *bitmap_header,int compression_on)
1174 {
1175         int skip;
1176         int new_w,new_h;
1177         int len,total_len=0,newlen;
1178         int x,y,xofs,odd;
1179         ubyte *p = bitmap_header->raw_data;
1180         ubyte tspan[80],new_span[80*2];
1181         long save_pos;
1182
1183         skip = max((bitmap_header->w+79)/80,(bitmap_header->h+63)/64);
1184
1185         new_w = bitmap_header->w / skip;
1186         new_h = bitmap_header->h / skip;
1187
1188         odd = new_w & 1;
1189
1190         len = new_w * new_h + 4;
1191
1192         put_sig(tiny_sig,ofile);
1193         save_pos = cftell(ofile);
1194         put_long(EVEN(len),ofile);
1195
1196         put_word(new_w,ofile);
1197         put_word(new_h,ofile);
1198
1199         for (y=0;y<new_h;y++) {
1200                 for (x=xofs=0;x<new_w;x++,xofs+=skip)
1201                         tspan[x] = p[xofs];
1202
1203                 if (compression_on) {
1204                         total_len += newlen = rle_span(new_span,tspan,new_w+odd);
1205                         fwrite(new_span,newlen,1,ofile);
1206                 }
1207                 else
1208                         fwrite(p,new_w+odd,1,ofile);
1209
1210                 p += skip * bitmap_header->row_size;            //bitmap_header->w;
1211
1212         }
1213
1214         if (compression_on) {
1215                 Assert(cfseek(ofile,save_pos,SEEK_SET)==0);
1216                 put_long(4+total_len,ofile);
1217                 Assert(cfseek(ofile,4+total_len,SEEK_CUR)==0);
1218                 if (total_len&1) cfputc(0,ofile);               //pad to even
1219         }
1220
1221         return ((compression_on) ? (EVEN(total_len)+8+4) : (len+8));
1222 }
1223 #endif
1224
1225 int write_pbm(FILE *ofile,iff_bitmap_header *bitmap_header,int compression_on)                  /* writes a pbm iff file */
1226 {
1227         int ret;
1228         long raw_size = EVEN(bitmap_header->w) * bitmap_header->h;
1229         long body_size,tiny_size,pbm_size = 4 + BMHD_SIZE + 8 + EVEN(raw_size) + sizeof(pal_entry)*(1<<bitmap_header->nplanes)+8;
1230         long save_pos;
1231
1232 //printf("write_pbm\n");
1233
1234         put_sig(form_sig,ofile);
1235         save_pos = ftell(ofile);
1236         put_long(pbm_size+8,ofile);
1237         put_sig(pbm_sig,ofile);
1238
1239         ret = write_bmhd(ofile,bitmap_header);
1240         if (ret != IFF_NO_ERROR) return ret;
1241
1242         ret = write_pal(ofile,bitmap_header);
1243         if (ret != IFF_NO_ERROR) return ret;
1244
1245 #if WRITE_TINY
1246         tiny_size = write_tiny(ofile,bitmap_header,compression_on);
1247 #else
1248         tiny_size = 0;
1249 #endif
1250
1251         body_size = write_body(ofile,bitmap_header,compression_on);
1252
1253         pbm_size = 4 + BMHD_SIZE + body_size + tiny_size + sizeof(pal_entry)*(1<<bitmap_header->nplanes)+8;
1254
1255         Assert(fseek(ofile,save_pos,SEEK_SET)==0);
1256         put_long(pbm_size+8,ofile);
1257         Assert(fseek(ofile,pbm_size+8,SEEK_CUR)==0);
1258
1259         return ret;
1260
1261 }
1262
1263 //writes an IFF file from a grs_bitmap structure. writes palette if not null
1264 //returns error codes - see IFF.H.
1265 int iff_write_bitmap(char *ofilename,grs_bitmap *bm,ubyte *palette)
1266 {
1267         FILE *ofile;
1268         iff_bitmap_header bmheader;
1269         int ret;
1270         int compression_on;
1271
1272         if (bm->bm_type == BM_RGB15) return IFF_BAD_BM_TYPE;
1273
1274 #if COMPRESS
1275         compression_on = (bm->bm_w>=MIN_COMPRESS_WIDTH);
1276 #else
1277         compression_on = 0;
1278 #endif
1279
1280         //fill in values in bmheader
1281
1282         bmheader.x = bmheader.y = 0;
1283         bmheader.w = bm->bm_w;
1284         bmheader.h = bm->bm_h;
1285         bmheader.type = TYPE_PBM;
1286         bmheader.transparentcolor = iff_transparent_color;
1287         bmheader.pagewidth = bm->bm_w;  //I don't think it matters what I write
1288         bmheader.pageheight = bm->bm_h;
1289         bmheader.nplanes = 8;
1290         bmheader.masking = mskNone;
1291         if (iff_has_transparency)       {
1292                  bmheader.masking |= mskHasTransparentColor;
1293         }
1294         bmheader.compression = (compression_on?cmpByteRun1:cmpNone);
1295
1296         bmheader.xaspect = bmheader.yaspect = 1;        //I don't think it matters what I write
1297         bmheader.raw_data = bm->bm_data;
1298         bmheader.row_size = bm->bm_rowsize;
1299
1300         if (palette) memcpy(&bmheader.palette,palette,256*3);
1301
1302         //open file and write
1303
1304         if ((ofile = fopen(ofilename,"wb")) == NULL) {
1305                 ret=IFF_NO_FILE;
1306         } else {
1307                 ret = write_pbm(ofile,&bmheader,compression_on);
1308         }
1309
1310         fclose(ofile);
1311
1312         return ret;
1313 }
1314
1315 //read in many brushes.  fills in array of pointers, and n_bitmaps.
1316 //returns iff error codes
1317 int iff_read_animbrush(char *ifilename,grs_bitmap **bm_list,int max_bitmaps,int *n_bitmaps,ubyte *palette)
1318 {
1319         int ret;                        //return code
1320         FFILE ifile;
1321         iff_bitmap_header bmheader;
1322         long sig,form_len;
1323         long form_type;
1324
1325         *n_bitmaps=0;
1326
1327         ret = open_fake_file(ifilename,&ifile);         //read in entire file
1328         if (ret != IFF_NO_ERROR) goto done;
1329
1330         bmheader.raw_data = NULL;
1331
1332         sig=get_sig(&ifile);
1333         form_len = get_long(&ifile);
1334
1335         if (sig != form_sig) {
1336                 ret = IFF_NOT_IFF;
1337                 goto done;
1338         }
1339
1340         form_type = get_sig(&ifile);
1341
1342         if ((form_type == pbm_sig) || (form_type == ilbm_sig))
1343                 ret = IFF_FORM_BITMAP;
1344         else if (form_type == anim_sig) {
1345                 int anim_end = ifile.position + form_len - 4;
1346
1347                 while (ifile.position < anim_end && *n_bitmaps < max_bitmaps) {
1348
1349                         grs_bitmap *prev_bm;
1350
1351                         prev_bm = *n_bitmaps>0?bm_list[*n_bitmaps-1]:NULL;
1352
1353                         MALLOC(bm_list[*n_bitmaps] , grs_bitmap, 1 );
1354                         bm_list[*n_bitmaps]->bm_data = NULL;
1355
1356                         ret = iff_parse_bitmap(&ifile,bm_list[*n_bitmaps],form_type,*n_bitmaps>0?NULL:palette,prev_bm);
1357
1358                         if (ret != IFF_NO_ERROR)
1359                                 goto done;
1360
1361                         (*n_bitmaps)++;
1362                 }
1363
1364                 if (ifile.position < anim_end)  //ran out of room
1365                         ret = IFF_TOO_MANY_BMS;
1366
1367         }
1368         else
1369                 ret = IFF_UNKNOWN_FORM;
1370
1371 done:
1372
1373         close_fake_file(&ifile);
1374
1375         return ret;
1376
1377 }
1378
1379 //text for error messges
1380 char error_messages[] = {
1381         "No error.\0"
1382         "Not enough mem for loading or processing bitmap.\0"
1383         "IFF file has unknown FORM type.\0"
1384         "Not an IFF file.\0"
1385         "Cannot open file.\0"
1386         "Tried to save invalid type, like BM_RGB15.\0"
1387         "Bad data in file.\0"
1388         "ANIM file cannot be loaded with normal bitmap loader.\0"
1389         "Normal bitmap file cannot be loaded with anim loader.\0"
1390         "Array not big enough on anim brush read.\0"
1391         "Unknown mask type in bitmap header.\0"
1392         "Error reading file.\0"
1393 };
1394
1395
1396 //function to return pointer to error message
1397 char *iff_errormsg(int error_number)
1398 {
1399         char *p = error_messages;
1400
1401         while (error_number--) {
1402
1403                 if (!p) return NULL;
1404
1405                 p += strlen(p)+1;
1406
1407         }
1408
1409         return p;
1410
1411 }
1412
1413