/*
 * MandelVroom 2.0
 *
 * (c) Copyright 1987,1989  Kevin L. Clague, San Jose, CA
 *
 * All rights reserved.
 *
 * Permission is hereby granted to distribute this program's source
 * executable, and documentation for non-comercial purposes, so long as the
 * copyright notices are not removed from the sources, executable or
 * documentation.  This program may not be distributed for a profit without
 * the express written consent of the author Kevin L. Clague.
 *
 * This program is not in the public domain.
 *
 * Fred Fish is expressly granted permission to distribute this program's
 * source and executable as part of the "Fred Fish freely redistributable
 * Amiga software library."
 *
 * Permission is expressly granted for this program and it's source to be
 * distributed as part of the Amicus Amiga software disks, and the
 * First Amiga User Group's Hot Mix disks.
 *
 * contents: this file contains the functions to save projects to disk,
 * load projects from disk, and save icon files (if the program was started
 * from the WorkBench.)
 */

#include "mandp.h"

extern struct NewScreen NewScreen;

extern ULONG CalcTime;

extern BYTE FromWB;

       ULONG BorderType;

USHORT  MandimageData1[] = {
 0xFFFF, 0xFFFF, 0xFFFF, 0xFFC0,
 0xFFFF, 0xFFFF, 0xFFFF, 0xFFC0,
 0xFFFF, 0xFFE3, 0xFFFF, 0xFFC0,
 0xFFFF, 0xF101, 0x67FF, 0xFFC0,
 0xFFF8, 0x7040, 0xC0F7, 0xFFC0,
 0xF9D4, 0x4441, 0x414B, 0xFFC0,
 0xF80F, 0x0F79, 0x8403, 0xFFC0,
 0xDA0F, 0xFFFF, 0xEC01, 0xFFC0,
 0x9743, 0xFFFF, 0xFE46, 0x0FC0,
 0x8FFF, 0xFFFF, 0xFF80, 0x3FC0,
 0xF03F, 0xFFEF, 0xFFC0, 0x7FC0,
 0xB7FF, 0xFE00, 0x3F91, 0xDFC0,
 0xFFFF, 0xF878, 0x3FC0, 0x07C0,
 0x8FFF, 0xF8F0, 0x7F80, 0x17C0,
 0xB7FF, 0xF0FF, 0xFFC0, 0x3FC0,
 0xFFFF, 0xF83F, 0xFC03, 0x7FC0,
 0xFFFF, 0xF70F, 0xD801, 0xFFC0,
 0xFFFF, 0xFE00, 0x0000, 0xFFC0,
 0xBFFF, 0xFE50, 0x415C, 0xFFC0,
 0xBFFF, 0xFFFC, 0x90FF, 0xFFC0,
 0xFFFF, 0xFFFD, 0xFEFF, 0xFFC0,
 0xFFFF, 0xFFFF, 0xFFFF, 0xFFC0,
/**/
 0x01E0, 0xE1F0, 0xFC03, 0xFE00,
 0x41E1, 0xC78F, 0xC03F, 0xF800,
 0x61C7, 0x2BDD, 0xE1FF, 0x0000,
 0x4394, 0x7FFF, 0xFD80, 0x0000,
 0x4C57, 0xFFBF, 0x7FFD, 0xFFC0,
 0x1FBB, 0xFFFF, 0xBFB4, 0x3FC0,
 0x6FF0, 0xFCCF, 0xFFFC, 0xC1C0,
 0x65F3, 0xF9C4, 0xB7FF, 0x9C00,
 0x79FF, 0x8F33, 0x6BBD, 0xFB00,
 0x70E7, 0xF136, 0x667F, 0xF9C0,
 0x4FE0, 0x19D4, 0x0D3F, 0xD8C0,
 0x4E9F, 0xC9FF, 0xC3EE, 0x3440,
 0x6580, 0x67D7, 0xECBF, 0xFB00,
 0x7A3E, 0x2FBF, 0x9EFF, 0xFF80,
 0x69FF, 0xCF2A, 0xA3FF, 0xF580,
 0x6700, 0x67E6, 0xC7FD, 0xB1C0,
 0x583F, 0x1AF4, 0xA7FF, 0xF3C0,
 0x31FF, 0xF5FF, 0xFFFF, 0x73C0,
 0x53E0, 0x1DAF, 0xFEA7, 0x23C0,
 0x4700, 0x00E7, 0xEF58, 0xE1C0,
 0x4E07, 0xFFE3, 0x77E3, 0xC1C0,
 0x383F, 0xFC00, 0x078F, 0x81C0,
/**/
 };

