/* static char szModuleName__[] = "c:/unix/newer/fil.c"; jmh 29 May 2001 */
/* static char szLastVersion[] = "Version 0.5"; jmh 29 May 2001 */
/* static char szLastSave[] = "1994-11-17*11:16"; jmh 29 May 2001 */

/*-----------------------------------------------------------
-- Filepackage                      File: Fil.c
--
-- Rev
--    990125	 ARG, Modified entry names to avoid collision w. filep
--    970908     ARG, static added to putvaxfloat, getvaxfloat
--    941002     ARG, FileMode added in fpopen
--    940707     ARG, *Length used instead of AttrSize in memcpy in fpReadAttr
--    940704     ARG, INT32 instead of int
--    940524     CFR, ReturnCodes checked at fpClose
--    940510     CFR, File offset Compensation removed
--    940315     CFR, Converted from Filb.ada
--
--
-- Purpose:
-- The File package for writing/reading the binary representation
-- of the Attributes to/from file.
--
-- The definitions of the fields are reflected in rr_fil.h
--
-----------------------------------------------------------                 */

#ifdef   VAXC
#include <types.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#else
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <math.h>
#endif
#include "fil.h"
#include "rr_fil.h"
#define  FI_GENERAL_ERROR -1
#define  FI_ATTRIBUTE_NOT_FOUND_ERROR -2
#define  FI_UNKNOWN_IDENTITY_ERROR -3
#define  FI_BLOCKSIZE  512
#define  IDENTSIZE     sizeof(IdentArea_t)
static void fiConvertFile2CAttr(unsigned char *pAttr,INT32 AttrSize,
                                AttrTyp_t Type,INT32 *Retcode);

static void fiConvertC2FileAttr(unsigned char *pBuff,Attr_t *pAttr,AttrTyp_t
                                Type,INT32 Len,INT32 *Retcode);

static short GetVAX16(unsigned char p[]);
static long GetVAX32(unsigned char p[]);
static float GetVAXFloat(unsigned char *p);
static void PutVAX16(unsigned char p[],unsigned short value);
static void PutVAX32(unsigned char p[],unsigned long value);
static void PutVAXFloat(unsigned char p[],float value);

/* ------------------------------------------------------------
   -- fiCreate
   -- 
   -- Description
   -- 
   -- Parameters
   -- 
   ----------------------------------------------------------               */

void fiCreate(Fil_t *F,char *Name,INT32 AttrSize,INT32 DataSize,INT32 
              *Retcode)
{
  INT32 Byte,Count;
  IdentArea_t Id;

  if ((F->fp = fopen(Name, 
                     "wb")) == NULL)
    {

      /**********************************************************************/
      /* perror("Could not open Nordrad file \n");                          */
      /**********************************************************************/

      *Retcode = FI_GENERAL_ERROR;
      return ;
    } 
  F->Opened = 1;
  strcpy(F->Name, 
         Name);
  F->AttrSize = AttrSize-IDENTSIZE;
  F->Blocks = AttrSize/FI_BLOCKSIZE;
  F->DataSize = DataSize;
  F->Allocated = (F->AttrSize)+IDENTSIZE;
  memcpy(Id.SysName, 
         "NORDRAD_RR", 
         10);
  Id.Version = 2;
  Id.Size = AttrSize/FI_BLOCKSIZE;     /* blocks                            */
  fwrite(&Id, 
         IDENTSIZE, 
         1, 
         F->fp);
  Byte = 0;

  /**************************************************************************/
  /* clear attributes                                                       */
  /**************************************************************************/

  for (Count = 0; Count < AttrSize; Count++)
    fwrite(&Byte, 
           1, 
           1, 
           F->fp);

  /**************************************************************************/
  /* write a byte at last position, allocates a file big enough not used    */
  /* fseek(F->fp,(AttrSize)+DataSize-1,SEEK_SET); fwrite(&Byte,1,1,F->fp);  */
  /**************************************************************************/

  fseek(F->fp, 
        0L, 
        SEEK_SET);
  fclose(F->fp);
  F->Opened = 0;                       /* treat as closed                   */
  fiOpen(F, 
         UpdateMode, 
         Retcode);                     /* but open it                       */
} 


