/**************************************************
 *
 * FileID.c
 *
 *    Identify picture/IFF file
 *      and give info about it.
 *
 *    Copyright(c), 1990, 1991. Lloyd B. Eldred
 *                            & Fredrick R Homan
 **************************************************/
#include <stdio.h>
#include <math.h>
#include "fi_iff.h"

UBYTE VERBOSE, TERSE,COMMENT;  /* Yuck, global variables... */

void main(argc, argv)
char **argv;
{
	FILE *picfile;
	char buf[256];
   char *filename; 
	int type,width,height,color,i,planes,start,start2,offset;
	UBYTE c,c1,c2,c3,c4,gct,cr,sf,bci,p;
	long pos;
	UWORD par;
	LONG makelong(char,char,char,char),ch_size;
   int cfind(char * , int , char * , int);
   int cfindws(char * , int , char * , int, int);
   void Gif_PlainText(FILE *, UBYTE),Gif_Application(FILE *, UBYTE),
      Gif_Comment(FILE *, UBYTE),Gif_Image(FILE *, UBYTE),
      Gif_Graphic(FILE *, UBYTE),fi_getc(FILE *,char *),
      fi_exit();
   float ar;
/*
   struct stat *st;
*/   
  	if ((argc < 2) | (argc > 3)) {
		printf(
		"FileID -- File IDentifier. V 1.30\n"
      "Copyright (c) 1990, 1991 Lloyd B. Eldred and Fredrick R Homan.\n"
		"Gives information about GIF and IFF files\n"
		"Usage: FileID [-flag] filename\n"
      "Valid flags: -c : Give included comments only\n"
      "             -t : terse mode, gives one line output\n"
      "             -v : verbose mode, gives lots of extra information\n");
		fi_exit();
	}
   
   COMMENT = FALSE;
   VERBOSE = FALSE;
   TERSE = FALSE;
   type = 0;
   filename = argv[1];
   
   c1 = argv[1][0];
   c2 = argv[1][1];
   if(c1 == '-'){
      if(c2 == 'v' || c2 == 'V'){
          VERBOSE=TRUE;
          if(argc == 3) filename = argv[2];
          else{
             printf("No file specified\n");
             fi_exit();
             }
       }
       else if(c2 == 't' || c2 == 'T'){
          TERSE=TRUE;
          if(argc == 3) filename = argv[2];
          else{
             printf("No file specified\n");
             fi_exit();
             }
       }
       else if(c2 == 'c' || c2 == 'C'){
          COMMENT=TRUE;
          if(argc == 3) filename = argv[2];
          else{
             printf("No file specified\n");
             fi_exit();
             }
       } 
       else{
            printf("Invalid flag -%c\n",c2);
            fi_exit();
       }
      }   
      
	if ((picfile = fopen(filename, "rb")) == NULL) {
			perror(filename);
			fi_exit();
   		}
/* 
   if(stat(filename,st) == -1){
         printf("Error reading file statistics.\n");
         fi_exit();
      }
   
   filesize = (long)st->st_size;
*/      
	/* search for header line */
	for (;;) {
		if (fread(buf, sizeof(buf), 1,picfile) != 1) {
			fprintf(stderr, "Unrecognized filetype\n");
			fclose(picfile);
			fi_exit();
		}
		start = cfind(buf,3,"GIF",3);
		if (start != -1){
			type=GIF;
			break;
		}
		
		start = cfind(buf,4,"FORM",4);
		if (start != -1){
			type=IFF;
			break;
		}
		
		start = cfind(buf,4,"CAT ",4);
		if (start != -1){
			type=IFF;
			break;
		}

		start = cfind(buf,4,"LIST",4);
		if (start != -1){
			type=IFF;
			break;
		}
      
/* Well, one last try: check for a Mac-padded GIF */
		start = cfind(buf,sizeof(buf),"GIF",3);
		if (start != -1){
			type=GIF;
			break;
		}


	        
	}
	
	fclose(picfile);

/********************************************************************/
/*                          GIF analysis                            */
/********************************************************************/
	
	if(type == GIF){

		if(start != 0){
			printf("Padding encountered at the beginning of the file.\n" 
                "Some viewers may not like this file.\n");
		   start2 = cfindws(buf,sizeof(buf),"GIF",3,128);
		   if (start2 != -1){
			   printf("Macintosh resource fork found. Recommend using"
                " StripGif to remove the header.\n");
            start=start2;
         }
      }

 		c1 = buf[start+3];
		c2 = buf[start+4];
		c3 = buf[start+5];

		if(!TERSE){
         printf("GIF -- Version %c%c%c:",c1,c2,c3);
		   if( c1 != '8' || (c2 != '7' && c2 != '9') || c3 != 'a'){
		      printf(" non recognized version, the following are guesses");
            }
    		if (COMMENT) printf("\n");
         if(!COMMENT) printf("\n  Image Header\n");
      }
      else printf("GIF%c%c%c",c1,c2,c3);
         
		c1 = buf[start+6];
		c2 = buf[start+7];
		c3 = buf[start+8];
		c4 = buf[start+9];
		c  = buf[start+10];
      bci= buf[start+11];
      p= buf[start+12];
			
  /* Expand Logical Screen Descriptor packed fields */
      gct = (UBYTE)(c & 0x80);
      cr =  (UBYTE)(c & 0x70)>>4;
      cr++;
      sf =  (UBYTE)(c & 0x08);
		planes = (int)(c & 0x7) + 1;
      par=(UWORD)p+15;

      ar = par/64.0;
         
      if(VERBOSE){
         if(gct && !sf)
           printf("    Global Color Table Flag set (table unsorted)\n");
         if(gct && sf)
           printf("    Global Color Table Flag set (table sorted)\n");
         printf("    Color resolution: %d bits of RG&B per palette color\n",
               cr);
         if(gct)
            printf("    Background color is color number %d\n",bci);
         if(!p)
            printf("    No pixel aspect ratio information given.\n");
         else
            printf("    Aspect ratio (pixel's width/height) is %g\n",ar);
      }
      
		color=1;
		
		for(i=0; i<planes ; i++)
		  color = color * 2;
		
		width=c1 + 256 * c2;
		
		height=c3 + 256 * c4;
		
		if(!TERSE && !COMMENT) 
                 printf("    Width : %5d\n"
		                  "    Height: %5d\n"
		                  "    Colors: %5d\n",width,height,color);
                        
      if(TERSE) printf(" %5d %5d %5d\n",width,height,color);              
		
      /* 
       *Done with logical screen descriptor, continue
       * only if user has selected verbose mode
       */
   if(!VERBOSE && !COMMENT) fi_exit();
   
   offset=start+13;
   
   if(gct){ /* if Global Color Table, skip it... */
      offset += 3 * color; 
      }
   
	if ((picfile = fopen(filename, "rb")) == NULL) {
			perror(filename);
			fi_exit();
   		}
   if (fseek(picfile,offset,1) == -1){
         printf(" Unexpected end of file. (1)\n");  
         fclose(picfile);
         fi_exit();
      }
   
   for(;;){
   
      fi_getc(picfile,&c1);
      
      switch(c1){
         case 0x2c:
            Gif_Image(picfile,!COMMENT);
            break;
         
         case 0x21:
            if (!COMMENT) printf("  Extension:");
            fi_getc(picfile,&c2);
            
            if(c2 == 0xf9) Gif_Graphic(picfile,!COMMENT);
            if(c2 == 0xfe) {
             if (!COMMENT) printf("Comment\n");
             Gif_Comment(picfile,1);
            }
            if(c2 == 0x01) Gif_PlainText(picfile,!COMMENT);
            if(c2 == 0xff) Gif_Application(picfile,!COMMENT);

            break;
              
         case 0x3b:
            printf("  Normal End of GIF reached.\n");               
            pos = ftell(picfile);
            printf("  GIF terminator found at %d bytes offset.\n"
                        ,pos);            
            fclose(picfile);
            fi_exit();
            break;
/***/            
         default:
            pos = ftell(picfile);
            printf(
            "  Unknown block type: (Label 0x%x) at %d bytes offset.\n"
               ,c1,pos);            
            fclose(picfile);
            fi_exit();
            break;
         
         } /* end of switch */

   } /* end of for(;;) */
 
   
	} /* End of GIF analysis section */

/********************************************************************/
/*                          IFF analysis                            */
/********************************************************************/

	if(type == IFF){
		if(!TERSE) printf("IFF file:\n");
      if(TERSE) printf("IFF - ");
      
      c = buf[start];
	   if ((picfile = fopen(filename, "rb")) == NULL) {
			perror(filename);
			fi_exit();
   		}
      if (fseek(picfile,start+4,1) == -1){
         printf(" Unexpected end of file. (I-1)\n");  
         fclose(picfile);
         fi_exit();
      }

      ch_size = IFF_size(picfile);
            
      if(c == 'F') IFF_FORM(picfile,ch_size);
      if(c == 'C') IFF_CAT(picfile,ch_size);
      if(c == 'L') IFF_LIST(picfile,ch_size);
      
      if(VERBOSE) printf("End of File.\n");
      pos = ftell(picfile);
      if(VERBOSE) printf("  IFF file ended at %d bytes offset.\n"
                        ,pos);
      fclose(picfile);
      fi_exit();
      } /* End of IFF code */
	
} /* end of main() */