struct Image Mandimage1 = {
 0,  /* LeftEdge */
 0,  /* TopEdge */
 58,  /* Width */
 22,  /* Height */
 2,  /* Depth */
 (USHORT *)MandimageData1,  /* ImageData */
 0xFF,  /* PlanePick */
 0x0,  /* PlaneOnOff */
 0,  /* [NextImage] */
 };

struct DiskObject MandIcon = {
 WB_DISKMAGIC,   /* do_Magic */
 WB_DISKVERSION, /* do_Version */

/* Embedded Gadget Structure */
 0,  /* [NextGadget] */
 23,  /* LeftEdge */
 14,  /* TopEdge */
 58,  /* Width */
 23,  /* Height */
 0x5,  /* Flags */
 0x3,  /* Activation */
 0x1,  /* GadgetType */
 (APTR)&Mandimage1, /* GadgetRender */
 NULL,     /* SelectRender */
 NULL,     /* GadgetText */
 0x0,  /* MutualExclude */
 0x0,  /* [SpecialInfo] */
 0,  /* GadgetID */
 0x0,  /* [UserData] */

/* Rest of DiskObject structure */
 0x4,  /* do_Type */
 "MandelBrot:MandelVroom",   /* do_Default Tool */
 0x0,  /* [do_ToolTypes] */
 0x80000000,  /* do_CurrentX */
 0x80000000,  /* do_CurrentY */
 0x0,  /* [do_DrawerData] */
 0x0,  /* [do_ToolWindow] */
 10240 /* do_StackSize */
 };

USHORT  JuliaimageData1[] = {
 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
 0x0000, 0x0000, 0x0F80, 0x0000, 0x0000,
 0x0000, 0x0000, 0x7F60, 0x0000, 0x0000,
 0x0000, 0x000F, 0xF07E, 0x0000, 0x0000,
 0x0000, 0x0079, 0xC071, 0xC000, 0x0000,
 0x0004, 0xFFDB, 0xFFFE, 0xFC00, 0x0000,
 0x001C, 0x6FDF, 0xFFFF, 0xFF7D, 0x0000,
 0x00FF, 0xF183, 0xFFE0, 0x73C3, 0xC000,
 0x05FF, 0xF100, 0x7FE0, 0xC3FF, 0xFC00,
 0x33C3, 0xFC00, 0x7FFE, 0x007C, 0x6D80,
 0x1F85, 0xF800, 0xFFF8, 0x007F, 0x0670,
 0x03F1, 0xFC06, 0x3FF0, 0x01FE, 0x03E0,
 0x003B, 0xFF98, 0x0FF0, 0x021F, 0xDF80,
 0x000F, 0x187C, 0x3FFF, 0xE6FE, 0xB000,
 0x0003, 0xFFFD, 0xFFFF, 0xDFC1, 0xC000,
 0x0000, 0x003E, 0x7FDF, 0x7FFF, 0x0000,
 0x0000, 0x0006, 0x785B, 0x6000, 0x0000,
 0x0000, 0x0000, 0xFC7E, 0x0000, 0x0000,
 0x0000, 0x0000, 0x1BF0, 0x0000, 0x0000,
 0x0000, 0x0000, 0x0380, 0x0000, 0x0000,
 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/**/
 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
 0x0000, 0x0000, 0x0D80, 0x0000, 0x0000,
 0x0000, 0x0000, 0x70E0, 0x0000, 0x0000,
 0x0000, 0x000F, 0xFFFE, 0x0000, 0x0000,
 0x0000, 0x007E, 0x3F8F, 0xC000, 0x0000,
 0x0007, 0xFFF4, 0x0001, 0xFC00, 0x0000,
 0x001F, 0x93E0, 0x0000, 0xFFF3, 0x0000,
 0x00F0, 0x0FFC, 0x001F, 0xFC3D, 0xC000,
 0x0660, 0x0FFF, 0x801F, 0xFC00, 0x7C00,
 0x2C7C, 0x1FFF, 0x9FFF, 0xFF83, 0xF380,
 0x1C7E, 0x07FF, 0xFFFF, 0xFF83, 0xF990,
 0x03FE, 0x03FF, 0xFF8F, 0xFFC1, 0xFC60,
 0x003C, 0x007F, 0xF00F, 0xFFE0, 0x3F80,
 0x000F, 0xE7FB, 0xC000, 0x1F03, 0x7000,
 0x0002, 0xFFFE, 0x0000, 0x3FFE, 0xC000,
 0x0000, 0x003F, 0x80A1, 0xFFFF, 0x0000,
 0x0000, 0x0007, 0xC7E6, 0xE000, 0x0000,
 0x0000, 0x0000, 0xFFBE, 0x0000, 0x0000,
 0x0000, 0x0000, 0x1C70, 0x0000, 0x0000,
 0x0000, 0x0000, 0x0280, 0x0000, 0x0000,
 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/**/
 };