/* ------------------------------------------------------------
   -- Open
   -- 
   -- Description
   -- 
   -- Parameters
   --
   ----------------------------------------------------------               */

void fiOpen(Fil_t *F,FileMode_t FileMode,INT32 *Retcode)
{
  IdentArea_t Id;
  INT32 AttrSize;

  if (F->Opened)
    {                                  /* already open                      */
      *Retcode = 1;
      return ;
    } 
  if (FileMode == UpdateMode)
    {
#ifdef   VMS
      F->fp = fopen(F->Name, 
                    "r+b", 
                    "ctx=stm");
#else
      F->fp = fopen(F->Name, 
                    "r+b");
#endif
    }                                  /* if (FileMode == UpdateMode )      */
  else
    {
#ifdef   VMS
      F->fp = fopen(F->Name, 
                    "rb", 
                    "ctx=stm");
#else
      F->fp = fopen(F->Name, 
                    "rb");
#endif
    }                                  /* NOT if (FileMode == UpdateMode )  */
  if (F->fp == NULL)
    {

      /**********************************************************************/
      /* perror("Could not open Nordrad pic file\n");                       */
      /**********************************************************************/

      fiClose(F, 
              Retcode);
      *Retcode = FI_GENERAL_ERROR;
      return ;
    } 
  F->Opened = 1;
  fread(&Id, 
        IDENTSIZE, 
        1, 
        F->fp);
  if (memcmp(Id.SysName, 
             "NORDRAD_RR", 
             10) != 0)
    {

      /**********************************************************************/
      /* perror("Seems that File is not a Nordrad file \n");                */
      /**********************************************************************/

      fiClose(F, 
              Retcode);
      *Retcode = FI_UNKNOWN_IDENTITY_ERROR;
      return ;
    } 
  F->AttrBuf = (char *)malloc(FI_BLOCKSIZE *Id.Size);
  F->Blocks = Id.Size;
  if (F->AttrBuf == NULL)
    {
      *Retcode = FI_GENERAL_ERROR;
      fiClose(F, 
              Retcode);
      return ;
    } 
  AttrSize = (Id.Size *FI_BLOCKSIZE)-IDENTSIZE;
  F->AttrSize = AttrSize;
  F->Allocated = AttrSize+IDENTSIZE;
  memset(F->AttrBuf, 
         0, 
         AttrSize);
  fread(F->AttrBuf, 
        AttrSize, 
        1, 
        F->fp);
  *Retcode = 1;
} 


/* ------------------------------------------------------------
   -- 
   -- 
   -- Description
   -- 
   -- Parameters
   --
   ----------------------------------------------------------               */

void fiClose(Fil_t *F,INT32 *Retcode)
{
  if (F->fp == NULL)
    {
      *Retcode = FI_GENERAL_ERROR;
      return ;
    } 
  if (fclose(F->fp) != 0)
    {
      *Retcode = FI_GENERAL_ERROR;
      return ;
    } 
  F->Opened = 0;
  if (F->AttrBuf != NULL)
    free(F->AttrBuf);
  F->AttrBuf = NULL;
  F->fp = NULL;
  *Retcode = 1;
} 


/* ------------------------------------------------------------
   -- 
   -- 
   -- Description
   -- 
   -- Parameters
   --
   ----------------------------------------------------------               */

void fiDelete(Fil_t *F,INT32 *Retcode)
{
  fiClose(F, 
          Retcode);
  if (*Retcode == 1)
    remove(F->Name);
} 


/* ------------------------------------------------------------
   -- 
   -- 
   -- Description
   -- 
   -- Parameters
   --
   ----------------------------------------------------------               */

void fiAllocate(Fil_t *F,INT32 Size,INT32  *Offset,INT32 *Retcode)
{
  *Offset = F->Allocated;
  F->Allocated = F->Allocated+Size;
  *Retcode = 1;
} 


/* ------------------------------------------------------------
   -- 
   -- 
   -- Description
   -- 
   -- Parameters
   --
   ----------------------------------------------------------               */

