/*
        Frank Lyonnet 1993
*/

#include "Erreur.h"
#include "Bool.h"
#include <stdio.h>
#include "Modes.h"

#define JFREAD(file,buf,sizeofbuf)  \
  ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))

#define LM_to_uint(a,b)         ((((b)&0xFF) << 8) | ((a)&0xFF))

#define BitSet(byte, bit)       ((byte) & (bit))

#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))

#define COLORMAPFLAG    0x80    /* mask for bit signifying colormap presence */

static int ReadByte(FILE * File) {
/* Read next byte from GIF file */
  int c;

  if ((c = getc(File)) == EOF)
     erreur_fatal("Premature EOF in GIF file");
  return c;
}

static int GetDataBlock (FILE * File, char *buf) {
/* Read a GIF data block, which has a leading count byte */
/* A zero-length block marks the end of a data block sequence */
  int count;

  count = ReadByte(File);
  if (count > 0) {
    if (! ReadOK(File, buf, count))
      erreur_fatal("Premature EOF in GIF file");
  }

  return count;
}

static void SkipDataBlocks (FILE * File) {
/* Skip a series of data blocks, until a block terminator is found */
  char buf[256];

  while (GetDataBlock(File,buf) > 0)
    /* skip */;
}

static void DoExtension(FILE * File) {
/* Process an extension block */
/* Currently we ignore 'em all */
  int extlabel;

  /* Read extension label byte */
  extlabel = ReadByte(File);

  /* Skip the data block(s) associated with the extension */
  SkipDataBlocks(File);
}

static void SkipColorMap (FILE * File, int cmaplen) {
 int i; /* Skip a GIF colormap */

  for (i = 0; i < cmaplen; i++) {
    (void) ReadByte(File);
    (void) ReadByte(File);
    (void) ReadByte(File);
  }
}

BOOL is_gif(char *Filename) {
 FILE *File;
 BOOL Res = FALSE;
 char hdrbuf[10];        /* workspace for reading control blocks */

   File = fopen(Filename, "r");
   if (ReadOK(File, hdrbuf, 6))
      Res =(hdrbuf[0] == 'G' && hdrbuf[1] == 'I' && hdrbuf[2] == 'F');
   fclose(File);
   return (Res);
}

void get_gif_size(char *Filename, int *Width, int *Height) {
 char hdrbuf[10];                /* workspace for reading control blocks */
 short int width, height;           /* image dimensions */
 int colormaplen,c;
 FILE *File;

   File = fopen(Filename, "r");

   if (!ReadOK(File, hdrbuf, 6))
      erreur_fatal("Not a GIF file");

   if (hdrbuf[0] != 'G' || hdrbuf[1] != 'I' || hdrbuf[2] != 'F')
      erreur_fatal("Not a GIF file");

   if ((hdrbuf[3] != '8' || hdrbuf[4] != '7' || hdrbuf[5] != 'a') &&
       (hdrbuf[3] != '8' || hdrbuf[4] != '9' || hdrbuf[5] != 'a'))
      erreur_fatal("Not a GIF file");

   if (!ReadOK(File, hdrbuf, 7))
      erreur_fatal("Premature EOF in GIF file");

   width = LM_to_uint(hdrbuf[0], hdrbuf[1]);
   height = LM_to_uint(hdrbuf[2], hdrbuf[3]);
   colormaplen = 2 << (hdrbuf[4] & 0x07);

  /* Read global colormap if header indicates it is present */
   if (BitSet(hdrbuf[4], COLORMAPFLAG))
      SkipColorMap(File, colormaplen);

   /* Scan until we reach start of desired image.
    * We don't currently support skipping images, but could add it easily.
    */

   for (;;) {
      c = ReadByte(File);

      if (c == ';')               /* GIF terminator?? */
         erreur_fatal("Too few images in GIF file");

      if (c == '!') {   
         /* Extension */
         DoExtension(File);
         continue;
      }
    
      if (c != ',')       /* Not an image separator? */
         continue;
    
      /* Read and decipher Local Image Descriptor */
      if (!ReadOK(File, hdrbuf, 9))
         erreur_fatal("Premature EOF in GIF file");

      /* we ignore top/left position info, also sort flag */
      width = LM_to_uint(hdrbuf[4],hdrbuf[5]);
      height = LM_to_uint(hdrbuf[6],hdrbuf[7]);   

      break;
   }   

   *Width = width;
   *Height = height;

   fclose(File);
}

void get_gif_bpp_and_colorspace(char *Filename,int *Bpp,int *Colorspace) {
   *Bpp = 8;
   *Colorspace = FYEO_COLORMAPED;
}