struct Image Juliaimage1 = {
 0,  /* LeftEdge */
 0,  /* TopEdge */
 78,  /* Width */
 22,  /* Height */
 2,  /* Depth */
 (USHORT *)JuliaimageData1,  /* ImageData */
 0xFF,  /* PlanePick */
 0x0,  /* PlaneOnOff */
 0,  /* [NextImage] */
 };

struct DiskObject JuliaIcon = {
 WB_DISKMAGIC,   /* do_Magic */
 WB_DISKVERSION, /* do_Version */

/* Embedded Gadget Structure */
 0,  /* [NextGadget] */
 23,  /* LeftEdge */
 14,  /* TopEdge */
 78,  /* Width */
 23,  /* Height */
 0x5,  /* Flags */
 0x3,  /* Activation */
 0x1,  /* GadgetType */
 (APTR)&Juliaimage1, /* GadgetRender */
 NULL,     /* SelectRender */
 NULL,     /* GadgetText */
 0x0,  /* MutualExclude */
 0x0,  /* [SpecialInfo] */
 0,  /* GadgetID */
 0x0,  /* [UserData] */

/* Rest of DiskObject structure */
 0x4,  /* do_Type */
 "MandelBrot:MandelVroom",   /* do_Default Tool */
 0x0,  /* [do_ToolTypes] */
 0x80000000,  /* do_CurrentX */
 0x80000000,  /* do_CurrentY */
 0x0,  /* [do_DrawerData] */
 0x0,  /* [do_ToolWindow] */
 10240 /* do_StackSize */
 };

/*
 * Save all the data needed to restore the system to current state.
 */