void fiCopy_Header(Fil_t *From_F,Fil_t *To_F,INT32 *Retcode)
{
  INT32 Ret;
  IdentArea_t Id;

  fiOpen(From_F, 
         InputMode, 
         &Ret);
  fiOpen(To_F, 
         UpdateMode, 
         &Ret);
  if (From_F->AttrSize != To_F->AttrSize)
    {
      *Retcode = FI_GENERAL_ERROR;
      return ;
    } 
  fseek(From_F->fp, 
        0L, 
        SEEK_SET);
  fseek(To_F->fp, 
        0L, 
        SEEK_SET);
  Id.Size = From_F->Blocks;
  Id.Version = 2;
  memcpy(Id.SysName, 
         "NORDRAD_RR", 
         10);
  fwrite(&Id, 
         IDENTSIZE, 
         1, 
         To_F->fp);
  memcpy(To_F->AttrBuf, 
         From_F->AttrBuf, 
         From_F->AttrSize);
  fwrite(From_F->AttrBuf, 
         From_F->AttrSize, 
         1, 
         To_F->fp);
  *Retcode = 1;
} 

void fiGetName(Fil_t *Fil,char *pname,INT32 *Retcode)
{
  strcpy(pname, 
         Fil->Name);
  *Retcode = 1;
} 


/* ------------------------------------------------------------
   -- 
   -- 
   -- Description
   -- 
   -- Parameters
   --
   ----------------------------------------------------------               */
/*
   ------------------------------------------------------------
   -- Generic attribute handling.
   ------------------------------------------------------------
                                                                            */

void fiReadAttr(Fil_t *F,Attr_t *Attr,AttrTyp_t Type,INT32 *Length,INT32 
                *Retcode)
{
  INT32 NotFound = 1;
  INT32 AttrSize;
  unsigned char *p;
  Attr_t *pAttr;
  unsigned char Byte;

  if (!F->Opened)
    {
      fiOpen(F, 
             InputMode, 
             Retcode);
      if (*Retcode < 0)
        return ;
    } 
  p = (unsigned char *)F->AttrBuf;
  while (NotFound && ((p-(unsigned char *)F->AttrBuf < F->AttrSize)))
    {
      pAttr = (Attr_t *)p;
      Byte = *p;
      Byte = Byte&0x7F;                /* Mask bits 0-6                     */
      AttrSize = *(p+1)<<1;
      AttrSize = AttrSize+(*p>>7);
      if (Byte == 0)
        {
          *Retcode = FI_ATTRIBUTE_NOT_FOUND_ERROR;
          return ;
        } 
      if (Byte == Type)
        {
          pAttr = (Attr_t *)(p+2);
          NotFound = 0;

          /******************************************************************/
          /* Size = Bit 7 + bit 0-7 of next byte                            */
          /******************************************************************/

          *Length = AttrSize-2;        /* Do not count length and size part */
          memcpy(Attr->buff, 
                 pAttr->buff, 
                 *Length);
          fiConvertFile2CAttr(&(Attr->buff[0]), 
                              *Length, 
                              Type, 
                              Retcode);
          return ;
        } 
      else
        {                              /* position to next attribute        */

          /******************************************************************/
          /* Size = Bit 6-7 + bit 0-7 of next byte                          */
          /******************************************************************/

          p = p+(AttrSize);
        } 
    } 
  *Retcode = -2;
} 


/* ------------------------------------------------------------
   -- 
   -- 
   -- Description Converts from VAX File format to C-Structures.
   -- 
   -- Parameters
   --
   ----------------------------------------------------------               */