int cfind(buffer,blength,string,slength)
char *buffer;
char *string;
int blength,slength;
{
	int i,start;
	int found;
	
	start = 0;
	
	while(start <= (blength-slength)){
		found = 1;
		
		for(i=0;i<slength;i++)
			if(buffer[start+i] != string[i]){
				found = 0;
				break;
			}
		
		if(found == 1) return(start);
		
		start++;
	}
	
	return(-1);  /* string not found */
		
} /* end of cfind() */	

int cfindws(buffer,blength,string,slength,init)
char *buffer;
char *string;
int blength,slength,init;
{
	int i,start;
	int found;
	
	start = init;
	
	while(start <= (blength-slength)){
		found = 1;
		
		for(i=0;i<slength;i++)
			if(buffer[start+i] != string[i]){
				found = 0;
				break;
			}
		
		if(found == 1) return(start);
		
		start++;
	}
	
	return(-1);  /* string not found */
		
} /* end of cfindws() */	

LONG makelong(c1,c2,c3,c4)  /* makes 4 bytes into a long, MSB first */
char c1,c2,c3,c4;
{
	union value_union{
      LONG number;
      char text[4];} value; 
	
   value.text[0]=c1;
   value.text[1]=c2;
   value.text[2]=c3;
   value.text[3]=c4;
   
	return(value.number);
	
} /* end of makelong() */


void fi_exit()
{
   exit(0);
}
