#include <stdio.h>
#include "config.h"
#include "unixlib.h"

#if defined(ATARI_ST)
#include <string.h>
#include <ext.h>

#elif defined (SUN) || defined(MSDOS) || defined(SEQUENT386) || defined(AVIION)
#include <sys/types.h>
#include <sys/stat.h>

#else
#error Wrong machine type. Edit config.h and follow the instructions.

#endif

#include "portab.h"
#include "picstat.h"


typedef struct
{
  UWORD b_width;
  UWORD b_height;
  WORD  b_x;
  WORD  b_y;
  UBYTE b_nplanes;
  UBYTE b_mask;
  UBYTE b_comp;
  UBYTE b_unused;
  UWORD b_tcol;
  UBYTE b_xaspect;
  UBYTE b_yaspect;
  UWORD b_pwidth;
  UWORD b_pheight;
} BMHDBUF;

typedef struct
{
  ULONG a_mode;
} CAMGBUF;

typedef struct
{
  UBYTE c_col[256];
} CMAPBUF;

/*
 *  return IFF ILBM stats of a file
 */

int ilbmstat (name, buf, mode)
 char *name;
 struct picstat *buf;
 int mode;

{
  int ret;
  struct stat sbuf;
  FILE *fp;
  UBYTE marker[4];
  unsigned long length;
  BMHDBUF bmhdbuf;
  CAMGBUF camgbuf;
  CMAPBUF cmapbuf;
  UBYTE *col;

  int i, j, k;
  int bufcount;
  int ncols;

  if (mode)
    {
      ret = lstat (name, &sbuf);
    }
  else
    {
      ret = stat (name, &sbuf);
    }
  if (ret)
    {
      return (-1);
    }
  if ((fp = fopen (name, "rb")) == NULL)
    {
      return (-1);
    }
  if (4L != fread (marker, 1L, 4L, fp))
    {
      fclose (fp);
      return (-1);
    }
  if (strncmp (marker, "FORM", 4) != 0)
    {
      fclose (fp);
      return (-1);
    }
  if (4L != fread (marker, 1L, 4L, fp))
    {
      fclose (fp);
      return (-1);
    }
  if (4L != fread (marker, 1L, 4L, fp))
    {
      fclose (fp);
      return (-1);
    }
  if (strncmp (marker, "ILBM", 4) != 0)
    {
      fclose (fp);
      return (-1);
    }
  bufcount = 0;
  while ((bufcount<3) && (!feof(fp)))
    {
      if (4L != fread (marker, 1L, 4L, fp))
        {
          fclose (fp);
          return (-1);
        }
      if (4L != fread (&length, 1L, 4L, fp))
        {
          fclose (fp);
          return (-1);
        }
      if (strncmp (marker, "BMHD", 4) == 0)
        {
          bufcount++;
          if (length != sizeof(BMHDBUF))
            {
              fclose (fp);
              return (-1);
            }
          if (length != fread (&bmhdbuf, 1L, length, fp))
            {
              fclose (fp);
              return (-1);
            }
        }
      else if (strncmp (marker, "CAMG", 4) == 0)
        {
          bufcount++;
          if (length != sizeof(CAMGBUF))
            {
              fclose (fp);
              return (-1);
            }
          if (length != fread (&camgbuf, 1L, length, fp))
            {
              fclose (fp);
              return (-1);
            }
        }
      else if (strncmp (marker, "CMAP", 4) == 0)
        {
          bufcount++;
          if (length > sizeof(CMAPBUF))
            {
              fclose (fp);
              return (-1);
            }
          if (length != fread (&cmapbuf, 1L, length, fp))
            {
              fclose (fp);
              return (-1);
            }
          ncols = length/3;
        }
      else
        {
          if (fseek (fp, length, SEEK_CUR) != 0)
            {
              fclose (fp);
              return (-1);
            }
        }
    }
  if (fclose (fp))
    {
      return (-1);
    }
  col = cmapbuf.c_col;
  buf->p_fsize = sbuf.st_size;
  buf->p_sizex = NSWAP2(bmhdbuf.b_width);
  buf->p_sizey = NSWAP2(bmhdbuf.b_height);
  for (buf->p_colrez=0, i=0; i < ncols; i++)
    {
      for (j=0; j<8; j++)
        {
          if (!((col[3*i] >> j) & 0x1) ||
              !((col[3*i+1] >> j) & 0x1) ||
              !((col[3*i+2] >> j) & 0x1))
            {
              break;
            }
        }
      for (k=8; k>0; k--)
        {
          if (!((col[3*i] >> k) & 0x1) ||
              !((col[3*i+1] >> k) & 0x1) ||
              !((col[3*i+2] >> k) & 0x1))
            {
              break;
            }
        }
      if (k-j+1 > buf->p_colrez)
        {
          buf->p_colrez = k-j;
        }
    }
  for (buf->p_coltype=CT_BW, i=0; i < ncols; i++)
    {
        if ((col[3*i] != col[3*i+1]) || (col[3*i+1] != col[3*i+2]))
          {
            buf->p_coltype = CT_COLOR;
            break;
          }
      }
  if (buf->p_coltype == CT_COLOR)
    {
      buf->p_colrez *= 3;
    }
  buf->p_ncol = ncols;
  for (i=0; i < ncols; i++)
    {
      for (j=0; j < i; j++)
        {
          if ((col[3*i] == col[3*j]) &&
              (col[3*i+1] == col[3*j+1]) &&
              (col[3*i+2] == col[3*j+2]))
            {
              col[3*j] = col[0];
              col[3*j+1] = col[1];
              col[3*j+2] = col[2];
              buf->p_ncol--;
              break;
            }
        }
    }
  if (buf->p_ncol >= 1<<buf->p_colrez)
    {
      buf->p_ncol = 1<<buf->p_colrez;
    }
  buf->p_nframes = 1;
  buf->p_speed = 0;
  if (camgbuf.a_mode & 0x00000800)
    {
      strcpy (buf->p_type, "HAM");
    }
/*
  else if (camgbuf.a_mode & 0x00000800)
    {
      strcpy (buf->p_type, "HAM8");
    }
*/
  else
    {
      strcpy (buf->p_type, "ILBM");
    }
  buf->p_cols = NULL;
  return (0);
}