static void fiConvertFile2CAttr(unsigned char *pAttr,INT32 AttrSize,
                                AttrTyp_t Type,INT32 *Retcode)
{
  Pixel_t Pixel,*pp;
  Bitmap_t BitMap,*pb;
  AreaDef_t AreaDef,*pa;
  IntStore_t IntStoreDef,*pi;
  Z_To_R_Constants_t Z_To_R,*pz;
  Resolution_t ResolutionDef,*pr;
  Quantity_t QuantityDef,*pq;
  RrTyp_t RrTypeDef,*prr;
  typedef struct
    {
      unsigned char a[100];
    } 
  ByteArray;
  ByteArray *p;

  p = (ByteArray *)pAttr;
  pp = (Pixel_t *)pAttr;
  pb = (Bitmap_t *)pAttr;
  pa = (AreaDef_t *)pAttr;
  pi = (IntStore_t *)pAttr;
  pr = (Resolution_t *)pAttr;
  pq = (Quantity_t *)pAttr;
  prr = (RrTyp_t *)pAttr;
  pz = (Z_To_R_Constants_t *) pAttr;
  pa = pa;
  pb = pb;
  pp = pp;
  pi = pi;
  pz = pz;
  pr = pr;
  pq = pq;
  prr = prr;
  AttrSize = AttrSize;
  switch (Type)
    {
      case  Clutter_Treatment_Attr :
      case  Occultation_Correction_Attr :
      case  RrTyp_Attr :
        RrTypeDef = (RrTyp_t)(p->a[0]);
        memcpy(pAttr, 
               &RrTypeDef, 
               sizeof(RrTypeDef));
        break;
      case  Quantity_Attr :

        /********************************************************************/
        /* What in low Nibble, Unit in high                                 */
        /********************************************************************/

        QuantityDef.What = (QuantityUnit_t)(p->a[0]&0x0F);
        QuantityDef.Unit = (PhysUnit_t)p->a[0];
        QuantityDef.Unit = (PhysUnit_t)(QuantityDef.Unit>>4);
        memcpy(pAttr, 
               &QuantityDef, 
               sizeof(QuantityDef));
        break;
      case  Resolution_Attr :
        ResolutionDef.Resolution = GetVAX16(&p->a[0]);
        memcpy(pAttr, 
               &ResolutionDef, 
               sizeof(ResolutionDef));
        break;
      case  Z_To_R_Constants_Attr :
        Z_To_R.Factor = GetVAXFloat(&p->a[0]);
        Z_To_R.Exponent = GetVAXFloat(&p->a[4]);
        Z_To_R.Type = p->a[8];         /* CFR BBN,ARG 940426                */
        memcpy(pAttr, 
               &Z_To_R, 
               sizeof(Z_To_R));
        break;
      case  IntStore_Attr :
        IntStoreDef.Ord = GetVAXFloat(&p->a[0]);
        IntStoreDef.Slope = GetVAXFloat(&p->a[4]);
        IntStoreDef.Offset = GetVAX32(&p->a[8]);
        memcpy(pAttr, 
               &IntStoreDef, 
               sizeof(IntStoreDef));
        break;
      case  AreaProperties_Attr :
        AreaDef.Proj.ProjectionType = (Projection_Type_t)p->a[0];
        /* AreaDef.Proj.ProjectionType = AreaDef.Proj.ProjectionType&0x7; */
        switch (AreaDef.Proj.ProjectionType)
          {
            case  Polar_Stereographic :/* polar                             */
              AreaDef.Proj.ProjData.TangentPoint.Lat = GetVAXFloat(&p->a[1])
                 ;
              AreaDef.Proj.ProjData.TangentPoint.Long = GetVAXFloat(&p->a[5]
                 );
              AreaDef.SouthWest.LatLong.Lat = GetVAXFloat(&p->a[9]);
              AreaDef.SouthWest.LatLong.Long = GetVAXFloat(&p->a[13]);
              AreaDef.NorthEast.LatLong.Lat = GetVAXFloat(&p->a[17]);
              AreaDef.NorthEast.LatLong.Long = GetVAXFloat(&p->a[21]);
              break;
            case  Gnomonic :           /* gnomonic                          */
            case  Unknown :
              AreaDef.Proj.ProjData.Pos.Lat = GetVAXFloat(&p->a[1]);
              AreaDef.Proj.ProjData.Pos.Long = GetVAXFloat(&p->a[5]);
              AreaDef.SouthWest.LatLong.Lat = GetVAXFloat(&p->a[9]);
              AreaDef.SouthWest.LatLong.Long = GetVAXFloat(&p->a[13]);
              AreaDef.NorthEast.LatLong.Lat = GetVAXFloat(&p->a[17]);
              AreaDef.NorthEast.LatLong.Long = GetVAXFloat(&p->a[21]);
              break;
            default  :                 /* unknown projection type           */
              *Retcode = FI_GENERAL_ERROR;
              return ;
              break;                   /* I know it is unreachable, but     
                                          thats ok                          */
          } 
        memcpy(pAttr, 
               &AreaDef, 
               sizeof(AreaDef));
        break;
      case  Pixel_Attr :
        Pixel.RowCnt = GetVAX16(&p->a[0]);
        Pixel.ColCnt = GetVAX16(&p->a[2]);
        Pixel.StorePixels = GetVAX32(&p->a[4]);
        Pixel.StoreBits = p->a[8];
        Pixel.StoreMax = p->a[9];
        Pixel.Compressed = p->a[10];
        Pixel.FileOffset = GetVAX32(&p->a[11]);
        memcpy(pAttr, 
               &Pixel, 
               sizeof(Pixel));
        break;
      case  Bitmap_Attr :
        BitMap.FileOffset = GetVAX32(&p->a[0]);
        BitMap.StorePixels = GetVAX32(&p->a[4]);
        BitMap.Compressed = p->a[8];
        memcpy(pAttr, 
               &BitMap, 
               sizeof(BitMap));
        break;
    default:
      break;
    } 
  *Retcode = 1;
} 

