/* drawhack
 * (c) Tony Howat, 1997
 * xargle@eh.org or http://www.xargle.demon.co.uk/2020
 *
 * drawhack does its best to produce some sort of sensible textual output
 * from a drawfile in it own special way, dissecting each object as it
 * goes.
 *
 * drawhack may be freely distributed, edited, whatever, as long as I get
 * some of the hugs if people find it useful
 */

#include <stdio.h>
#include <string.h>
#include <time.h>

#define DRAW 0x77617244

/* see OS3 PRM 4-458 */
struct draw_file_header
{
  int id;           /* Should be "Draw", 0x77617244 */
  int majorver;     /* Major part of version number */
  int minorver;     /* Minor part of version number */
  char creator[12]; /* String ID of program which created file */
  int xmin;         /* file bounding box */
  int ymin;         /* file bounding box */
  int xmax;         /* file bounding box */
  int ymax;         /* file bounding box */
};

struct draw_object_header
{
  int tag;          /* 1 word  */
  int size;         /* 1 word  */
  int xmin;         /* object bounding box */
  int ymin;         /* object bounding box */
  int xmax;         /* object bounding box */
  int ymax;         /* object bounding box */
};

struct draw_libstrhdr			/* Library object */
{
  char name[21];			/* Object name */
  time_t time;			/* Time last updated */
};

int read_object(FILE *in)
{
  struct draw_object_header header;

  printf("(0x%x)",(int)ftell(in));

  /* read in header */
  if(1!=fread(&header,sizeof(header),1,in))
  {
    printf("(0x%x)",(int)ftell(in));
    printf("Object header is too short.\n");
    return 0;
  }

  printf("(0x%x)",(int)ftell(in));

  printf("draw_object_header\n"
         "tag = %i\n"
         "size = %i\n"
         "bbox (xmin,ymin,xmax,ymax) = %i,%i,%i,%i\n\n"
         ,header.tag,header.size,header.xmin,
         header.ymin,header.xmax,header.ymax);

  switch(header.tag)
  {
    case 0:
    {
      printf("-- Font List Object\n");
      fseek(in,SEEK_CUR,header.size);
      printf("(0x%x)",(int)ftell(in));
      break;
    }
    case 1:
    {
      printf("-- Text Object\n");
      fseek(in,SEEK_CUR,header.size);
      printf("(0x%x)",(int)ftell(in));
      break;
    }
    case 2:
    {
      printf("-- Path Object\n");
      fseek(in,SEEK_CUR,header.size);
      printf("(0x%x)",(int)ftell(in));
      break;
    }
    case 5:
    {
      printf("-- Sprite Object\n");
      fseek(in,SEEK_CUR,header.size);
      printf("(0x%x)",(int)ftell(in));
      break;
    }
    case 6:
    {
      printf("-- Group Object\n");
      fseek(in,SEEK_CUR,header.size);
      printf("(0x%x)",(int)ftell(in));
      break;
    }
    case 9:
    {
      printf("-- Text Area Object\n");
      fseek(in,SEEK_CUR,header.size);
      printf("(0x%x)",(int)ftell(in));
      break;
    }
    case 10:
    {
      printf("-- Text Column Object\n");
      fseek(in,SEEK_CUR,header.size);
      printf("(0x%x)",(int)ftell(in));
      break;
    }
    case 100:
    {
      struct draw_libstrhdr libstrhdr;
      char name[22];
      char time[30];

      printf("-- DrawPlus Library object\n");

      /* read in header */
      if(1!=fread(&libstrhdr,sizeof(libstrhdr),1,in))
      {
        printf("DrawPlus library header is too short.\n");
        return 0;
      }

      strncpy(name,libstrhdr.name,21);
      name[21]='\0'; /* make sure it's terminated */
      

      printf("-- name = %s time = %s\n",name,asctime(localtime(&(libstrhdr.time))));
      //read_object(in);
      printf("(0x%x)",(int)ftell(in));
      printf("skip %i\n",header.size-sizeof(struct draw_libstrhdr)-sizeof(struct draw_object_header));
      fseek(in,SEEK_CUR,header.size-sizeof(struct draw_libstrhdr)-sizeof(struct draw_object_header));
      printf("(0x%x)",(int)ftell(in));
      printf("---\n");
      return 1;
      break;
    }
    default:
      printf("Unknown object type, skipping\n");
      fseek(in,SEEK_CUR,header.size);
      return 0;
      break;      
  }
}

int read_file_header(FILE *in)
{
  struct draw_file_header header;
  /* read in header */
  if(1!=fread(&header,sizeof(header),1,in))
  {
    printf("File header is too short, I will try without a file header\n");
    rewind(in);
    return 0;
  } else {
    if(header.id != DRAW)
    {
      printf("No valid draw file header, I will try without a file header\n");
      rewind(in);
      return 0;
    } else {
      char creator[14];

      strncpy(creator,header.creator,12);
      creator[12]='\0'; /* make sure it's terminated */

      printf("draw_file_header\n"
             "version (major:minor) = %i.%i\n"
             "creator = %s\n"
             "bbox (xmin,ymin,xmax,ymax) = %i,%i,%i,%i\n\n"
             ,header.majorver,header.minorver,creator,header.xmin,
             header.ymin,header.xmax,header.ymax);
    }
  }

  return 1;
}

int drawhack(char *file)
{
  FILE *in;

  if((in=fopen(file,"rb+"))==NULL)
  {
    printf("Couldn't open %s.\n",file);
    return 1;
  }

  read_file_header(in);
  
  while(read_object(in))
    ;
    
  fclose(in);
  return 0;
}

int main(void)
{
  printf("Drawhack V0.00, (c) Tony Howat 1997.\n"
         "Compiled " __DATE__"\n\n");

  return drawhack("<DLibrary$Dir>.tests.2");
}