int
SaveCounts(SaveName, Pict)
  register char *SaveName;
  register struct Picture *Pict;
{
  register FILE  *SaveFile;

  USHORT ViewModes;
  UBYTE  Depth;
  ULONG  Version = VERSION;
  char   ErrMsg[80];

  /*
   * Change the mouse pointer to Sleepy pointer
   */
  SetSleepyPointer();

  /*
   * open the desired file for writing
   */
  SaveFile = fopen(SaveName,"w");

  if (SaveFile == (FILE *) NULL) {
    sprintf(ErrMsg, "Can't open file %s", SaveName);
    DispErrMsg(ErrMsg, 0);
    return(UNSUCCESSFUL);
  }

  Pict->LeftEdge = Pict->Window->LeftEdge;
  Pict->TopEdge  = Pict->Window->TopEdge;

  /*
   * if there is data to save, save it
   */
  if (Pict->Counts && ! (Pict->Flags & NO_RAM_GENERATE) ) {

    if (Pict->pNode.ln_Type == MANDPICT) {

      /*
       * Put out the file header
       */
      fwrite((char *) "MAN4",    4,  1, SaveFile);
    } else {

      /*
       * Put out the file header
       */
      fwrite((char *) "JUL4",    4,  1, SaveFile);
    }

    /*
     * Put out the revision number
     */
    fwrite((char *) Version,   sizeof(Version), 1, SaveFile);

    if (Pict->pNode.ln_Type == JULIAPICT) {

      /*
       * Put out the Julia point
       */
      fwrite((char *) &Pict->Real,   sizeof(double),   1, SaveFile);
      fwrite((char *) &Pict->Imag,   sizeof(double),   1, SaveFile);
    }

    /*
     * Put out the location on the complex plane
     */
    fwrite((char *) &Pict->RealLow,   sizeof(double),   1, SaveFile);
    fwrite((char *) &Pict->ImagLow,   sizeof(double),   1, SaveFile);
    fwrite((char *) &Pict->RealHigh,  sizeof(double),   1, SaveFile);
    fwrite((char *) &Pict->ImagHigh,  sizeof(double),   1, SaveFile);

    /*
     * Put out the Maximum iteration count for a given point
     */
    fwrite((char *) &Pict->MaxIteration, sizeof(SHORT),    1, SaveFile);

    /*
     * Put out the generator type
     */
    fwrite((char *) &Pict->MathMode, sizeof(Pict->MathMode), 1, SaveFile);

    /*
     * Put out the time it took to generate
     */
    fwrite((char *) &CalcTime, sizeof(CalcTime), 1, SaveFile);

    /*
     * Put out the screen's viewmodes
     */
    ViewModes = NewScreen.ViewModes;
    fwrite((char *) &ViewModes, sizeof(ViewModes), 1, SaveFile);

    /*
     * Put out the number of bit planes
     */
    Depth = NewScreen.Depth;
    fwrite((char *) &Depth, sizeof(Depth), 1, SaveFile);

    /*
     * Put some window flags
     */
    fwrite((char *) &BorderType, sizeof(BorderType), 1, SaveFile);

    /*
     * Save the Color Palette
     */
    fwrite((char *) &Pict->RGBs, sizeof(Pict->RGBs), 1, SaveFile);

    /*
     * Save the number of contours
     */
    fwrite((char *) &NumContours, sizeof(NumContours), 1, SaveFile);

    /*
     * Save the contour's heights
     */
    fwrite((char *) Pict->Heights, sizeof(SHORT), (int) NumContours, SaveFile);

    /*
     * Save the contour's pen numbers (Color is a misnomer)
     */
    fwrite((char *) Pict->Pens, sizeof(UBYTE), (int) NumContours, SaveFile);

    /*
     * Put out the image dimensions
     */
    fwrite((char *) &Pict->CountX,   sizeof(SHORT),   1, SaveFile);
    fwrite((char *) &Pict->CountY,   sizeof(SHORT),   1, SaveFile);

    /*
     * Put out project's position
     */
    fwrite((char *) &Pict->LeftEdge, sizeof(Pict->LeftEdge), 1, SaveFile);
    fwrite((char *) &Pict->TopEdge,  sizeof(Pict->TopEdge),  1, SaveFile);
    fwrite((char *) &Pict->CurLine,  sizeof(Pict->CurLine),  1, SaveFile);

    (void) WriteRLLTwo( SaveFile, Pict );

  } else {
    DispErrMsg("No Picture to save",0);
    fclose(SaveFile);
    return(UNSUCCESSFUL);
  }

  fclose(SaveFile);

  if (FromWB) {

    FILE *IconFile;
    char IconName[80];

    strcpy( IconName, SaveName );
    strcat( IconName, ".info" );

    if ((IconFile = fopen( IconName, "r" )) == NULL) {

      /*
       * OutPut an icon for the saved picture
       */
      if (Pict->pNode.ln_Type == MANDPICT)
        (void) PutDiskObject(SaveName,&MandIcon);
      else
        (void) PutDiskObject(SaveName,&JuliaIcon);

    } else {
      fclose( IconFile );
    }
  }

  return(SUCCESSFUL);
} /* SaveCounts */

int
WriteRLLTwo( SaveFile, Pict )
  register FILE *SaveFile;
  register struct Picture *Pict;
{

  LONG Words;

  Words = Compress( Pict );

  fwrite( (char *) &Words, sizeof(LONG), 1, SaveFile);

  /* in case I ever recompile into 16 bit ints */

  if (sizeof(int) == 2 && sizeof(int)*Words > 65535) {
    DispErrMsg("Programming error in Savemand\n", 0);
    return(UNSUCCESSFUL);
  }

  fwrite( (char *) Pict->Counts, (int) (sizeof(SHORT) * Words), 1, SaveFile);

  Decompress( Words, Pict );
  return( SUCCESSFUL );
}

/* Compress the data.  Count up how many words in a row have the same value.
 * If the count is only one, then just put the data in the compressed array.
 * Otherwise, turn on the most significant bit in the Count, and put it
 * in the compressed array, then put the potential in the array.
 *
 * Advantages:
 * -  Compressed data guaranteed to be as small or smaller than uncompressed
 *    data.
 * -  Compression can be done in place in memory, so it is fast without
 *    requiring extra memory.
 * -  Once compressed, the data can be written to disk with one fwrite,
 *    therefore it should be quicker than previously used method that
 *    compressed and wrote to disk at the same time.
 * -  Maximum iteration count for Mandelbrot potential is 32767. The
 *    previous method only allowed 1023.
 */