static short GetVAX16(unsigned char p[])
{
  unsigned short tmp;

  tmp = p[1];
  tmp = tmp<<8;
  tmp += p[0];
  return  tmp;
} 

static long GetVAX32(unsigned char p[])
{
  unsigned long tmp;

  tmp = p[3];
  tmp = tmp<<8;
  tmp += p[2];
  tmp = tmp<<8;
  tmp += p[1];
  tmp = tmp<<8;
  tmp += p[0];
  return  tmp;
} 

static void PutVAX16(unsigned char p[],unsigned short value)
{
  p[0] = value&0xFF;
  p[1] = value>>8;
} 

static void PutVAX32(unsigned char p[],unsigned long value)
{
  p[0] = value&0xFF;
  p[1] = (value>>8)&0xFF;
  p[2] = (value>>16)&0xFF;
  p[3] = (value>>24)&0xFF;
} 

static void PutVAXFloat(unsigned char *p,float number)
{
  float mantissa;
  long fraction;
  int exp;
  unsigned char Byte;

  if (number == 0)
    {
      *p = 0;
      *(p+1) = 0;
      *(p+2) = 0;
      *(p+3) = 0;
      return ;
    } 
  mantissa = frexp(number, 
                   &exp);
  if (mantissa < 0)
    mantissa = -mantissa;
  fraction = mantissa *0x1000000L;
  Byte = (fraction>>16)&0x7F;
  *p = Byte;
  Byte = (fraction>>8)&0xFF;
  *(p+3) = Byte;
  Byte = fraction&0xFF;
  *(p+2) = Byte;
  exp = exp+128;
  Byte = exp&0xFF;
  *(p+1) = (Byte>>1)&0x7F;
  Byte = exp&0x01;
  Byte = Byte<<7;
  *(p) = (*p)|(Byte);
  if (number < 0)
    *(p+1) = *(p+1)|0x80;
} 


/*
                                                                            */

static float GetVAXFloat(unsigned char *p)
{
  float mantissa,number;
  long fraction,tmplong;
  unsigned int exp;
  unsigned char Byte;

/* all Zeros, return 0                                                      */

  if ((*p == 0)&(*(p+1) == 0)&(*(p+2) == 0)&(*(p+3) == 0))
    {
      return 0.0;
    } 
  Byte = *p;
  Byte = Byte|0x80;
  fraction = Byte;
  fraction = (fraction<<16);
  Byte = *(p+3);
  tmplong = Byte;
  tmplong = (tmplong<<8);
  fraction = fraction+tmplong;
  Byte = *(p+2);
  tmplong = Byte;
  fraction = fraction+tmplong;
  mantissa = fraction;
  mantissa = mantissa/0x1000000L;
  Byte = *(p+1);
  Byte = (Byte<<1);
  exp = Byte;
  Byte = *(p);
  Byte = (Byte>>7);
  exp = exp+Byte;
  exp = exp-128;
  number = ldexp(mantissa, 
                 exp);
  if ((*(p+1)&0x80) != 0)
    number = -number;
  return  number;
} 


/* ------------------------------------------------------------
   -- 
   -- 
   -- Description Converts from C-structure format to VAX File
   -- Format.
   -- 
   --
   ----------------------------------------------------------               */

