/*****************************************************************************
*
*                                     dump.c
*
*   from DKBTrace (c) 1990  David Buck
*
*  This module contains the code to read and write the default file format
*  generated by DKBTrace.  The format is as follows:
*
*
*  (header:)
*    wwww hhhh       - Width, Height (16 bits, LSB first)
*
*  (each scanline:)
*    llll            - Line number (16 bits, LSB first)
*    rr rr rr ...    - Red data for line (8 bits per pixel,
*                       left to right, 0-255 (255=bright, 0=dark))
*    gg gg gg ...    - Green data for line (8 bits per pixel,
*                       left to right, 0-255 (255=bright, 0=dark))
*    bb bb bb ...    - Blue data for line (8 bits per pixel,
*                       left to right, 0-255 (255=bright, 0=dark))
*
* This software is freely distributable. The source and/or object code may be
* copied or uploaded to communications services so long as this notice remains
* at the top of each file.  If any changes are made to the program, you must
* clearly indicate in the documentation and in the programs startup message
* who it was who made the changes. The documentation should also describe what
* those changes were. This software may not be included in whole or in
* part into any commercial package without the express written consent of the
* author.  It may, however, be included in other public domain or freely
* distributed software so long as the proper credit for the software is given.
*
* This software is provided as is without any guarantees or warranty. Although
* the author has attempted to find and correct any bugs in the software, he
* is not responsible for any damage caused by the use of the software.  The
* author is under no obligation to provide service, corrections, or upgrades
* to this package.
*
* Despite all the legal stuff above, if you do find bugs, I would like to hear
* about them.  Also, if you have any comments or questions, you may contact me
* at the following address:
*
*     David Buck
*     22C Sonnet Cres.
*     Nepean Ontario
*     Canada, K2H 8W7
*
*  I can also be reached on the following bulleton boards:
*
*     OMX              (613) 731-3419
*     Mystic           (613) 596-4249  or  (613) 596-4772
*
*  Fidonet:   1:163/109.9
*  Internet:  dbuck@ccs.carleton.ca
*  The "You Can Call Me RAY" BBS    (708) 358-5611
*
*  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
*
*     The "You Can Call Me RAY" BBS (708) 358-5611
*     The Information Exchange BBS  (708) 945-5575
*
*****************************************************************************/

#include "frame.h"
#include "dkbproto.h"

FILE_HANDLE *Get_Dump_File_Handle()
   {
   FILE_HANDLE *handle;

   if ((handle = (FILE_HANDLE *) malloc(sizeof(FILE_HANDLE))) == NULL) {
      fprintf (stderr, "Cannot allocate memory for output file handle\n");
      return(NULL);
      }

   handle->Default_File_Name_p = Default_Dump_File_Name;
   handle->Open_File_p = Open_Dump_File;
   handle->Write_Line_p = Write_Dump_Line;
   handle->Read_Line_p = Read_Dump_Line;
   handle->Read_Image_p = Read_Dump_Image;
   handle->Close_File_p = Close_Dump_File;
   return (handle);
   }

char *Default_Dump_File_Name()
   {
   return ("data.dis");
   }

int Open_Dump_File (handle, name, width, height, buffer_size, mode)
   FILE_HANDLE *handle;
   char *name;
   int *width;
   int *height;
   int buffer_size;
   int mode;
   {
   int data1, data2;

   handle->mode = mode;
   handle->filename = name;

   switch (mode) {
      case READ_MODE:
         if ((handle->file = fopen (name, "rb")) == NULL) {
            return(0);
            }

         if (buffer_size != 0) {
            if ((handle->buffer = malloc (buffer_size)) == NULL)
               return(0);

            setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
            }

         if (((data1 = getc(handle->file)) == EOF)
             || ((data2 = getc(handle->file)) == EOF))
            return(0);

         *width  = data2 * 256 + data1;

         if (((data1 = getc(handle->file)) == EOF)
             || ((data2 = getc(handle->file)) == EOF))
            return(0);

         *height = data2 * 256 + data1;
         handle->width = *width;
         handle->height = *height;
         handle->buffer_size = buffer_size;
         break;

      case WRITE_MODE:
         if ((handle->file = fopen (name, "wb")) == NULL)
            return(0);

         if (buffer_size != 0) {
            if ((handle->buffer = malloc (buffer_size)) == NULL)
               return(0);

            setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
            }

         putc(*width % 256, handle->file);  /* write to either type of file */
         putc(*width / 256, handle->file);
         putc(*height % 256, handle->file);
         putc(*height / 256, handle->file);

         handle->width = *width;
         handle->height = *height;
         handle->buffer_size = buffer_size;

         break;

      case APPEND_MODE:
         if ((handle->file = fopen (name, "ab")) == NULL)
            return(0);

         if (buffer_size != 0) {
            if ((handle->buffer = malloc (buffer_size)) == NULL)
               return(0);

            setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
            }

         handle->buffer_size = buffer_size;
         break;
      }
   return(1);
   }