int
Compress( Pict )
  register struct Picture *Pict;
{
  register SHORT *CountPtr,*CompressPtr;
  register SHORT  Count;
  register USHORT Cur;
  register ULONG  i;
  register ULONG  Word = 0;

  i = Pict->CountsSize/sizeof(SHORT);

  CountPtr = CompressPtr = Pict->Counts;
  Cur = *CountPtr;
  Count = 1;

  while (--i) {
    CountPtr++;

    /*
     * Count up how many in a row have same height
     */
    if (Cur == *CountPtr) {
      Count++;
    } else {
      if ( Count > 1 ) {
        *CompressPtr++ = Count | 0x8000;
      }
      *CompressPtr++ = Cur;
      Count = 1;
      Cur = *CountPtr;
    }
  }

  if ( Count > 1 ) {
    *CompressPtr++ = Count | 0x8000;
  }
  *CompressPtr++ = Cur;

  Word = CompressPtr - Pict->Counts;

  return( Word );
}

/*
 * Load the state of the program from file
 */
int
LoadCounts(LoadName, Pict )
  register char *LoadName;
  register struct Picture *Pict;
{
  register FILE  *LoadFile;
  USHORT ViewModes;
  UBYTE  Depth;
  char   Header[5];
  ULONG  Version;
  char   ErrMsg[80];
  int    rc;
  char  *File, *ExtractName();

  extern int Num_vp_Colors;
  extern USHORT NewViewModes;
  extern UBYTE  NewDepth;

  extern struct MathTransBase *MathTransBase;
  extern LONG   SPTIEEE;

  /*
   * Change the mouse pointer to Sleepy pointer
   */

  SetSleepyPointer();

  LoadFile = fopen(LoadName,"r");

  Pict->GenState = FINISHEDSTATE;

  if (LoadFile == (FILE *) NULL) {

    /*
     * can't read a non-existant file
     */
    sprintf(ErrMsg, "File %s not found", LoadName);
    DispErrMsg(ErrMsg, 0);
    return( UNSUCCESSFUL );
  }

  /*
   * Read and check the file header
   */
  (void) fread((char *) &Header[0], 4, 1, LoadFile);
  Header[4] = '\0';

  if (strcmp(&Header[0], "MAND") != 0 &&
      strcmp(&Header[0], "MAN1") != 0 &&
      strcmp(&Header[0], "MAN2") != 0 &&
      strcmp(&Header[0], "MAN3") != 0 &&
      strcmp(&Header[0], "MAN4") != 0 &&
      strcmp(&Header[0], "JUL3") != 0 &&
      strcmp(&Header[0], "JUL4") != 0    ) {

    /*
     * File of improper format
     */
    sprintf(ErrMsg, "File %s is not a MAND file",LoadName);
    DispErrMsg(ErrMsg, 0);
    fclose(LoadFile);
    return( UNSUCCESSFUL );
  }

  /*
   * Read in the version
   */
  (void) fread((char *) &Version, sizeof(Version), 1, LoadFile);

  if ( strcmp( &Header[0], "MAN2") == 0 ||
       strcmp( &Header[0], "MAN3") == 0 ||
       strcmp( &Header[0], "MAN4") == 0 ||
       strcmp( &Header[0], "JUL3") == 0 ||
       strcmp( &Header[0], "JUL4") == 0 ) {

    if ( strcmp( &Header[0], "JUL3") == 0 ||
         strcmp( &Header[0], "JUL4") == 0 ) {

      Pict->pNode.ln_Type = JULIAPICT;
      (void) fread((char *) &Pict->Real, sizeof(double), 1, LoadFile);
      (void) fread((char *) &Pict->Imag, sizeof(double), 1, LoadFile);
    } else {
      Pict->pNode.ln_Type = MANDPICT;
    }

    /*
     * Read in the location in the complex plane
     */
    (void) fread((char *) &Pict->RealLow,  sizeof(double), 1, LoadFile);
    (void) fread((char *) &Pict->ImagLow,  sizeof(double), 1, LoadFile);
    (void) fread((char *) &Pict->RealHigh, sizeof(double), 1, LoadFile);
    (void) fread((char *) &Pict->ImagHigh, sizeof(double), 1, LoadFile);
  } else {

    /* Must be old FFP code */

    LONG startx, starty, endx, endy;

    LONG SPTieee();

    /*
     * Read in the FFP form of location in the complex plane
     */
    (void) fread((char *) &startx, sizeof(LONG), 1, LoadFile);
    (void) fread((char *) &starty, sizeof(LONG), 1, LoadFile);
    (void) fread((char *) &endx,   sizeof(LONG), 1, LoadFile);
    (void) fread((char *) &endy,   sizeof(LONG), 1, LoadFile);

    /*
     * Convert it to IEEE format
     */
    if (OpenFFPLibs() != 0)
      return(UNSUCCESSFUL);

    startx = SPTieee( startx );
    starty = SPTieee( starty );
    endx   = SPTieee( endx );
    endy   = SPTieee( endy );

    /*
     * promote them to doubles
     */
    Pict->RealLow  = (double) *( (float *) &startx );
    Pict->ImagLow  = (double) *( (float *) &starty );
    Pict->RealHigh = (double) *( (float *) &endx );
    Pict->ImagHigh = (double) *( (float *) &endy );
  }

  /*
   * Read in the maximum iteration count for a given point
   */
  (void) fread((char *) &Pict->MaxIteration, sizeof(SHORT), 1, LoadFile);

  /*
   * Read in the generator type
   */
  (void) fread((char *) &Pict->MathMode, sizeof(Pict->MathMode), 1, LoadFile);

  /*
   * Read in the calculation time
   */
  (void) fread((char *) &CalcTime, sizeof(CalcTime), 1, LoadFile);

  /*
   * Read in the screen's viewmodes
   */
  (void) fread((char *) &ViewModes, sizeof(ViewModes), 1, LoadFile);

  ViewModes &= HIRES | INTERLACE | EXTRA_HALFBRITE;
  Pict->ViewModes = ViewModes;

  /*
   * Read in the number of bit planes
   */
  (void) fread((char *) &Depth, sizeof(Depth), 1, LoadFile);
  Pict->Depth = Depth;

  /*
   * Read in the window flags
   */
  (void) fread((char *) &BorderType, sizeof(BorderType), 1, LoadFile);

  /*
   * Read in the color palette information
   */
  (void) fread((char *) &Pict->RGBs[0], sizeof(Pict->RGBs), 1, LoadFile);

  /*
   * Read in the number of contours
   */
  (void) fread((char *) &NumContours, sizeof(NumContours), 1, LoadFile);

  /*
   * Read in the heights
   */
  (void) fread((char *) Pict->Heights, sizeof(SHORT), NumContours, LoadFile);

  /*
   * Read in the pen numbers (Color is a misnomer)
   */
  (void) fread((char *) Pict->Pens, sizeof(UBYTE), NumContours, LoadFile);

  for ( ; NumContours < NUMCONTS; NumContours++ ) {
    *(Pict->Heights + NumContours) = 0;
    *(Pict->Pens + NumContours) = 0;
  }

  /*
   * Read in the image dimensions
   */
  (void) fread((char *) &Pict->CountX,   sizeof(SHORT),  1, LoadFile);
  (void) fread((char *) &Pict->CountY,   sizeof(SHORT),  1, LoadFile);

  if ( strcmp( &Header[0], "MAN4") == 0 ||
       strcmp( &Header[0], "JUL4") == 0 ) {

    /*
     * Read in the image dimensions
     */
    (void) fread((char *) &Pict->LeftEdge, sizeof(Pict->LeftEdge),
                                           1, LoadFile);
    (void) fread((char *) &Pict->TopEdge,  sizeof(Pict->TopEdge),
                                           1, LoadFile);
    (void) fread((char *) &Pict->CurLine,  sizeof(Pict->CurLine),
                                           1, LoadFile);
    if (Pict->CurLine > Pict->CountY)
      Pict->CurLine -= TOPMARG;

  } else {
    Pict->CurLine = Pict->CountY;
  }

  GetCountsMemory( Pict );

  if (Pict->Counts == (SHORT *) NULL || (Pict->Flags & NO_RAM_GENERATE)) {
    DispErrMsg("Can't load counts. Out of RAM!!",0);
    fclose(LoadFile);
    return( UNSUCCESSFUL );
  }

  if ( strcmp( &Header[0], "MAN3") == 0 ||
       strcmp( &Header[0], "MAN4") == 0 ||
       strcmp( &Header[0], "JUL3") == 0 ||
       strcmp( &Header[0], "JUL4") == 0 ) {

    rc = ReadRLLTwo( LoadFile, Pict );
  } else {
    rc = ReadRLLOne( LoadFile, Pict );
  }
  fclose(LoadFile);

  if (rc != SUCCESSFUL) {
    return( rc );
  }

  File = ExtractName( LoadName );
  strncpy( Pict->Title, "  ", 2);
  strncat( Pict->Title, File, sizeof(Pict->Title)-3);

  CalculateGaps( Pict );

  NewViewModes = Pict->ViewModes;
  NewDepth     = Pict->Depth;

  if ( MaybeNewScreen() == 0 ) {

    /*
     * Let's show it to them
     */
    if (OpenPicture( Pict ) != 0) {

      return( UNSUCCESSFUL );

    } else {
      LoadRGB4( vp, Pict->RGBs, Num_vp_Colors );
      ReColor( Pict );
    }
  }

  GetCurPict();

  if (CurPict) {
    LoadRGB4( vp, CurPict->RGBs, Num_vp_Colors );
  }
  InitBorderSubs();

  return( SUCCESSFUL );
} /* LoadCounts */