static void fiConvertC2FileAttr(unsigned char *pBuff,Attr_t *pAttr,AttrTyp_t
                                Type,INT32 Len,INT32 *Retcode)
{
  Pixel_t *pp;
  Bitmap_t *pb;
  AreaDef_t *pa;
  Resolution_t *pr;
  Z_To_R_Constants_t *pzr;
  IntStore_t *pi;
  Quantity_t *pq;
  RrTyp_t *prr;
  typedef struct
    {
      unsigned char a[100];
    } 
  ByteArray;
  ByteArray *p;
  unsigned short tmp;

  p = (ByteArray *)(pBuff+2);
  pa = (AreaDef_t *)&pAttr->buff[0];
  pp = (Pixel_t *)&pAttr->buff[0];
  pb = (Bitmap_t *)&pAttr->buff[0];
  pr = (Resolution_t *)&pAttr->buff[0];
  pzr = (Z_To_R_Constants_t *)&pAttr->buff[0];
  pi = (IntStore_t *)&pAttr->buff[0];
  pq = (Quantity_t *)&pAttr->buff[0];
  prr = (RrTyp_t *)&pAttr->buff[0];
  switch (Type)
    {
      case  Clutter_Treatment_Attr :
      case  Occultation_Correction_Attr :
      case  RrTyp_Attr :               /* are all one bytes                 */
        *pBuff = Type|0x80;            /* Hard coded Type,including lsb of  
                                          length                            */
        *(pBuff+1) = 0x01;             /* Hard coded Length                 */
        tmp = *prr;
        p->a[0] = tmp;
        break;
      case  Quantity_Attr :
        *pBuff = 0x85;                 /* Hard coded Type                   */
        *(pBuff+1) = 0x01;             /* Hard coded Length                 */
        tmp = pq->Unit;                /* Put Unit in High nibble, What in  
                                          low.                              */
        tmp = tmp<<4;
        tmp = tmp+pq->What;
        p->a[0] = tmp;
        break;
      case  IntStore_Attr :
        *pBuff = 0x06;                 /* Hard coded Type                   */
        *(pBuff+1) = 0x07;             /* Hard coded length                 */
        PutVAXFloat(&p->a[0], 
                    pi->Ord);
        PutVAXFloat(&p->a[4], 
                    pi->Slope);
        PutVAX32(&p->a[8], 
                 pi->Offset);
        break;
      case  Resolution_Attr :
        *pBuff = 0x0F;                 /* Hard coded Type                   */
        *(pBuff+1) = 0x02;             /* Hard coded Length                 */
        PutVAX16(&p->a[0], 
                 pr->Resolution);
        break;
      case  Pixel_Attr :
        *pBuff = 0x89;                 /* Hard coded length                 */
        *(pBuff+1) = 0x08;             /* Hard coded type                   */
        PutVAX16(&p->a[0], 
                 pp->RowCnt);
        PutVAX16(&p->a[2], 
                 pp->ColCnt);
        PutVAX32(&p->a[4], 
                 pp->StorePixels);
        p->a[8] = pp->StoreBits;
        p->a[9] = pp->StoreMax;
        p->a[10] = pp->Compressed;
        PutVAX32(&p->a[11], 
                 pp->FileOffset);
        break;
      case  Bitmap_Attr :
        *pBuff = 0x8D;                 /* Hard coded type                   */
        *(pBuff+1) = 0x05;             /* Hard coded length                 */
        PutVAX32(&p->a[0], 
                 pb->FileOffset);
        PutVAX32(&p->a[4], 
                 pb->StorePixels);
        p->a[8] = pb->Compressed;
        break;
      case  AreaProperties_Attr :
        *pBuff = 0x83;                 /* Hard coded type                   */
        *(pBuff+1) = 0x0D;             /* Hard coded length                 */
        p->a[0] = pa->Proj.ProjectionType;
        switch (pa->Proj.ProjectionType)
          {
            case  Polar_Stereographic :/* polar                             */
              PutVAXFloat(&p->a[1], 
                          pa->Proj.ProjData.TangentPoint.Lat);
              PutVAXFloat(&p->a[5], 
                          pa->Proj.ProjData.TangentPoint.Long);
              PutVAXFloat(&p->a[9], 
                          pa->SouthWest.LatLong.Lat);
              PutVAXFloat(&p->a[13], 
                          pa->SouthWest.LatLong.Long);
              PutVAXFloat(&p->a[17], 
                          pa->NorthEast.LatLong.Lat);
              PutVAXFloat(&p->a[21], 
                          pa->NorthEast.LatLong.Long);
              break;
            case  Gnomonic :
            case  Unknown :
              PutVAXFloat(&p->a[1], 
                          pa->Proj.ProjData.Pos.Lat);
              PutVAXFloat(&p->a[5], 
                          pa->Proj.ProjData.Pos.Long);
              PutVAXFloat(&p->a[9], 
                          pa->SouthWest.LatLong.Lat);
              PutVAXFloat(&p->a[13], 
                          pa->SouthWest.LatLong.Long);
              PutVAXFloat(&p->a[17], 
                          pa->NorthEast.LatLong.Lat);
              PutVAXFloat(&p->a[21], 
                          pa->NorthEast.LatLong.Long);
              break;
            default  :
              *Retcode = FI_GENERAL_ERROR;
              return ;
              break;                   /* I know it is unreachable, but     
                                          thats ok                          */
          } 
        break;
      case  Z_To_R_Constants_Attr :
        *pBuff = 0x90;                 /* Hard coded type                   */
        *(pBuff+1) = 0x05;             /* Hard coded length                 */
        PutVAXFloat(&p->a[0], 
                    pzr->Factor);
        PutVAXFloat(&p->a[4], 
                    pzr->Exponent);
        p->a[8] = pzr->Type;
        break;
      default  :                       /* No special Format, move it        
                                          bytewise                          */
          {
            unsigned short TmpShrt;

            TmpShrt = Len;
            TmpShrt = TmpShrt&0x01;
            TmpShrt = TmpShrt<<7;
            TmpShrt = TmpShrt+Type;
            *pBuff = TmpShrt;
            TmpShrt = Len+2;           /* add length of attribute header    */
            TmpShrt = TmpShrt>>1;
            *(pBuff+1) = TmpShrt;
          } 
        memcpy(pBuff+2, 
               pAttr, 
               Len);
        break;
    } 
  *Retcode = 1;
} 