void Write_Dump_Line (handle, line_data, line_number)
   FILE_HANDLE *handle;
   COLOUR *line_data;
   int line_number;
   {
   register int x;

   putc(line_number % 256, handle->file);
   putc(line_number / 256, handle->file);

   for (x = 0 ; x < handle->width ; x++)
      putc((int) floor (line_data[x].Red * 255.0), handle->file);

   for (x = 0 ; x < handle->width ; x++)
      putc((int) floor (line_data[x].Green * 255.0), handle->file);

   for (x = 0 ; x < handle->width ; x++)
      putc((int) floor (line_data[x].Blue * 255.0), handle->file);

   if (handle->buffer_size == 0) {
      fflush(handle->file);                       /* close and reopen file for */
      handle->file = freopen(handle->filename, "ab",
                    handle->file);                /* integrity in case we crash*/
      }
   }

int Read_Dump_Line (handle, line_data, line_number)
   FILE_HANDLE *handle;
   COLOUR *line_data;
   int *line_number;
   {
   int data, i, c;

   if ((c = getc(handle->file)) == EOF) {
      return (0);
      }

   *line_number = c;

   if ((c = getc(handle->file)) == EOF)
      return (-1);

   *line_number += c*256;

   for (i = 0 ; i < handle->width ; i++) {
      if ((data = getc(handle->file)) == EOF)
         return(-1);

      line_data[i].Red = (DBL) data / 255.0;
      }

   for (i = 0 ; i < handle->width ; i++) {
      if ((data = getc(handle->file)) == EOF)
         return(-1);

      line_data[i].Green = (DBL) data / 255.0;
      }

   for (i = 0 ; i < handle->width ; i++) {
      if ((data = getc(handle->file)) == EOF)
         return(-1);

      line_data[i].Blue = (DBL) data / 255.0;
      }

   return (1);
   }

int Read_Dump_Int_Line (handle, line_data, line_number)
   FILE_HANDLE *handle;
   IMAGE_LINE *line_data;
   int *line_number;
   {
   int data, i, c;

   if ((c = getc(handle->file)) == EOF) {
      return (0);
      }

   *line_number = c;

   if ((c = getc(handle->file)) == EOF)
      return (-1);

   *line_number += c*256;

   if (((line_data->red = (unsigned char *) malloc(handle->width))==NULL) ||
       ((line_data->green = (unsigned char *) malloc(handle->width))==NULL) ||
       ((line_data->blue = (unsigned char *) malloc(handle->width))==NULL)) {
      fprintf (stderr, "Cannot allocate memory for picture: %s\n", handle->filename);
      close_all();
      exit(1);
      }

   for (i = 0 ; i < handle->width ; i++) {
      line_data->red[i] = 0;
      line_data->green[i] = 0;
      line_data->blue[i] = 0;
      }

   for (i = 0 ; i < handle->width ; i++) {
      if ((data = getc(handle->file)) == EOF)
         return(-1);

      line_data->red[i] = (unsigned short) data;
      }

   for (i = 0 ; i < handle->width ; i++) {
      if ((data = getc(handle->file)) == EOF)
         return(-1);

      line_data->green[i] = (unsigned short) data;
      }

   for (i = 0 ; i < handle->width ; i++) {
      if ((data = getc(handle->file)) == EOF)
         return(-1);

      line_data->blue[i] = (unsigned short) data;
      }

   return (1);
   }

void Close_Dump_File (handle)
   FILE_HANDLE *handle;
   {
   fclose (handle->file);
   if (handle->buffer_size != 0)
      free (handle->buffer);
   }

void Read_Dump_Image(Image, name)
   IMAGE *Image;
   char *name;
   {
   int rc, row, data1, data2;
   struct Image_Line line;
   FILE_HANDLE handle;

   if ((handle.file = Locate_File (name, "rb")) == NULL) {
      fprintf (stderr, "Cannot open dump file %s\n", name);
      close_all();
      exit(1);
      }

   if (((data1 = getc(handle.file)) == EOF)
       || ((data2 = getc(handle.file)) == EOF)) {

      fprintf (stderr, "Cannot open dump file %s\n", name);
      close_all();
      exit(1);
      }

   Image->iwidth  = data2 * 256 + data1;
   handle.width = Image->iwidth;

   if (((data1 = getc(handle.file)) == EOF)
       || ((data2 = getc(handle.file)) == EOF)) {

      fprintf (stderr, "Cannot open dump file %s\n", name);
      close_all();
      exit(1);
      }

   Image->iheight = data2 * 256 + data1;
   handle.height = Image->iheight;

   Image->width = (DBL)Image->iwidth;
   Image->height = (DBL)Image->iheight;

   Image->Colour_Map_Size = 0;
   Image->Colour_Map = NULL;

   if ((Image->data.rgb_lines = (struct Image_Line *)
          malloc(Image->iheight * sizeof (struct Image_Line))) == NULL) {
      fprintf (stderr, "Cannot allocate memory for picture: %s\n", name);
      exit(1);
      }

   while ((rc = Read_Dump_Int_Line(&handle, &line, &row)) == 1)
      Image->data.rgb_lines[row] = line;

   fclose (handle.file);

   if (rc == 0)
      return;
   else {
      close_all();
      exit(1);
      }
   }