/* Load count information in pseudo RLL format */
/* Bits 9-0 are iteration count.               */
/* Bits 15-10 are how many iteration count of same height in a row */

int
ReadRLLOne( LoadFile, Pict )
  register FILE *LoadFile;
  register struct Picture *Pict;
{
  register SHORT *CountPtr;
  register LONG   i;
  register ULONG  Count = 0;

  USHORT t;

  CountPtr = Pict->Counts;

  i = Pict->CountsSize / sizeof( SHORT );

  while (i > 0) {
    if ( fread((char *) &t, sizeof(t), 1, LoadFile) == 0) {
      DispErrMsg("Premature EOF on source file",0);
      fclose(LoadFile);
      return( UNSUCCESSFUL);
    }
    Count = t >> 10;
    t = t & 0x3ff;

    for (; Count > 0; Count--) {
     *(CountPtr++) = t;
      i--;
    }
  }
  return( SUCCESSFUL );
}

int
ReadRLLTwo( LoadFile, Pict )
  register FILE *LoadFile;
  register struct Picture *Pict;
{
  LONG Words;

  if (fread((char *) &Words, sizeof(Words), 1, LoadFile) == 0) {
    DispErrMsg("Premature EOF on source file",0);
    fclose(LoadFile);
    return(UNSUCCESSFUL);
  }
  if (fread((char *) Pict->Counts,(int)(sizeof(SHORT)*Words),1,LoadFile) == 0){
    DispErrMsg("Premature EOF on source file",0);
    fclose(LoadFile);
    return(UNSUCCESSFUL);
  }
  Decompress( Words, Pict );
  return( SUCCESSFUL );
}