/* ------------------------------------------------------------
   -- 
   -- fiWriteAttr
   --  
   -- Description
   -- 
   -- Pseudocode
   --
   -- Parameters
   --
   ----------------------------------------------------------               */

void fiWriteAttr(Fil_t *F,Attr_t *Attr,AttrTyp_t Type,INT32 Len,INT32 
                 *Retcode)
{
  INT32 NotFound = 1;
  INT32 AttrSize;
  unsigned char *p;
  unsigned char Byte;
  INT32 ConvertRet;

  if (!F->Opened)
    fiOpen(F, 
           UpdateMode, 
           Retcode);
  p = (unsigned char *)F->AttrBuf;
  Byte = Type;
  while (NotFound && ((p-(unsigned char *)F->AttrBuf) < F->AttrSize))
    {
      Byte = (*p);
      Byte = Byte&0x7F;                /* Mask bits 0-6                     */
      AttrSize = *(p+1)<<1;
      AttrSize = AttrSize+(*p>>7);
      if ((Byte == 0)                  /* Found an Empty place              */
         || (Byte == Type))            /* Or Same attr                      */
        {
          AttrSize = Len;
          fiConvertC2FileAttr(p, 
                              Attr, 
                              Type, 
                              Len, 
                              &ConvertRet);
          if (ConvertRet != 1)
            {
              *Retcode = FI_GENERAL_ERROR;
              return ;
            } 
          fseek(F->fp, 
                IDENTSIZE, 
                SEEK_SET);
          fwrite(F->AttrBuf, 
                 F->AttrSize, 
                 1, 
                 F->fp);
          *Retcode = 1;
          return ;                     /* finished                          */
        } 
      else
        {                              /* position to next attribute        */

          /******************************************************************/
          /* Size = Bit 6-7 + bit 0-7 of next byte                          */
          /******************************************************************/

          p = p+AttrSize;
        } 
    } 
  *Retcode = FI_GENERAL_ERROR;
} 

