1 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
2 /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */
3 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
4 /* Copyright (C) 2005 by Duane H. Hesser. All rights reserved. */
5 /* */
6 /* See the file LICENSE.EXIFPROBE for terms of use. */
7 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
8
9 #ifndef lint
10 static char *ModuleId = "@(#) $Id: x3f.c,v 1.7 2005/07/24 20:31:30 alex Exp $";
11 #endif
12
13 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14 /* Sigma/FOVEON x3f routines */
15 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
16 /* See http://www.sd9.org.uk/X3F_Format.pdf */
17 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <time.h>
23
24 #include "defs.h"
25 #include "datadefs.h"
26 #include "summary.h"
27 #include "maker.h"
28 #include "misc.h"
29 #include "tags.h"
30 #include "extern.h"
31 #include "x3f.h"
32 #include "maker_extern.h"
33
34 /* Read and record the X3F file header */
35
36 struct x3f_header *
read_x3fheader(FILE * inptr,unsigned long offset)37 read_x3fheader(FILE *inptr,unsigned long offset)
38 {
39 static struct x3f_header header;
40 struct x3f_header *headerptr = NULL;
41 unsigned long xmagic;
42 unsigned char *bytearray;
43
44 memset(&header,0,sizeof(struct x3f_header));
45 if(inptr)
46 {
47 xmagic = read_ulong(inptr,TIFF_INTEL,offset);
48 if(xmagic == PROBE_X3FMAGIC)
49 {
50 header.magic = xmagic;
51 header.version_major = read_ushort(inptr,TIFF_INTEL,HERE);
52 header.version_minor = read_ushort(inptr,TIFF_INTEL,HERE);
53 bytearray = read_bytes(inptr,16,HERE);
54 if(bytearray)
55 memcpy(header.unique_id,bytearray,16);
56 header.mark_bits = read_ulong(inptr,TIFF_INTEL,HERE);
57 header.image_width = read_ulong(inptr,TIFF_INTEL,HERE);
58 header.image_height = read_ulong(inptr,TIFF_INTEL,HERE);
59 header.image_rotation = read_ulong(inptr,TIFF_INTEL,HERE);
60 if(header.version_minor >= 1)
61 {
62 /* this is a string, e.g. "AUTO\0" */
63 bytearray = read_bytes(inptr,32,HERE);
64 if(bytearray)
65 memcpy(header.white_balance,bytearray,32);
66 bytearray = read_bytes(inptr,32,HERE);
67 if(bytearray)
68 memcpy(header.extended_data_types,bytearray,32);
69 bytearray = read_bytes(inptr,128,HERE);
70 if(bytearray)
71 memcpy(header.extended_data_values,bytearray,128);
72 }
73 headerptr = &header;
74 }
75 }
76 return(headerptr);
77 }
78
79
80 /* Print X3f header information if options permit. Return 0 if */
81 /* information is valid to print, or -1 if the header is invalid */
82
83 int
print_x3f_header(FILE * inptr,struct fileheader * header,unsigned long section_id)84 print_x3f_header(FILE *inptr,struct fileheader *header,unsigned long section_id)
85 {
86 struct x3f_header *x3fheader = NULL;
87 int status = -1;
88 int chpr = 0;
89 int i;
90
91 if(header)
92 {
93 if(header->x3f_header)
94 {
95 x3fheader = header->x3f_header;
96 if(header->probe_magic == PROBE_X3FMAGIC)
97 {
98 if(Print_options & section_id)
99 {
100 chpr += printf("%4.4s (%#06lx) version %2u.%-2u, id ",
101 (char *)&(x3fheader->magic),
102 x3fheader->magic,
103 x3fheader->version_major,
104 x3fheader->version_minor);
105 chpr += printf("%#02x ",x3fheader->unique_id[0] & 0xff);
106 for(i = 0; i < 16; ++i)
107 chpr += printf("%02x ",x3fheader->unique_id[i] & 0xff);
108 chpr = newline(chpr);
109 if(x3fheader->version_minor >= 1)
110 {
111 print_tag_address(ENTRY,24,MEDIUMINDENT,"@");
112 if((PRINT_TAGINFO))
113 {
114 if((PRINT_LONGNAMES))
115 chpr += printf("X3f.Header.");
116 chpr += printf("MarkBits");
117 if((PRINT_VALUE))
118 {
119 putindent(X3FTAGWIDTH - 8);
120 chpr += printf(" = ");
121 }
122 }
123 if((PRINT_VALUE))
124 chpr += printf("%#06lx",x3fheader->mark_bits);
125 chpr = newline(chpr);
126 }
127 print_tag_address(ENTRY,28,MEDIUMINDENT,"@");
128 if((PRINT_TAGINFO))
129 {
130 if((PRINT_LONGNAMES))
131 chpr += printf("X3f.Header.");
132 chpr += printf("ImageWidth");
133 if((PRINT_VALUE))
134 {
135 putindent(X3FTAGWIDTH - 10);
136 chpr += printf(" = ");
137 }
138 }
139 if((PRINT_VALUE))
140 chpr += printf("%lu",x3fheader->image_width);
141 chpr = newline(chpr);
142 print_tag_address(ENTRY,32,MEDIUMINDENT,"@");
143 if((PRINT_TAGINFO))
144 {
145 if((PRINT_LONGNAMES))
146 chpr += printf("X3f.Header.");
147 chpr += printf("ImageHeight");
148 if((PRINT_VALUE))
149 {
150 putindent(X3FTAGWIDTH - 11);
151 chpr += printf(" = ");
152 }
153 }
154 if((PRINT_VALUE))
155 chpr += printf("%lu",x3fheader->image_height);
156 chpr = newline(chpr);
157 print_tag_address(ENTRY,36,MEDIUMINDENT,"@");
158 if((PRINT_TAGINFO))
159 {
160 if((PRINT_LONGNAMES))
161 chpr += printf("X3f.Header.");
162 chpr += printf("ImageRotation");
163 if((PRINT_VALUE))
164 {
165 putindent(X3FTAGWIDTH - 13);
166 chpr += printf(" = ");
167 }
168 }
169 if((PRINT_VALUE))
170 chpr += printf("%lu",x3fheader->image_rotation);
171 chpr = newline(chpr);
172 if(x3fheader->version_minor >= 1)
173 {
174 print_tag_address(ENTRY,40,MEDIUMINDENT,"@");
175 if((PRINT_TAGINFO))
176 {
177 if((PRINT_LONGNAMES))
178 chpr += printf("X3f.Header.");
179 chpr += printf("WhiteBalance");
180 if((PRINT_VALUE))
181 {
182 putindent(X3FTAGWIDTH - 12);
183 chpr += printf(" = ");
184 }
185 }
186 if((PRINT_VALUE))
187 show_string(x3fheader->white_balance,32,0);
188 chpr = newline(chpr);
189 print_tag_address(ENTRY,72,MEDIUMINDENT,"@");
190 if((PRINT_TAGINFO))
191 {
192 if((PRINT_LONGNAMES))
193 chpr += printf("X3f.Header.");
194 chpr += printf("ExtendedDataTypes");
195 if((PRINT_VALUE))
196 {
197 putindent(X3FTAGWIDTH - 17);
198 chpr += printf(" = ");
199 }
200 }
201 if((PRINT_VALUE))
202 print_ubytes(inptr,32,72);
203 chpr = newline(chpr);
204 print_tag_address(ENTRY,104,MEDIUMINDENT,"@");
205 if((PRINT_TAGINFO))
206 {
207 if((PRINT_LONGNAMES))
208 chpr += printf("X3f.Header.");
209 chpr += printf("ExtendedDataValues");
210 if((PRINT_VALUE))
211 {
212 putindent(X3FTAGWIDTH - 19);
213 chpr += printf(" = ");
214 }
215 }
216 if((PRINT_VALUE))
217 print_ulong(inptr,32,TIFF_INTEL,104);
218 chpr = newline(chpr);
219 }
220 print_tag_address(SECTION,104 + 128 - 1,0,"@");
221 chpr += printf("</END OF HEADER>");
222 chpr = newline(chpr);
223 }
224 status = 0;
225 }
226 else if(Print_options & section_id)
227 {
228 chpr += printf("INVALID X3F IDENTIFIER ");
229 print_magic(header->probe_magic,4);
230 }
231 }
232 else
233 fprintf(stderr,"%s: null x3fheader to print_x3f_header()\n",Progname);
234 }
235 else
236 fprintf(stderr,"%s: null fileheader to print_x3f_header()\n",Progname);
237 chpr = newline(chpr);
238 return(status);
239 }
240
241 /* Process the remainder of an X3F file, after the header has been */
242 /* read and validated. Returns the maximum offset reached in */
243 /* processing, which is normally end of file. */
244
245 unsigned long
process_x3f(FILE * inptr,struct fileheader * header,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,int level,int indent)246 process_x3f(FILE *inptr,struct fileheader *header,unsigned long fileoffset_base,
247 struct image_summary *summary_entry,
248 char *parent_name,int level,int indent)
249 {
250 struct x3f_header *x3fheader;
251 unsigned long max_offset = 0UL;
252 unsigned short byteorder = 0;
253 unsigned long directory_pointer = 0UL;
254
255 if(inptr)
256 {
257 if(header)
258 {
259 if(header->x3f_header)
260 {
261 x3fheader = header->x3f_header;
262 /* X3F is always little-endian; nonetheless, pass it */
263 /* as an argument to lower-level functions. Just set */
264 /* it here. */
265 byteorder = TIFF_INTEL;
266 if(fseek(inptr,-4L,2) == 0)
267 directory_pointer = ftell(inptr);
268 if(ferror(inptr) == 0)
269 {
270 max_offset = process_x3f_dir(inptr,byteorder,x3fheader,
271 directory_pointer,summary_entry,
272 parent_name,level,indent);
273 if(max_offset > 0L)
274 max_offset += 4;
275 }
276 else
277 fprintf(stderr,"%s: cannot read directory offset\n",Progname);
278 }
279 else
280 fprintf(stderr,"%s: null x3fheader to process_x3f()\n",Progname);
281 }
282 else
283 fprintf(stderr,"%s: null fileheader to process_x3f()\n",Progname);
284 }
285 else
286 fprintf(stderr,"%s: no open file pointer to read Print Image data\n",
287 Progname);
288
289 return(max_offset);
290 }
291
292 /* Find the directory at the end of the file and process it. Report */
293 /* the detail data first, then show the directory itself. */
294
295 unsigned long
process_x3f_dir(FILE * inptr,unsigned short byteorder,struct x3f_header * x3fheader,unsigned long directory_pointer,struct image_summary * summary_entry,char * parent_name,int level,int indent)296 process_x3f_dir(FILE *inptr,unsigned short byteorder,struct x3f_header *x3fheader,
297 unsigned long directory_pointer,
298 struct image_summary *summary_entry,
299 char *parent_name,int level,int indent)
300 {
301 struct x3f_direntry *entry;
302 unsigned long directory_offset = 0UL;
303 unsigned long section_id;
304 unsigned long max_dir_offset = 0L;
305 unsigned long entry_offset,next_entry_offset;
306 unsigned long num_entries;
307 unsigned short version_major;
308 unsigned short version_minor;
309 int i;
310 int chpr = 0;
311
312 directory_offset = read_ulong(inptr,byteorder,directory_pointer);
313
314 section_id = read_ulong(inptr,byteorder,directory_offset);
315 version_minor = read_ushort(inptr,byteorder,HERE);
316 version_major = read_ushort(inptr,byteorder,HERE);
317 num_entries = read_ulong(inptr,byteorder,HERE);
318 entry = NULL;
319
320 entry_offset = ftell(inptr);
321
322 /* Print the entries first, in order */
323 for(i = 0; i < num_entries; ++i)
324 {
325 entry = read_x3f_direntry(inptr,byteorder,entry,entry_offset);
326 if(ferror(inptr))
327 {
328 fprintf(stderr,"%s: error reading directory entry at %lu\n",
329 Progname,entry_offset);
330 break;
331 }
332 if(entry == NULL)
333 {
334 fprintf(stderr,"%s: null entry %d\n",Progname,i);
335 break;
336 }
337 next_entry_offset = ftell(inptr);
338 process_x3f_direntry(inptr,byteorder,entry,entry_offset,
339 summary_entry,parent_name,i,indent);
340 entry_offset = next_entry_offset;
341 }
342 chpr = newline(chpr);
343
344 /* Now show the directory itself */
345
346 if((PRINT_SECTION))
347 {
348 print_tag_address(SECTION,directory_offset,indent,"@");
349 chpr += printf("<DIRECTORY> version %d.%d id \"%4.4s\", %lu entries",
350 version_major,version_minor,
351 (char *)§ion_id,num_entries);
352 }
353 chpr = newline(chpr);
354 entry_offset = directory_offset + 12;
355 for(i = 0; i < num_entries; ++i)
356 {
357 entry = read_x3f_direntry(inptr,byteorder,entry,entry_offset);
358 if(ferror(inptr))
359 {
360 fprintf(stderr,"%s: error reading directory entry at %lu\n",
361 Progname,entry_offset);
362 break;
363 }
364 if(entry == NULL)
365 {
366 fprintf(stderr,"%s: null entry %d\n",Progname,i);
367 break;
368 }
369 next_entry_offset = ftell(inptr);
370 print_x3f_direntry(inptr,entry,entry_offset,
371 parent_name,i,indent);
372 entry_offset = next_entry_offset;
373 }
374 max_dir_offset = ftell(inptr);
375 if((PRINT_SECTION))
376 {
377 print_tag_address(SECTION,max_dir_offset - 1,indent,"@");
378 chpr += printf("</DIRECTORY>");
379 chpr = newline(chpr);
380 }
381
382 print_tag_address(ENTRY,directory_pointer,indent,"@");
383 if((PRINT_TAGINFO))
384 {
385 if((PRINT_LONGNAMES))
386 chpr += printf("%s.",parent_name);
387 chpr += printf("%s","DirectoryOffset");
388 if((PRINT_VALUE))
389 {
390 putindent(X3FTAGWIDTH - 15);
391 chpr += printf(" = ");
392 }
393 }
394 if((PRINT_VALUE))
395 {
396 if(PRINT_BOTH_OFFSET)
397 chpr += printf("@%#lx=%lu",directory_offset,directory_offset);
398 else if(PRINT_HEX_OFFSET)
399 chpr += printf("@%#lx",directory_offset);
400 else
401 chpr += printf("@%lu",directory_offset);
402 }
403 chpr = newline(chpr);
404
405 if(entry)
406 free(entry);
407 return(max_dir_offset);
408 }
409
410 /* Process a directory entry, representing one section of the file. */
411 /* An entry number is added to the section id, so that sections with */
412 /* the same name (e.g. IMGA) can be identified, especially in LIST */
413 /* mode. */
414
415 void
process_x3f_direntry(FILE * inptr,unsigned short byteorder,struct x3f_direntry * entry,unsigned long offset,struct image_summary * summary_entry,char * parent_name,int entry_num,int indent)416 process_x3f_direntry(FILE *inptr,unsigned short byteorder,struct x3f_direntry *entry,
417 unsigned long offset,struct image_summary *summary_entry,
418 char *parent_name,int entry_num,int indent)
419 {
420 struct x3f_imag_header *imag_header;
421 struct x3f_prop_header *prop_header;
422 struct x3f_camf_header *camf_header;
423 unsigned long data_offset = 0UL;
424 unsigned long data_length = 0UL;
425 char *dirname = CNULL;
426 int chpr = 0;
427
428 if(entry)
429 {
430 if((PRINT_SECTION))
431 {
432 print_tag_address(SECTION,entry->data_offset,indent,"@");
433 chpr += printf("<%4.4s:%d> (%#06lx)",(char *)&entry->data_type,entry_num,entry->data_type);
434 chpr += printf(" length %lu",entry->data_length);
435 chpr = newline(chpr);
436 }
437 switch(entry->data_type)
438 {
439 case X3F_IMAG:
440 dirname = splice(parent_name,".","IMAG");
441 imag_header = read_x3f_imag_header(inptr,byteorder,entry->data_offset);
442 data_offset = display_x3f_imag_header(entry,imag_header,dirname,entry_num,
443 indent + MEDIUMINDENT);
444 data_length = entry->data_length - (data_offset - entry->data_offset);
445 if((summary_entry == NULL) || summary_entry->entry_lock)
446 summary_entry = new_summary_entry(summary_entry,FILEFMT_X3F,IMGFMT_X3F);
447 if(summary_entry)
448 {
449 switch(imag_header->image_type)
450 {
451 case 2:
452 summary_entry->subfiletype = REDUCED_RES_TYPE;
453 break;
454 case 3:
455 /* observed; spec doesn't say */
456 summary_entry->subfiletype = PRIMARY_TYPE;
457 break;
458 default:
459 /* assume this; spec doesn't say */
460 summary_entry->subfiletype = REDUCED_RES_TYPE;
461 break;
462 }
463 switch(imag_header->image_format)
464 {
465 case 3:
466 summary_entry->imagesubformat = IMGSUBFMT_RGB;
467 break;
468 case 11:
469 summary_entry->imagesubformat = IMGSUBFMT_HUFF_COMPRESSED_RGB;
470 break;
471 case 18:
472 summary_entry->imagesubformat = IMGSUBFMT_JPEG_COMPRESSED_RGB;
473 break;
474 case 6:
475 summary_entry->imagesubformat = IMGSUBFMT_X3F_COMPRESSED;
476 break;
477 default:
478 summary_entry->imagesubformat = IMGSUBFMT_X3F_UNSPECIFIED;
479 break;
480 }
481 summary_entry->imageformat = IMGFMT_X3F;
482 summary_entry->pixel_width = imag_header->image_width;
483 summary_entry->pixel_height = imag_header->image_height;
484 summary_entry->offset = data_offset;
485 summary_entry->length = data_length;
486 summary_entry->entry_lock = lock_number(summary_entry);
487
488 }
489 if((PRINT_SECTION))
490 {
491 print_tag_address(SECTION,data_offset,indent + MEDIUMINDENT,"@");
492 chpr += printf("<IMAG.Data> length %lu",data_length);
493 chpr = newline(chpr);
494 dumpsection(inptr,data_offset,data_length,indent + LARGEINDENT);
495 print_tag_address(SECTION,entry->data_offset + entry->data_length - 1,
496 indent + MEDIUMINDENT,"@");
497 chpr += printf("</IMAG.Data>");
498 }
499 else if((LIST_MODE))
500 {
501 print_tag_address(ENTRY,data_offset,indent + MEDIUMINDENT,"@");
502 if((PRINT_TAGINFO))
503 {
504 if((PRINT_LONGNAMES))
505 chpr += printf("%s:%d.",dirname,entry_num);
506 else
507 chpr += printf("IMAG:%d.",entry_num);
508 chpr += printf("Data");
509 if((PRINT_VALUE))
510 {
511 putindent(X3FTAGWIDTH - 7);
512 chpr += printf(" = ");
513 }
514 }
515 if((PRINT_VALUE))
516 chpr += printf("@%lu:%lu",data_offset,data_length);
517 }
518 chpr = newline(chpr);
519 break;
520 case X3F_IMA2:
521 dirname = splice(parent_name,".","IMA2");
522 imag_header = read_x3f_imag_header(inptr,byteorder,entry->data_offset);
523 data_offset = display_x3f_imag_header(entry,imag_header,dirname,entry_num,
524 indent + MEDIUMINDENT);
525 data_length = entry->data_length - (data_offset - entry->data_offset);
526 if((summary_entry == NULL) || summary_entry->entry_lock)
527 summary_entry = new_summary_entry(summary_entry,FILEFMT_X3F,IMGFMT_X3F);
528 if(summary_entry)
529 {
530 switch(imag_header->image_type)
531 {
532 case 2:
533 summary_entry->subfiletype = REDUCED_RES_TYPE;
534 break;
535 case 3:
536 /* observed; spec doesn't say */
537 summary_entry->subfiletype = PRIMARY_TYPE;
538 break;
539 default:
540 /* assume this; spec doesn't say */
541 summary_entry->subfiletype = REDUCED_RES_TYPE;
542 break;
543 }
544 switch(imag_header->image_format)
545 {
546 case 3:
547 summary_entry->imagesubformat = IMGSUBFMT_RGB;
548 break;
549 case 11:
550 summary_entry->imagesubformat = IMGSUBFMT_HUFF_COMPRESSED_RGB;
551 break;
552 case 18:
553 summary_entry->imagesubformat = IMGSUBFMT_JPEG_COMPRESSED_RGB;
554 break;
555 case 6:
556 /* No idea how "raw" this is, or how it's */
557 /* compressed/encoded */
558 summary_entry->imagesubformat = IMGSUBFMT_X3F_COMPRESSED;
559 break;
560 default:
561 summary_entry->imagesubformat = IMGSUBFMT_X3F_UNSPECIFIED;
562 break;
563 }
564 summary_entry->imageformat = IMGFMT_X3F;
565 summary_entry->pixel_width = imag_header->image_width;
566 summary_entry->pixel_height = imag_header->image_height;
567 summary_entry->offset = data_offset;
568 summary_entry->length = data_length;
569 summary_entry->entry_lock = lock_number(summary_entry);
570
571 }
572 if((PRINT_SECTION))
573 {
574 print_tag_address(SECTION,data_offset,indent + MEDIUMINDENT,"@");
575 chpr += printf("<IMA2.Data> length %lu",data_length);
576 chpr = newline(chpr);
577 dumpsection(inptr,data_offset,data_length,indent + LARGEINDENT);
578 print_tag_address(SECTION,entry->data_offset + entry->data_length - 1,
579 indent + MEDIUMINDENT,"@");
580 chpr += printf("</IMA2.Data>");
581 }
582 else if((LIST_MODE))
583 {
584 print_tag_address(ENTRY,data_offset,indent + MEDIUMINDENT,"@");
585 if((PRINT_TAGINFO))
586 {
587 if((PRINT_LONGNAMES))
588 chpr += printf("%s:%d.",dirname,entry_num);
589 else
590 chpr += printf("IMA2:%d.",entry_num);
591 chpr += printf("Data");
592 if((PRINT_VALUE))
593 {
594 putindent(X3FTAGWIDTH - 7);
595 chpr += printf(" = ");
596 }
597 }
598 if((PRINT_VALUE))
599 chpr += printf("@%lu:%lu",data_offset,data_length);
600 }
601 chpr = newline(chpr);
602 break;
603 case X3F_PROP:
604 dirname = splice(parent_name,".","PROP");
605 prop_header = read_x3f_prop_header(inptr,byteorder,entry->data_offset);
606 data_offset = display_x3f_prop_header(entry,prop_header,dirname,entry_num,
607 indent + MEDIUMINDENT);
608 data_length = entry->data_length - (data_offset - entry->data_offset);
609 process_x3f_props(inptr,byteorder,data_offset,data_length,
610 prop_header->char_format,dirname,
611 prop_header->num_entries,
612 indent + MEDIUMINDENT);
613 break;
614 case X3F_CAMF:
615 dirname = splice(parent_name,".","CAMF");
616 camf_header = read_x3f_camf_header(inptr,byteorder,entry->data_offset);
617 data_offset = display_x3f_camf_header(entry,camf_header,dirname,entry_num,
618 indent + MEDIUMINDENT);
619 data_length = entry->data_length - (data_offset - entry->data_offset);
620 if((PRINT_SECTION))
621 {
622 print_tag_address(SECTION,data_offset,indent + MEDIUMINDENT,"@");
623 chpr += printf("<CAMF.Data> length %lu",data_length);
624 chpr = newline(chpr);
625 dumpsection(inptr,data_offset,data_length,indent + LARGEINDENT);
626 print_tag_address(SECTION,entry->data_offset + entry->data_length - 1,
627 indent + MEDIUMINDENT,"@");
628 chpr += printf("</CAMF.Data>");
629 }
630 else if((LIST_MODE))
631 {
632 print_tag_address(ENTRY,data_offset,indent + MEDIUMINDENT,"@");
633 if((PRINT_TAGINFO))
634 {
635 if((PRINT_LONGNAMES))
636 chpr += printf("%s:%d.",dirname,entry_num);
637 else
638 chpr += printf("CAMF:%d.",entry_num);
639 chpr += printf("Data");
640 if((PRINT_VALUE))
641 {
642 putindent(X3FTAGWIDTH - 7);
643 chpr += printf(" = ");
644 }
645 }
646 if((PRINT_VALUE))
647 chpr += printf("@%lu:%lu",data_offset,data_length);
648 }
649 chpr = newline(chpr);
650 break;
651 default:
652 if((PRINT_SECTION))
653 {
654 print_tag_address(SECTION,entry->data_offset,indent + MEDIUMINDENT,"@");
655 chpr += printf("<%4.4s> length %lu",(char *)&entry->section_id,entry->data_length);
656 chpr = newline(chpr);
657 dumpsection(inptr,data_offset,data_length,indent + LARGEINDENT);
658 print_tag_address(SECTION,entry->data_offset + entry->data_length - 1,
659 indent + MEDIUMINDENT,"@");
660 chpr += printf("</%4.4s>",(char *)&entry->section_id);
661 }
662 else if((LIST_MODE))
663 {
664 print_tag_address(ENTRY,data_offset,indent,"@");
665 if((PRINT_TAGINFO))
666 {
667 if((PRINT_LONGNAMES))
668 chpr += printf("%s:%d.",dirname,entry_num);
669 else
670 chpr += printf("%4.4s:%d.",(char *)&entry->section_id,entry_num);
671 if((PRINT_VALUE))
672 {
673 putindent(X3FTAGWIDTH - 7);
674 chpr += printf(" = ");
675 }
676 }
677 if((PRINT_VALUE))
678 chpr += printf("@%lu:%lu",entry->data_offset,entry->data_length);
679 }
680 chpr = newline(chpr);
681 break;
682 }
683 if((PRINT_SECTION))
684 {
685 print_tag_address(SECTION,entry->data_offset + entry->data_length - 1,indent,"@");
686 chpr += printf("</%4.4s:%d>",(char *)&entry->data_type,entry_num);
687 chpr += newline(chpr);
688 }
689 if(dirname)
690 free(dirname);
691 }
692 }
693
694 void
print_x3f_direntry(FILE * inptr,struct x3f_direntry * entry,unsigned long offset,char * parent_name,int entry_num,int indent)695 print_x3f_direntry(FILE *inptr,struct x3f_direntry *entry,unsigned long offset,
696 char *parent_name,int entry_num,int indent)
697 {
698 int chpr = 0;
699
700 if(entry)
701 {
702 print_tag_address(ENTRY,offset,indent + MEDIUMINDENT,"@");
703 if((PRINT_TAGINFO))
704 {
705 if((PRINT_LONGNAMES))
706 chpr += printf("%s.",parent_name);
707 chpr += printf("%4.4s:%-2d",(char *)&entry->data_type,entry_num);
708 if((PRINT_VALUE))
709 putindent(X3FTAGWIDTH - 7);
710 }
711 if((PRINT_VALUE))
712 {
713 chpr += printf(" = ");
714 chpr += printf("@%lu:%lu",entry->data_offset,entry->data_length);
715 }
716 chpr += newline(chpr);
717 }
718 }
719
720
721 struct x3f_direntry *
read_x3f_direntry(FILE * inptr,unsigned short byteorder,struct x3f_direntry * entry,unsigned long offset)722 read_x3f_direntry(FILE *inptr,unsigned short byteorder,struct x3f_direntry *entry,
723 unsigned long offset)
724 {
725 if(inptr)
726 {
727 if(entry == NULL)
728 entry = (struct x3f_direntry *)malloc(sizeof(struct x3f_direntry));
729 if(entry)
730 {
731 memset(entry,0,sizeof(struct x3f_direntry));
732 entry->data_offset = read_ulong(inptr,byteorder,offset);
733 entry->data_length = read_ulong(inptr,byteorder,HERE);
734 entry->data_type = read_ulong(inptr,byteorder,HERE);
735 }
736 }
737 else
738 entry = (struct x3f_direntry *)0;
739 return(entry);
740 }
741
742 struct x3f_imag_header *
read_x3f_imag_header(FILE * inptr,unsigned short byteorder,unsigned long offset)743 read_x3f_imag_header(FILE *inptr,unsigned short byteorder,unsigned long offset)
744 {
745 static struct x3f_imag_header header;
746 struct x3f_imag_header *headerptr= (struct x3f_imag_header *)0;
747
748 if(!feof(inptr) && !ferror(inptr))
749 {
750 header.section_id = read_ulong(inptr,byteorder,offset);
751 header.version_minor = read_ushort(inptr,byteorder,HERE);
752 header.version_major = read_ushort(inptr,byteorder,HERE);
753 header.image_type = read_ulong(inptr,byteorder,HERE);
754 header.image_format = read_ulong(inptr,byteorder,HERE);
755 header.image_width = read_ulong(inptr,byteorder,HERE);
756 header.image_height = read_ulong(inptr,byteorder,HERE);
757 header.image_rowsize = read_ulong(inptr,byteorder,HERE);
758 if(!feof(inptr) && !ferror(inptr))
759 headerptr = &header;
760 }
761 return(headerptr);
762 }
763
764 struct x3f_camf_header *
read_x3f_camf_header(FILE * inptr,unsigned short byteorder,unsigned long offset)765 read_x3f_camf_header(FILE *inptr,unsigned short byteorder,unsigned long offset)
766 {
767 static struct x3f_camf_header header;
768 struct x3f_camf_header *headerptr = (struct x3f_camf_header *)0;
769
770 if(!feof(inptr) && !ferror(inptr))
771 {
772 header.section_id = read_ulong(inptr,byteorder,offset);
773 header.version_minor = read_ushort(inptr,byteorder,HERE);
774 header.version_major = read_ushort(inptr,byteorder,HERE);
775 header.item1 = read_ulong(inptr,byteorder,HERE);
776 header.item2 = read_ulong(inptr,byteorder,HERE);
777 header.item3 = read_ulong(inptr,byteorder,HERE);
778 header.item4 = read_ulong(inptr,byteorder,HERE);
779 header.item5 = read_ulong(inptr,byteorder,HERE);
780 if(!feof(inptr) && !ferror(inptr))
781 headerptr = &header;
782 }
783 return(headerptr);
784 }
785
786 struct x3f_prop_header *
read_x3f_prop_header(FILE * inptr,unsigned short byteorder,unsigned long offset)787 read_x3f_prop_header(FILE *inptr,unsigned short byteorder,unsigned long offset)
788 {
789 static struct x3f_prop_header header;
790 struct x3f_prop_header *headerptr = (struct x3f_prop_header *)0;
791
792 if(!feof(inptr) && !ferror(inptr))
793 {
794 header.section_id = read_ulong(inptr,byteorder,offset);
795 header.version_minor = read_ushort(inptr,byteorder,HERE);
796 header.version_major = read_ushort(inptr,byteorder,HERE);
797 header.num_entries = read_ulong(inptr,byteorder,HERE);
798 header.char_format = read_ulong(inptr,byteorder,HERE);
799 header.reserved = read_ulong(inptr,byteorder,HERE);
800 header.entry_length = read_ulong(inptr,byteorder,HERE);
801 if(!feof(inptr) && !ferror(inptr))
802 headerptr = &header;
803 }
804 return(headerptr);
805 }
806
807 unsigned long
display_x3f_imag_header(struct x3f_direntry * direntry,struct x3f_imag_header * header,char * dirname,int entry_num,int indent)808 display_x3f_imag_header(struct x3f_direntry *direntry,struct x3f_imag_header *header,
809 char *dirname,int entry_num,int indent)
810 {
811 int chpr = 0;
812
813 print_tag_address(ENTRY,direntry->data_offset,indent,"@");
814 if((PRINT_TAGINFO))
815 {
816 if((PRINT_LONGNAMES))
817 chpr += printf("%s:%d.Header.",dirname,entry_num);
818 chpr += printf("%s","SectionId");
819 if((PRINT_VALUE))
820 {
821 putindent(X3FTAGWIDTH - 9);
822 chpr += printf(" = ");
823 }
824 }
825 if((PRINT_VALUE))
826 chpr += printf("%4.4s",(char *)&header->section_id);
827 chpr = newline(chpr);
828
829 print_tag_address(ENTRY,direntry->data_offset + 4,indent,"@");
830 if((PRINT_TAGINFO))
831 {
832 if((PRINT_LONGNAMES))
833 chpr += printf("%s:%d.Header.",dirname,entry_num);
834 chpr += printf("%s","Version");
835 if((PRINT_VALUE))
836 {
837 putindent(X3FTAGWIDTH - 7);
838 chpr += printf(" = ");
839 }
840 }
841 if((PRINT_VALUE))
842 chpr += printf("%u.%u",header->version_major,header->version_minor);
843 chpr = newline(chpr);
844
845 print_tag_address(ENTRY,direntry->data_offset + 8,indent,"@");
846 if((PRINT_TAGINFO))
847 {
848 if((PRINT_LONGNAMES))
849 chpr += printf("%s:%d.Header.",dirname,entry_num);
850 chpr += printf("%s","ImageType");
851 if((PRINT_VALUE))
852 {
853 putindent(X3FTAGWIDTH - 9);
854 chpr += printf(" = ");
855 }
856 }
857 if((PRINT_VALUE))
858 {
859 chpr += printf("%-2lu",header->image_type);
860 switch(header->image_type)
861 {
862 case 2: chpr += printf(" = \"Preview\""); break;
863 case 3: chpr += printf(" = \"Primary\""); break;
864 default: break;
865 }
866 }
867 chpr = newline(chpr);
868
869 print_tag_address(ENTRY,direntry->data_offset + 12,indent,"@");
870 if((PRINT_TAGINFO))
871 {
872 if((PRINT_LONGNAMES))
873 chpr += printf("%s:%d.Header.",dirname,entry_num);
874 chpr += printf("%s","ImageFormat");
875 if((PRINT_VALUE))
876 {
877 putindent(X3FTAGWIDTH - 11);
878 chpr += printf(" = ");
879 }
880 }
881 if((PRINT_VALUE))
882 {
883 chpr += printf("%-2lu",header->image_format);
884 switch(header->image_format)
885 {
886 case 3: chpr += printf(" = \"uncompressed RGB\""); break;
887 case 6: chpr += printf(" = \"compressed RAW\""); break;
888 case 11: chpr += printf(" = \"Huffman compressed RGB\""); break;
889 case 18: chpr += printf(" = \"JPEG compressed RGB\""); break;
890 default: break;
891 }
892 }
893 chpr = newline(chpr);
894
895 print_tag_address(ENTRY,direntry->data_offset + 16,indent,"@");
896 if((PRINT_TAGINFO))
897 {
898 if((PRINT_LONGNAMES))
899 chpr += printf("%s:%d.Header.",dirname,entry_num);
900 chpr += printf("%s","ImageWidth");
901 if((PRINT_VALUE))
902 {
903 putindent(X3FTAGWIDTH - 10);
904 chpr += printf(" = ");
905 }
906 }
907 if((PRINT_VALUE))
908 chpr += printf("%lu",header->image_width);
909 chpr = newline(chpr);
910
911 print_tag_address(ENTRY,direntry->data_offset + 20,indent,"@");
912 if((PRINT_TAGINFO))
913 {
914 if((PRINT_LONGNAMES))
915 chpr += printf("%s:%d.Header.",dirname,entry_num);
916 chpr += printf("%s","ImageHeight");
917 if((PRINT_VALUE))
918 {
919 putindent(X3FTAGWIDTH - 11);
920 chpr += printf(" = ");
921 }
922 }
923 if((PRINT_VALUE))
924 chpr += printf("%lu",header->image_height);
925 chpr = newline(chpr);
926
927 print_tag_address(ENTRY,direntry->data_offset + 24,indent,"@");
928 if((PRINT_TAGINFO))
929 {
930 if((PRINT_LONGNAMES))
931 chpr += printf("%s:%d.Header.",dirname,entry_num);
932 chpr += printf("%s","RowSize");
933 if((PRINT_VALUE))
934 {
935 putindent(X3FTAGWIDTH - 7);
936 chpr += printf(" = ");
937 }
938 }
939 if((PRINT_VALUE))
940 {
941 chpr += printf("%lu",header->image_rowsize);
942 if(header->image_rowsize == 0)
943 chpr += printf(" = \"variable length\"");
944 }
945 chpr = newline(chpr);
946
947 return(direntry->data_offset + 28);
948 }
949
950 unsigned long
display_x3f_prop_header(struct x3f_direntry * direntry,struct x3f_prop_header * header,char * dirname,int entry_num,int indent)951 display_x3f_prop_header(struct x3f_direntry *direntry,struct x3f_prop_header *header,
952 char *dirname,int entry_num,int indent)
953 {
954 int chpr = 0;
955
956 print_tag_address(ENTRY,direntry->data_offset,indent,"@");
957 if((PRINT_TAGINFO))
958 {
959 if((PRINT_LONGNAMES))
960 chpr += printf("%s:%d.Header.",dirname,entry_num);
961 chpr += printf("%s","SectionId");
962 if((PRINT_VALUE))
963 {
964 putindent(X3FTAGWIDTH - 9);
965 chpr += printf(" = ");
966 }
967 }
968 if((PRINT_VALUE))
969 chpr += printf("%4.4s",(char *)&header->section_id);
970 chpr = newline(chpr);
971
972 print_tag_address(ENTRY,direntry->data_offset + 4,indent,"@");
973 if((PRINT_TAGINFO))
974 {
975 if((PRINT_LONGNAMES))
976 chpr += printf("%s:%d.Header.",dirname,entry_num);
977 chpr += printf("%s","Version");
978 if((PRINT_VALUE))
979 {
980 putindent(X3FTAGWIDTH - 7);
981 chpr += printf(" = ");
982 }
983 }
984 if((PRINT_VALUE))
985 chpr += printf("%u.%u",header->version_major,header->version_minor);
986 chpr = newline(chpr);
987
988 print_tag_address(ENTRY,direntry->data_offset + 8,indent,"@");
989 if((PRINT_TAGINFO))
990 {
991 if((PRINT_LONGNAMES))
992 chpr += printf("%s:%d.Header.",dirname,entry_num);
993 chpr += printf("%s","Entries");
994 if((PRINT_VALUE))
995 {
996 putindent(X3FTAGWIDTH - 7);
997 chpr += printf(" = ");
998 }
999 }
1000 if((PRINT_VALUE))
1001 chpr += printf("%lu",header->num_entries);
1002 chpr = newline(chpr);
1003
1004 print_tag_address(ENTRY,direntry->data_offset + 12,indent,"@");
1005 if((PRINT_TAGINFO))
1006 {
1007 if((PRINT_LONGNAMES))
1008 chpr += printf("%s:%d.Header.",dirname,entry_num);
1009 chpr += printf("%s","CharFormat");
1010 if((PRINT_VALUE))
1011 {
1012 putindent(X3FTAGWIDTH - 10);
1013 chpr += printf(" = ");
1014 }
1015 }
1016 if((PRINT_VALUE))
1017 chpr += printf("%lu",header->char_format);
1018 chpr = newline(chpr);
1019
1020 print_tag_address(ENTRY,direntry->data_offset + 16,indent,"@");
1021 if((PRINT_TAGINFO))
1022 {
1023 if((PRINT_LONGNAMES))
1024 chpr += printf("%s:%d.Header.",dirname,entry_num);
1025 chpr += printf("%s","RESERVED");
1026 if((PRINT_VALUE))
1027 {
1028 putindent(X3FTAGWIDTH - 8);
1029 chpr += printf(" = ");
1030 }
1031 }
1032 if((PRINT_VALUE))
1033 chpr += printf("%lu",header->reserved);
1034 chpr = newline(chpr);
1035
1036 print_tag_address(ENTRY,direntry->data_offset + 20,indent,"@");
1037 if((PRINT_TAGINFO))
1038 {
1039 if((PRINT_LONGNAMES))
1040 chpr += printf("%s:%d.Header.",dirname,entry_num);
1041 chpr += printf("%s","SectionLength");
1042 if((PRINT_VALUE))
1043 {
1044 putindent(X3FTAGWIDTH - 13);
1045 chpr += printf(" = ");
1046 }
1047 }
1048 if((PRINT_VALUE))
1049 chpr += printf("%lu",header->entry_length);
1050 chpr = newline(chpr);
1051
1052 return(direntry->data_offset + 24);
1053 }
1054
1055 unsigned long
display_x3f_camf_header(struct x3f_direntry * direntry,struct x3f_camf_header * header,char * dirname,int entry_num,int indent)1056 display_x3f_camf_header(struct x3f_direntry *direntry,struct x3f_camf_header *header,
1057 char *dirname,int entry_num,int indent)
1058 {
1059 int chpr = 0;
1060
1061 print_tag_address(ENTRY,direntry->data_offset,indent,"@");
1062 if((PRINT_TAGINFO))
1063 {
1064 if((PRINT_LONGNAMES))
1065 chpr += printf("%s:%d.Header.",dirname,entry_num);
1066 chpr += printf("%s","SectionId");
1067 if((PRINT_VALUE))
1068 {
1069 putindent(X3FTAGWIDTH - 9);
1070 chpr += printf(" = ");
1071 }
1072 }
1073 if((PRINT_VALUE))
1074 chpr += printf("%4.4s",(char *)&header->section_id);
1075 chpr = newline(chpr);
1076
1077 print_tag_address(ENTRY,direntry->data_offset + 4,indent,"@");
1078 if((PRINT_TAGINFO))
1079 {
1080 if((PRINT_LONGNAMES))
1081 chpr += printf("%s:%d.Header.",dirname,entry_num);
1082 chpr += printf("%s","Version");
1083 if((PRINT_VALUE))
1084 {
1085 putindent(X3FTAGWIDTH - 7);
1086 chpr += printf(" = ");
1087 }
1088 }
1089 if((PRINT_VALUE))
1090 chpr += printf("%u.%u",header->version_major,header->version_minor);
1091 chpr = newline(chpr);
1092
1093 print_tag_address(ENTRY,direntry->data_offset + 8,indent,"@");
1094 if((PRINT_TAGINFO))
1095 {
1096 if((PRINT_LONGNAMES))
1097 chpr += printf("%s:%d.Header.",dirname,entry_num);
1098 chpr += printf("%s","Item1");
1099 if((PRINT_VALUE))
1100 {
1101 putindent(X3FTAGWIDTH - 5);
1102 chpr += printf(" = ");
1103 }
1104 }
1105 if((PRINT_VALUE))
1106 chpr += printf("%lu",header->item1);
1107 chpr = newline(chpr);
1108
1109 print_tag_address(ENTRY,direntry->data_offset + 12,indent,"@");
1110 if((PRINT_TAGINFO))
1111 {
1112 if((PRINT_LONGNAMES))
1113 chpr += printf("%s:%d.Header.",dirname,entry_num);
1114 chpr += printf("%s","Item2");
1115 if((PRINT_VALUE))
1116 {
1117 putindent(X3FTAGWIDTH - 5);
1118 chpr += printf(" = ");
1119 }
1120 }
1121 if((PRINT_VALUE))
1122 chpr += printf("%lu",header->item2);
1123 chpr = newline(chpr);
1124
1125 print_tag_address(ENTRY,direntry->data_offset + 16,indent,"@");
1126 if((PRINT_TAGINFO))
1127 {
1128 if((PRINT_LONGNAMES))
1129 chpr += printf("%s:%d.Header.",dirname,entry_num);
1130 chpr += printf("%s","Item3");
1131 if((PRINT_VALUE))
1132 {
1133 putindent(X3FTAGWIDTH - 5);
1134 chpr += printf(" = ");
1135 }
1136 }
1137 if((PRINT_VALUE))
1138 chpr += printf("%4.4s",(char *)&header->item3);
1139 chpr = newline(chpr);
1140
1141 print_tag_address(ENTRY,direntry->data_offset + 20,indent,"@");
1142 if((PRINT_TAGINFO))
1143 {
1144 if((PRINT_LONGNAMES))
1145 chpr += printf("%s:%d.Header.",dirname,entry_num);
1146 chpr += printf("%s","Item4");
1147 if((PRINT_VALUE))
1148 {
1149 putindent(X3FTAGWIDTH - 5);
1150 chpr += printf(" = ");
1151 }
1152 }
1153 if((PRINT_VALUE))
1154 chpr += printf("%lu",header->item4);
1155 chpr = newline(chpr);
1156
1157 /* Not sure how long the header is... CAMF is not described in */
1158 /* the public X3F spec. */
1159
1160 /* Assume the header is same length as PROP for the purposes of */
1161 /* dumping the data section */
1162 return(direntry->data_offset + 24);
1163 }
1164
1165 /* Process the property section. After the header, the section starts */
1166 /* with an index of offsets to each name and value. The actual names */
1167 /* and values follow. */
1168
1169
1170 unsigned long
process_x3f_props(FILE * inptr,unsigned short byteorder,unsigned long data_offset,unsigned long data_length,unsigned long char_format,char * dirname,unsigned long num_entries,int indent)1171 process_x3f_props(FILE *inptr,unsigned short byteorder,unsigned long data_offset,
1172 unsigned long data_length,unsigned long char_format,
1173 char *dirname,unsigned long num_entries,int indent)
1174 {
1175 unsigned long max_offset = 0UL;
1176 unsigned long name_offset = 0UL;
1177 unsigned long value_offset = 0UL;
1178 unsigned long offset = 0UL;
1179 unsigned long property_offset = 0UL;
1180 unsigned long index_length = 0UL;
1181 unsigned long list_data_length = 0UL;
1182 int chpr = 0;
1183 int i;
1184
1185 if(inptr)
1186 {
1187 clearerr(inptr);
1188 offset = data_offset;
1189 property_offset = data_offset + (num_entries * 8);
1190 index_length = num_entries * 8;
1191 list_data_length = data_length - index_length;
1192
1193 if((PRINT_SECTION))
1194 {
1195 print_tag_address(SECTION,data_offset,indent,"@");
1196 chpr += printf("<Property List> %ld entries, length %lu",num_entries,data_length);
1197 chpr = newline(chpr);
1198 print_tag_address(SECTION,data_offset,indent + SMALLINDENT,"@");
1199 chpr += printf("<Property List Index> %ld entries, length %lu",num_entries,index_length);
1200 chpr = newline(chpr);
1201 }
1202 /* Print the index of name/value offsets first */
1203 for(i = 0; i < num_entries; ++i)
1204 {
1205 if(fseek(inptr,offset,0) == 0)
1206 {
1207 name_offset = read_ulong(inptr,byteorder,HERE);
1208 name_offset *= 2;
1209 if(feof(inptr) || ferror(inptr))
1210 {
1211 PUSHCOLOR(RED);
1212 chpr += printf(" FAILED to read Property List name %d at offset %lu",i,offset);
1213 POPCOLOR();
1214 break;
1215 }
1216 value_offset = read_ulong(inptr,byteorder,HERE);
1217 value_offset *= 2;
1218 if(feof(inptr) || ferror(inptr))
1219 {
1220 PUSHCOLOR(RED);
1221 chpr += printf(" FAILED to read Property List value %d at offset %lu",i,offset + 4);
1222 POPCOLOR();
1223 break;
1224 }
1225
1226 /* Show the name/value offsets, even in LIST mode */
1227 print_tag_address(ENTRY,offset,indent + MEDIUMINDENT,"@");
1228 if((PRINT_TAGINFO))
1229 {
1230 if((PRINT_LONGNAMES))
1231 chpr += printf("%s.Index.",dirname);
1232 chpr += printf("NameOffset.%-2d",i);
1233 if((PRINT_VALUE))
1234 {
1235 putindent(X3FTAGWIDTH - 15);
1236 chpr += printf(" = ");
1237 }
1238 }
1239 if((PRINT_VALUE))
1240 {
1241 chpr += printf("@%lu",name_offset + property_offset);
1242 if((PRINT_RAW_VALUES))
1243 chpr += printf(" (%lu)",name_offset);
1244 }
1245 chpr = newline(chpr);
1246
1247 print_tag_address(ENTRY,offset + 4,indent + MEDIUMINDENT,"@");
1248 if((PRINT_TAGINFO))
1249 {
1250 if((PRINT_LONGNAMES))
1251 chpr += printf("%s.Index.",dirname);
1252 chpr += printf("ValueOffset.%-2d",i);
1253 if((PRINT_VALUE))
1254 {
1255 putindent(X3FTAGWIDTH - 16);
1256 chpr += printf(" = ");
1257 }
1258 }
1259 if((PRINT_VALUE))
1260 {
1261 chpr += printf("@%lu",value_offset + property_offset);
1262 if((PRINT_RAW_VALUES))
1263 chpr += printf(" (%lu)",value_offset);
1264 }
1265 chpr = newline(chpr);
1266
1267 }
1268 else
1269 {
1270 PUSHCOLOR(RED);
1271 chpr += printf(" SEEK FAILED reading Property List item %d at offset %lu",i,offset);
1272 POPCOLOR();
1273 break;
1274 }
1275
1276 offset += 8;
1277 max_offset = ftell(inptr);
1278 }
1279 if((PRINT_SECTION))
1280 {
1281 print_tag_address(SECTION,max_offset - 1,indent + SMALLINDENT,"@");
1282 chpr += printf("</Property List iIndex>");
1283 chpr = newline(chpr);
1284 print_tag_address(SECTION,property_offset,indent + SMALLINDENT,"@");
1285 chpr += printf("<Property List Data> length %lu",list_data_length);
1286 chpr = newline(chpr);
1287 }
1288 offset = data_offset;
1289
1290 /* Read 'em again, and this time show the names and values */
1291 for(i = 0; i < num_entries; ++i)
1292 {
1293 if(fseek(inptr,offset,0) == 0)
1294 {
1295 name_offset = read_ulong(inptr,byteorder,HERE);
1296 name_offset *= 2;
1297 if(feof(inptr) || ferror(inptr))
1298 {
1299 PUSHCOLOR(RED);
1300 chpr += printf(" FAILED to read Property List name %d at offset %lu",i,offset);
1301 POPCOLOR();
1302 break;
1303 }
1304 value_offset = read_ulong(inptr,byteorder,HERE);
1305 value_offset *= 2;
1306 if(feof(inptr) || ferror(inptr))
1307 {
1308 PUSHCOLOR(RED);
1309 chpr += printf(" FAILED to read Property List value %d at offset %lu",i,offset + 4);
1310 POPCOLOR();
1311 break;
1312 }
1313 name_offset += property_offset;
1314 value_offset += property_offset;
1315 print_property(inptr,byteorder,name_offset,value_offset,char_format,
1316 dirname,i,indent + MEDIUMINDENT);
1317 }
1318 else
1319 {
1320 PUSHCOLOR(RED);
1321 chpr += printf(" SEEK FAILED reading Property List item %d at offset %lu",i,offset);
1322 POPCOLOR();
1323 break;
1324 }
1325
1326 offset += 8;
1327 max_offset = ftell(inptr);
1328 }
1329 if((PRINT_SECTION))
1330 {
1331 print_tag_address(SECTION,max_offset - 1,indent + SMALLINDENT,"@");
1332 chpr += printf("</Property List Data>");
1333 chpr = newline(chpr);
1334 }
1335 if((PRINT_SECTION))
1336 {
1337 print_tag_address(SECTION,property_offset + list_data_length - 1,indent,"@");
1338 chpr += printf("</Property List>");
1339 chpr = newline(chpr);
1340 }
1341 }
1342 else
1343 {
1344 PUSHCOLOR(RED);
1345 fprintf(stderr,"%s: no file pointer to read X3F Properties List\n",Progname);
1346 POPCOLOR();
1347 }
1348 setcharsprinted(chpr);
1349 return(max_offset);
1350 }
1351
1352 /* Displays property names and values, given their offsets. The */
1353 /* characters are encoded as 16 bit 'unicode'. This routine reads */
1354 /* each character as an unsigned short and echos it via putchar(). */
1355
1356 void
print_property(FILE * inptr,unsigned short byteorder,unsigned long name_offset,unsigned long value_offset,unsigned long char_format,char * dirname,int index,int indent)1357 print_property(FILE *inptr,unsigned short byteorder,unsigned long name_offset,
1358 unsigned long value_offset,unsigned long char_format,
1359 char *dirname,int index,int indent)
1360 {
1361 int chpr = 0;
1362 int i = 0;
1363 int ch;
1364
1365 if(inptr)
1366 {
1367 clearerr(inptr);
1368 if(fseek(inptr,name_offset,0) == 0)
1369 {
1370 if((PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET))
1371 {
1372 print_tag_address(ENTRY,name_offset,indent + SMALLINDENT,"@");
1373 if((PRINT_TAGINFO))
1374 {
1375 if((PRINT_LONGNAMES))
1376 chpr += printf("%s.Data.",dirname);
1377 chpr += printf("Name.%-2d",index);
1378 if((PRINT_VALUE))
1379 {
1380 putindent(X3FTAGWIDTH - 17);
1381 chpr += printf(" = ");
1382 }
1383 }
1384 if((PRINT_VALUE))
1385 {
1386 while((ch = read_ushort(inptr,byteorder,HERE)))
1387 {
1388 if((PRINT_UNICODE))
1389 fwrite((char *)&ch,2,1,stdout);
1390 else
1391 putchar(ch);
1392 ++chpr;
1393 }
1394 }
1395 }
1396 else
1397 {
1398 print_tag_address(ENTRY,name_offset,indent + SMALLINDENT,"@");
1399 if((PRINT_TAGINFO))
1400 {
1401 if((PRINT_LONGNAMES))
1402 chpr += printf("%s.Data.",dirname);
1403 i = 0;
1404 while((ch = read_ushort(inptr,byteorder,HERE)))
1405 {
1406 if((PRINT_UNICODE))
1407 fwrite((char *)&ch,2,1,stdout);
1408 else
1409 putchar(ch);
1410 ++chpr;
1411 ++i;
1412 }
1413 if((PRINT_VALUE))
1414 {
1415 putindent(X3FTAGWIDTH - i - 6);
1416 chpr += printf(" = ");
1417 }
1418 }
1419 }
1420 }
1421 if((PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET))
1422 chpr = newline(chpr);
1423 if(fseek(inptr,value_offset,0) == 0)
1424 {
1425 if((PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET))
1426 {
1427 print_tag_address(ENTRY,value_offset,indent + SMALLINDENT,"@");
1428 if((PRINT_TAGINFO))
1429 {
1430 if((PRINT_LONGNAMES))
1431 chpr += printf("%s.",dirname);
1432 chpr += printf("Value.%-2d",index);
1433 if((PRINT_VALUE))
1434 {
1435 putindent(X3FTAGWIDTH - 18);
1436 chpr += printf(" = ");
1437 }
1438 }
1439 if((PRINT_VALUE))
1440 {
1441 while((ch = read_ushort(inptr,byteorder,HERE)))
1442 {
1443 if((PRINT_UNICODE))
1444 fwrite((char *)&ch,2,1,stdout);
1445 else
1446 putchar(ch & 0xff);
1447 ++chpr;
1448 }
1449 }
1450 }
1451 else if((PRINT_VALUE))
1452 {
1453 while((ch = read_ushort(inptr,byteorder,HERE)))
1454 {
1455 if((PRINT_UNICODE))
1456 fwrite((char *)&ch,2,1,stdout);
1457 else
1458 putchar(ch & 0xff);
1459 ++chpr;
1460 }
1461 }
1462 }
1463 chpr = newline(chpr);
1464 }
1465 }
1466