/* This algorithm decompresses the data.  The data array has
 * been malloced large enough to hold the decompressed data.  The data
 * is read from the disk into the array in compressed format.  This
 * decompresses the data in place.  The data must be decompressed from the
 * back to the front.
 */
Decompress( Word, Pict )
  LONG  Word;
  struct Picture *Pict;
{
  register SHORT *CountPtr, *CompressPtr;
  register SHORT  Count,Cur;
  register LONG   i;
  register SHORT  j;

  /* Point to the last word of compressed data */

  CompressPtr = Pict->Counts + Word - 1;

  i = Pict->CountsSize/sizeof(SHORT);

  /* Point to the last word of uncompressed data */

  CountPtr = Pict->Counts + i - 1;

  /* While there is data to uncompress.... */

  while (i > 1 && CountPtr >= Pict->Counts && CompressPtr >= Pict->Counts) {

    /* Pick up the last two words */

    Cur   = *CompressPtr--;
    Count = *CompressPtr;

    if (Count & 0x8000) {        /* is it compressed? */

      Count &= 0x7fff;           /* extract count */

      for ( j = 0; j < Count; j++) {  /* Decompress it */
        *CountPtr-- = Cur;
        i--;
      }
      CompressPtr--;

    } else {

      *CountPtr-- = Cur;         /* just move it */
      i--;
    }
  }
}
