static char szModuleName__[] = "a:/nordrad/unix/apiext.c";
static char szLastVersion[] = "Version 0.7";
static char szLastSave[] = "1997-02-05*21:05";

/************************************************************
Abstract
apiext.c - Nordrad API Extended
           Contains Convert, Export and Import Api primitives

(C) Copyright AU-System Communication AB 1994.

Change activity
990125		ARG, Modified entry names to avoid collision w. filep
1994-10-02      ARG  Fpopen modified
1994-02-02 1.00 BBN  Initial version by Björn Brodin.

Part of  Nordrad.

Description
************************************************************                */

#ifdef   VMS
#include <types.h>
#include <stdio.h>
#include <string.h>
#include <stat.h>
#include <math.h>
#include <netdb.h>
#else
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <math.h>
#include <malloc.h>
#include <netdb.h>
#endif
#include "netdef.h"
#include "api.h"
#include "net.h"
#include "utl.h"
#include "shft.h"
#include "fil.h"
#include "rr_fil.h"
#include "comp.h"
#include "nradutil.h"
#define  MAX_DONT_COPY_TAB 10
#define  BUFR_TYPE     1
#define  BUFR_PARAM_TYPE 2
extern BUF b;

/*----------------------------------------------------------
*       Functions
*---------------------------------------------------------                  */

void CopySelHeaderAttr(Fil_t *pSourceFile,Fil_t *pDestFile,INT32 
                       *piDontCopyList);

INT32 GetCnvConst(char *ParFilName, IntStore_t *pStoreAttr, ConvConst_t *pbb);
INT32 ValidateFileType(char *pFileNameStr,char *IdStr,INT32 iLen,long lPos,
                       INT32 Type);

INT32 CnvToSriProd(Fil_t *pSourceFile,Fil_t *pDestFile,char *pParamFileStr,
                   Pixel_t *pPixelAttrIn,struct ApiProdDescrStruc 
                   *pApiProdDescr);

INT32 ImportFromBufr(char *pBufferFileStr,char *pInParamFileStr,char 
                     *pOutParamFileStr,char *pDestFileStr,unsigned char 
                     PackAlg,struct ApiProdDescrStruc *pApiProdDescr);

INT32 ExportToBufr(char *pSourceFileStr,
		   char *pParamFileStr,
		   char *pDestFileStr,
		   unsigned char BufrMode);

INT32 pckExpandNradProd(char *pSourceFileStr,char *pDestFileStr);
INT32 pckCompressNradProd(char *SourceFileStr,char *DestFileStr);
#define  CONST_ORD     -2.0
#define  CONST_SLOPE   0.02
#define  CONST_OFFSET  0.0
#define  NEW_BUFR_ID_STR   \
"####  N O R D R A D   M S G . P A R   -   F I L E"

/*----------------------------------------------------------
*  API call Import - Convert BUFR format to NORDRAD format
*---------------------------------------------------------                  */

void Import_BUFR(char *pBufferFileStr,char *pDestFileStr,char 
                 *pInParamFileStr,char *pOutParamFileStr,unsigned char 
                 bPackAlg,struct ApiProdDescrStruc *pApiProdDescr,INT32 
                 *piStatus)
{
char szBufferFileStr  [MAX_FILE_NAME_SIZE+1];
char szDestFileStr    [MAX_FILE_NAME_SIZE+1];
char szInParamFileStr [MAX_FILE_NAME_SIZE+1];
char szOutParamFileStr [MAX_FILE_NAME_SIZE+1];

     INT32 iErr = OK;
     
  if (strlen (pDestFileStr) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szDestFileStr, pDestFileStr);

  if (strlen (pBufferFileStr) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szBufferFileStr, pBufferFileStr);

  if (strlen (pInParamFileStr) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szInParamFileStr, pInParamFileStr);  

  if (strlen (pOutParamFileStr) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szOutParamFileStr, pOutParamFileStr);

  if (bPackAlg > 1)
    {
      *piStatus = APIILLPAR;
      return ;
    } 
  if (UtlStripStr(szBufferFileStr, 
                  (INT32)strlen(szBufferFileStr), 
                  CHECK_NOT_EMPTY, 
                  UNCHANGED) == NOK)
    {
      *piStatus = APINOSOURCE;
      return ;
    } 
  if ((iErr = ValidateFileType(szBufferFileStr, 
                               "BUFR", 
                               4, 
                               0L, 
                               BUFR_TYPE)) != OK)
    {
      *piStatus = iErr;
      return ;
    } 
  if (UtlStripStr(szInParamFileStr, 
                  (INT32)strlen(szInParamFileStr), 
                  CHECK_NOT_EMPTY, 
                  UNCHANGED) == NOK)
    {
      *piStatus = BUFPARNAME;
      return ;
    } 
  if (UtlStripStr(szOutParamFileStr, 
                  (INT32)strlen(szOutParamFileStr), 
                  CHECK_NOT_EMPTY, 
                  UNCHANGED) == NOK)
    {
      *piStatus = BUFPARNAME;
      return ;
    } 
  if (UtlStripStr(szDestFileStr, 
                  (INT32)strlen(szDestFileStr), 
                  CHECK_NOT_EMPTY, 
                  UNCHANGED) == NOK)
    {
      *piStatus = APINODEST;
      return ;
    } 
  iErr = ImportFromBufr(szBufferFileStr, 
                        szInParamFileStr, 
                        szOutParamFileStr, 
                        szDestFileStr, 
                        bPackAlg, 
                        pApiProdDescr);
  *piStatus = iErr;
} 


/*----------------------------------------------------------
*  API call Export - Convert NORDRAD format to BUFR format
*---------------------------------------------------------                  */

void Export_BUFR(char *pBufferFileStr,
		 char *pDestFileStr,
		 char *pParamFileStr,
		 unsigned char BufrMode,
		 INT32 *piStatus)
{
char szBufferFileStr  [MAX_FILE_NAME_SIZE+1];
char szDestFileStr    [MAX_FILE_NAME_SIZE+1];
char szParamFileStr   [MAX_FILE_NAME_SIZE+1];

     INT32 iErr = OK;
     
  if (strlen (pDestFileStr) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szDestFileStr, pDestFileStr);

  if (strlen (pBufferFileStr) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szBufferFileStr, pBufferFileStr);

  if (strlen (pParamFileStr) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szParamFileStr, pParamFileStr);  

  if (UtlStripStr(szBufferFileStr, 
                  (INT32)strlen(szBufferFileStr), 
                  CHECK_NOT_EMPTY, 
                  UNCHANGED) == NOK)
    {
      *piStatus = APINOSOURCE;
      return ;
    } 
  if (UtlStripStr(szParamFileStr, 
                  (INT32)strlen(szParamFileStr), 
                  CHECK_NOT_EMPTY, 
                  UNCHANGED) == NOK)
    {
      *piStatus = BUFPARNAME;
      return ;
    } 
  if ((iErr = ValidateFileType(szParamFileStr, 
                               NEW_BUFR_ID_STR, 
                               strlen(NEW_BUFR_ID_STR), 
                               0L, 
                               BUFR_PARAM_TYPE)) != OK)
    {
      *piStatus = iErr;
      return ;
    } 
  if (UtlStripStr(szDestFileStr, 
                  (INT32)strlen(szDestFileStr), 
                  CHECK_NOT_EMPTY, 
                  UNCHANGED) == NOK)
    {
      *piStatus = APINODEST;
      return ;
    } 
  if (BufrMode > 1)
    {
      *piStatus = APIILLPAR;
      return ;
    } 

  iErr = ExportToBufr(szBufferFileStr, 
                      szParamFileStr, 
                      szDestFileStr,
		      BufrMode);
  *piStatus = iErr;
} 


/*----------------------------------------------------------------
*  API call Convert - Convert NORDRAD product to SRI product type
*----------------------------------------------------------------           */

void Convert_Dbz_To_SRI(char *pSourceFileNameStr,char *pDestFileNameStr,char
                        *pParamFileStr,unsigned char bPackAlg,struct 
                        ApiProdDescrStruc *pApiProdDescr,INT32 *piStatus)
{
  INT32 iRc = OK;
  Fil_t InFile;
  Fil_t OutFile;
  Pixel_t PixelInfoIn;
  Pixel_t *pPixelAttrIn;
  unsigned char ProdNameInfo;
  unsigned char *pProdNameAttr;
  char UnpDestFileStr[MAX_FILE_NAME_SIZE];
  char UnpSourceFileStr[MAX_FILE_NAME_SIZE];
  INT32 iAttrLen = 0;
  INT32 iDummyRc = 0;
  INT32 iErr = OK;

char szDestFileNameStr    [MAX_FILE_NAME_SIZE+1];
char szSourceFileNameStr  [MAX_FILE_NAME_SIZE+1];
char szParamFileStr       [MAX_FILE_NAME_SIZE+1];

  pProdNameAttr = (unsigned char *)&ProdNameInfo;
  pPixelAttrIn = (Pixel_t *)&PixelInfoIn;


     
  if (strlen (pDestFileNameStr) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szDestFileNameStr, pDestFileNameStr);

  if (strlen (pSourceFileNameStr) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szSourceFileNameStr, pSourceFileNameStr);

  if (strlen (pParamFileStr) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szParamFileStr, pParamFileStr);  


  memset(UnpSourceFileStr, 
         0, 
         sizeof(UnpSourceFileStr));
  if (bPackAlg > 1)
    {
      *piStatus = APIILLPAR;
      return ;
    } 
  if (UtlStripStr(szSourceFileNameStr, 
                  (INT32)strlen(szSourceFileNameStr), 
                  CHECK_NOT_EMPTY, 
                  UNCHANGED) == NOK)
    {
      *piStatus = APINOSOURCE;
      return ;
    } 
  memset(&InFile, 
         0, 
         sizeof(InFile));
  strcpy(InFile.Name, 
         szSourceFileNameStr);
  if (UtlStripStr(szParamFileStr, 
                  (INT32)strlen(szParamFileStr), 
                  CHECK_NOT_EMPTY, 
                  UNCHANGED) == NOK)
    {
      *piStatus = APIILLPAR;
      return ;
    } 
  if ((iErr = ValidateFileType(szParamFileStr, 
                               NEW_BUFR_ID_STR, 
                               strlen(NEW_BUFR_ID_STR), 
                               0L, 
                               BUFR_PARAM_TYPE)) != OK)
    {
      *piStatus = iErr;
      return ;
    } 
  if (UtlStripStr(szDestFileNameStr, 
                  (INT32)strlen(szDestFileNameStr), 
                  CHECK_NOT_EMPTY, 
                  UNCHANGED) == NOK)
    {
      *piStatus = APINODEST;
      return ;
    } 
  fiOpen(&InFile, 
         InputMode, 
         &iRc);
  if ((InFile.fp == NULL) || (iRc != OK))
    {
      if (iRc == -1)
        *piStatus = PGFFILNOTFND;
      else
        if (iRc == -3)

          *piStatus = PGFILLFILE;
        else
          *piStatus = APIILLPAR;
      return ;
    } 
  fiReadAttr(&InFile, 
             (Attr_t *)pProdNameAttr, 
             Name_Attr, 
             &iAttrLen, 
             &iRc);
  if (iRc != OK)
    {
      fiClose(&InFile, 
              &iTmpRc);
      *piStatus = BUFNRDERROR;
      return ;
    } 
  if ((*pProdNameAttr != PROD_RRPPI_Z) && (*pProdNameAttr != PROD_RRPSC_Z) 
     && (*pProdNameAttr != PROD_RRCAPPI_Z) && (*pProdNameAttr != 
     PROD_RRVMI_Z))
    {
      *piStatus = PGFILLFILE;
      fiClose(&InFile, 
              &iTmpRc);
      return ;
    } 
  fiReadAttr(&InFile, 
             (Attr_t *)pPixelAttrIn, 
             Pixel_Attr, 
             &iAttrLen, 
             &iRc);
  if (iRc != OK)
    {
      fiClose(&InFile, 
              &iTmpRc);
      *piStatus = BUFNRDERROR;
      return ;
    } 
  if (bPackAlg == RLE)
    {
      strcpy(UnpDestFileStr, 
             "NrdUx");
      tmpnam(UnpDestFileStr);          /* names for temporary files         */
      memset(&OutFile, 
             0, 
             sizeof(OutFile));
      strcpy(OutFile.Name, 
             UnpDestFileStr);
    } 
  else
    {
      memset(&OutFile, 
             0, 
             sizeof(OutFile));
      strcpy(OutFile.Name, 
             szDestFileNameStr);
    } 
  fiCreate(&OutFile, 
           OutFile.Name, 
           512, 
           0, 
           &iRc);
  if ((OutFile.fp == NULL) || (iRc != OK))
    {
      fiClose(&InFile, 
              &iTmpRc);
      if (iRc == -1)
        *piStatus = PGFFILNOTFND;
      else
        if (iRc == -3)

          *piStatus = PGFILLFILE;
        else
          *piStatus = APIILLPAR;
      return ;
    } 
  if (pPixelAttrIn->Compressed == TRUE)
    {
      fiClose(&InFile, 
              &iTmpRc);
      strcpy(UnpSourceFileStr, 
             "NrdUx");
      tmpnam(UnpSourceFileStr);        /* names for temporary files         */
      if ((iRc = pckExpandNradProd(szSourceFileNameStr, 
                                   UnpSourceFileStr)) != OK)
        {
          *piStatus = APIILLPAR;
          iDummyRc = remove(UnpDestFileStr);
          iDummyRc = remove(UnpSourceFileStr);
          return ;
        } 

      /**********************************************************************/
      /* re open infile as unpacked                                         */
      /**********************************************************************/

      strcpy(InFile.Name, 
             UnpSourceFileStr);
      fiOpen(&InFile, 
             InputMode, 
             &iRc);
      if ((InFile.fp == NULL) || (iRc != OK))
        {
          fiClose(&OutFile, 
                  &iTmpRc);
          iDummyRc = remove(UnpDestFileStr);
          iDummyRc = remove(UnpSourceFileStr);
          if (iRc == -1)
            *piStatus = PGFFILNOTFND;
          else
            if (iRc == -3)

              *piStatus = PGFILLFILE;
            else
              *piStatus = APIILLPAR;
          return ;
        } 
      fiReadAttr(&InFile, 
                 (Attr_t *)pPixelAttrIn, 
                 Pixel_Attr, 
                 &iAttrLen, 
                 &iRc);
      if (iRc != OK)
        {
          fiClose(&InFile, 
                  &iTmpRc);
          *piStatus = BUFNRDERROR;
          return ;
        } 
    } 
  iRc = CnvToSriProd(&InFile, 
                     &OutFile, 
                     szParamFileStr, 
                     pPixelAttrIn, 
                     pApiProdDescr);
  fiClose(&OutFile, 
          &iTmpRc);
  fiClose(&InFile, 
          &iTmpRc);
  if ((iRc != APIOK) && (bPackAlg == RLE))
    iDummyRc = remove(UnpDestFileStr);
  else
    if (bPackAlg == RLE)
      {

        iRc = pckCompressNradProd(OutFile.Name, 
                                  szDestFileNameStr);
        iDummyRc = remove(UnpDestFileStr);
      } 
  if (strlen(UnpSourceFileStr) > 0)
    iDummyRc = remove(UnpSourceFileStr);
  if (iRc == OK)
    iRc = APIOK;
  *piStatus = iRc;
} 


/*----------------------------------------------------------
*  ConvToSriProd- Converts from other nordrad product type 
*                 to nordrad rain intensity product.
*                 Since we are working on a uncompressed
*                 bitmap no change is made in size but type
*                 must be changed in header attribute.
*                 Returns an unpacked SRI nordrad file.
*---------------------------------------------------------                  */

INT32 CnvToSriProd(Fil_t *pSourceFile,Fil_t *pDestFile,char *pParamFileStr,
                   Pixel_t *pPixelAttrIn,struct ApiProdDescrStruc 
                   *pApiProdDescr)
{
  INT32 iRc = OK;
  unsigned char *pInData;              /* BBN 940526 to unsigned            */
  char *pInBitmData;
  INT32 iPixDataSize = 0;
  INT32 iInd = 0;
  INT32 iNextRow = 0;
  unsigned char ProdNameInfo;
  unsigned char *pProdNameAttr;
  Quantity_t QuantityInfoOut;
  Quantity_t *pQuantityAttrOut;
  Z_To_R_Constants_t ZtoRConstInfoOut;
  Z_To_R_Constants_t *pZtoRConstAttrOut;
  float fPhysDbZ = 0;
  float fPhysLogR = 0;
  double dExponent;
  double dTmpExponent;
  float fTmpFloat;
  double dFact = 0;
  double dLogFact = 0;
  IntStore_t IntStoreInfo;
  IntStore_t NewIntStoreInfo;
  IntStore_t *pIntStoreAttr;
  IntStore_t *pNewIntStoreAttr;
  ConvConst_t bb;
  Bitmap_t BitmapInfoIn;
  Bitmap_t *pBitmapAttrIn;
  Area_t *pAreaAttr;
  Area_t AreaInfo;
  Time_t TimeInfoOut;
  Time_t *pTimeAttrOut;
  Resolution_t ResolutionInfo;
  Resolution_t *pResolutionAttr;
  RrTyp_t RrTypeInfo;
  RrTyp_t *pRrTypeAttr;
  INT32 iAttrLen = 0;
  INT32 DontCopyList[MAX_DONT_COPY_TAB+1];
  unsigned char CnvToSriTab[MAX_PIX_VALUES+1];
  unsigned char s[7];
  FILE *ParFilep;
  INT32 iBytesRead = 0;

  pNewIntStoreAttr = (IntStore_t *)&NewIntStoreInfo;
  pIntStoreAttr = (IntStore_t *)&IntStoreInfo;
  pBitmapAttrIn = (Bitmap_t *)&BitmapInfoIn;
  pProdNameAttr = (unsigned char *)&ProdNameInfo;
  pQuantityAttrOut = (Quantity_t *)&QuantityInfoOut;
  pZtoRConstAttrOut = (Z_To_R_Constants_t *)&ZtoRConstInfoOut;
  pTimeAttrOut = (Time_t *)&TimeInfoOut;
  pAreaAttr = (Area_t *)&AreaInfo;
  pResolutionAttr = (Resolution_t *)&ResolutionInfo;
  pRrTypeAttr = (RrTyp_t *)&RrTypeInfo;

  /**************************************************************************/
  /* ---------< initialize Infile >--------------                           */
  /**************************************************************************/

  fiReadAttr(pSourceFile, 
             (Attr_t *)pIntStoreAttr, 
             IntStore_Attr, 
             &iAttrLen, 
             &iRc);
  if (iRc != OK)
    {
      fiClose(pSourceFile, 
              &iTmpRc);
      return  BUFNRDERROR;
    } 

  fiReadAttr(pSourceFile, 
             (Attr_t *)pBitmapAttrIn, 
             Bitmap_Attr, 
             &iAttrLen, 
             &iRc);
  if (iRc != OK)
    memset(pBitmapAttrIn, 
           0, 
           sizeof(BitmapInfoIn));
  fiReadAttr(pSourceFile, 
             (Attr_t *)pTimeAttrOut, 
             Time_Attr, 
             &iAttrLen, 
             &iRc);
  if (iRc < 0)
    {
      return  BUFNRDERROR;
    } 

  fiReadAttr(pSourceFile, 
             (Attr_t *)pAreaAttr, 
             Area_Attr, 
             &iAttrLen, 
             &iRc);
  if (iRc < 0)
    return  BUFNRDERROR;

  fiReadAttr(pSourceFile, 
             (Attr_t *)pResolutionAttr, 
             Resolution_Attr, 
             &iAttrLen, 
             &iRc);
  if (iRc != OK)
    return  BUFNRDERROR;

  fiReadAttr(pSourceFile, 
             (Attr_t *)pRrTypeAttr, 
             RrTyp_Attr, 
             &iAttrLen, 
             &iRc);
  if (iRc != OK)
    return  BUFNRDERROR;

  memset(DontCopyList, 
         0, 
         sizeof(DontCopyList));
  DontCopyList[0] = Height_Attr;
  CopySelHeaderAttr(pSourceFile, 
                    pDestFile, 
                    (INT32 *)DontCopyList);

  /**************************************************************************/
  /* ---< Re arrange pixel data for convertion to SRI format >----          */
  /**************************************************************************/

  iPixDataSize = pPixelAttrIn->ColCnt *pPixelAttrIn->RowCnt;
  pInData = (unsigned char *)malloc((size_t)iPixDataSize);
  if (pInData == NULL)
    return  APINOMEM;

  /**************************************************************************/
  /* read Pixel information from file in NORDRAD format                     */
  /**************************************************************************/

  fseek(pSourceFile->fp, 
        pPixelAttrIn->FileOffset-1, 
        SEEK_SET);
  iBytesRead = fread(pInData, 
                     sizeof(char), 
                     iPixDataSize, 
                     pSourceFile->fp);
  if (iBytesRead != iPixDataSize)
    {
      fiClose(pSourceFile, 
              &iTmpRc);
      return  BUFNRDERROR;
    } 



  if ((iRc = GetCnvConst(pParamFileStr, pNewIntStoreAttr, &bb )) != OK)
    return  BUFPARCONT;

  if (bb.izr != 0)
    return  BUFPARCONT;

  /**************************************************************************/
  /* Convert every pixel to rain intensity value                            */
  /**************************************************************************/

  fTmpFloat = bb.iexpzr;
  dExponent = fTmpFloat;              /* /100.00; remove 951002-ADS*/
  dTmpExponent = fTmpFloat*10.0;       /* = (fTmpFloat/100.0) * 10)         */
  dFact = bb.ifaczr;

  /**************************************************************************/
  /* create convertion table                                                */
  /**************************************************************************/

  dLogFact = 10.0*log10(dFact);
  iInd = MAX_PIX_VALUES;
  while (iInd >= 0)
    {

      /**********************************************************************/
      /* Pixel value to physical value in Db                                */
      /**********************************************************************/

      fPhysDbZ = ((iInd-pIntStoreAttr->Offset)*pIntStoreAttr->Slope)+
         pIntStoreAttr->Ord;

      /**********************************************************************/
      /* to physical value in mm/h                                          */
      /**********************************************************************/

      fPhysLogR = (fPhysDbZ-dLogFact)/dTmpExponent;

      /**********************************************************************/
      /* back to Pixel value                                                */
      /**********************************************************************/

      CnvToSriTab[iInd] = (fPhysLogR-pNewIntStoreAttr->Ord)/
         pNewIntStoreAttr->Slope+pNewIntStoreAttr->Offset;
      iInd--;
    } 
  CnvToSriTab[0] = 0;
  CnvToSriTab[255] = 255;

  /**************************************************************************/
  /* convert pixel data buffer content to rain intensity                    */
  /**************************************************************************/

  for (iInd = 0; iInd < iPixDataSize; iInd++)
    pInData[iInd] = CnvToSriTab[pInData[iInd]];
  fiAllocate(pDestFile, 
             iPixDataSize, 
             &pPixelAttrIn->FileOffset, 
             &iRc);
  pPixelAttrIn->FileOffset += 1;
  iNextRow = 0;
  fseek(pDestFile->fp, 
        pPixelAttrIn->FileOffset-1, 
        SEEK_SET);
  while (iNextRow < iPixDataSize)
    {
      fwrite(&pInData[iNextRow], 
             sizeof(char), 
             pPixelAttrIn->ColCnt, 
             pDestFile->fp);
      iNextRow += pPixelAttrIn->ColCnt;
    } 
  free(pInData);
  if (pBitmapAttrIn->StorePixels > 0)
    {

      /**********************************************************************/
      /* copy Bitmap info without change                                    */
      /**********************************************************************/

      pInBitmData = malloc(pBitmapAttrIn->StorePixels);
      if (pInBitmData == NULL)
        return  APINOMEM;

      /**********************************************************************/
      /* read Bitmap information from file in NORDRAD format                */
      /**********************************************************************/

      fseek(pSourceFile->fp, 
            pBitmapAttrIn->FileOffset-1, 
            SEEK_SET);
      iBytesRead = fread(pInBitmData, 
                         sizeof(char), 
                         pBitmapAttrIn->StorePixels, 
                         pSourceFile->fp);
      if (iBytesRead != pBitmapAttrIn->StorePixels)
        {
          fiClose(pSourceFile, 
                  &iTmpRc);
          return  BUFNRDERROR;
        } 

      fiAllocate(pDestFile, 
                 pBitmapAttrIn->StorePixels, 
                 &pBitmapAttrIn->FileOffset, 
                 &iRc);
      pBitmapAttrIn->FileOffset += 1;
      fseek(pDestFile->fp, 
            pBitmapAttrIn->FileOffset-1, 
            SEEK_SET);
      fwrite(pInBitmData, 
             sizeof(char), 
             pBitmapAttrIn->StorePixels, 
             pDestFile->fp);
      iAttrLen = sizeof(Bitmap_t);
      fiWriteAttr(pDestFile, 
                  (Attr_t *)pBitmapAttrIn, 
                  Bitmap_Attr, 
                  iAttrLen, 
                  &iRc);
      free(pInBitmData);
      if (iRc != OK)
        return  BUFNRDERROR;
    } 

  /**************************************************************************/
  /* Update header info                                                     */
  /**************************************************************************/

  iAttrLen = sizeof(Pixel_t);
  fiWriteAttr(pDestFile, 
              (Attr_t *)pPixelAttrIn, 
              Pixel_Attr, 
              iAttrLen, 
              &iRc);
  if (iRc != OK)
    return  BUFNRDERROR;

  *pProdNameAttr = PROD_RRSRI_Z;
  iAttrLen = sizeof(char);
  fiWriteAttr(pDestFile, 
              (Attr_t *)pProdNameAttr, 
              Name_Attr, 
              iAttrLen, 
              &iRc);
  if (iRc != OK)
    return  BUFNRDERROR;

  pQuantityAttrOut->Unit = mm_h;
  pQuantityAttrOut->What = q_Log_Surface_Rain_Intensity;
  iAttrLen = sizeof(Quantity_t);
  fiWriteAttr(pDestFile, 
              (Attr_t *)pQuantityAttrOut, 
              Quantity_Attr, 
              iAttrLen, 
              &iRc);
  if (iRc != OK)
    return  BUFNRDERROR;

  pZtoRConstAttrOut->Factor = dFact;
  pZtoRConstAttrOut->Exponent = dExponent;
  pZtoRConstAttrOut->Type = 0;         /* ZH to R Conversion                */
  iAttrLen = sizeof(Z_To_R_Constants_t);
  fiWriteAttr(pDestFile, 
              (Attr_t *)pZtoRConstAttrOut, 
              Z_To_R_Constants_Attr, 
              iAttrLen, 
              &iRc);
  if (iRc != OK)
    return  BUFNRDERROR;

  iAttrLen = sizeof(IntStore_t);
  fiWriteAttr(pDestFile, 
              (Attr_t *)pNewIntStoreAttr, 
              IntStore_Attr, 
              iAttrLen, 
              &iRc);
  if (iRc != OK)
    return  BUFNRDERROR;

  /**************************************************************************/
  /* create a product description memset(pApiProdDescr,0,sizeof(struct      */
  /* ApiProdDescrStruc));                                                   */
  /**************************************************************************/

  pApiProdDescr->bProd = PROD_RRSRI_Z;
  memcpy(&pApiProdDescr->cTimeStr[0], 
         "19", 
         2);
  memcpy(&pApiProdDescr->cTimeStr[2], 
         &pTimeAttrOut->timeString[0], 
         2);
  memcpy(&pApiProdDescr->cTimeStr[4], 
         "-", 
         1);
  memcpy(&pApiProdDescr->cTimeStr[5], 
         &pTimeAttrOut->timeString[2], 
         2);
  memcpy(&pApiProdDescr->cTimeStr[7], 
         "-", 
         1);
  memcpy(&pApiProdDescr->cTimeStr[8], 
         &pTimeAttrOut->timeString[4], 
         2);
  memcpy(&pApiProdDescr->cTimeStr[10], 
         " ", 
         1);
  memcpy(&pApiProdDescr->cTimeStr[11], 
         &pTimeAttrOut->timeString[6], 
         2);
  memcpy(&pApiProdDescr->cTimeStr[13], 
         ":", 
         1);
  memcpy(&pApiProdDescr->cTimeStr[14], 
         &pTimeAttrOut->timeString[8], 
         2);
  memcpy(&pApiProdDescr->cTimeStr[16], 
         ":", 
         1);
  memcpy(&pApiProdDescr->cTimeStr[17], 
         &pTimeAttrOut->timeString[10], 
         2);
  memcpy(&pApiProdDescr->cTimeStr[19], 
         ".", 
         1);
  memcpy(&pApiProdDescr->cTimeStr[20], 
         "00", 
         2);
  pApiProdDescr->cTimeStr[22] = 0;
  memcpy(pApiProdDescr->cArea, 
         pAreaAttr->Name, 
         sizeof(pApiProdDescr->cArea));
  pApiProdDescr->iResolution = pResolutionAttr->Resolution;
  switch (*pRrTypeAttr)
    {
      case 1 :
        pApiProdDescr->uData.RrType.bRrMode = 2;
        break;
      case 2 :
        pApiProdDescr->uData.RrType.bRrMode = 1;
        break;
      default  :
        pApiProdDescr->uData.RrType.bRrMode = 3;
    } 
  if ((iRc == 0) || (iRc == OK))
    iRc = APIOK;
  return  iRc;
} 


/*----------------------------------------------------------
*  CopySelHeaderAttr - Copy all file header attributes 
*                       except those listed.
*---------------------------------------------------------                  */

void CopySelHeaderAttr(Fil_t *pSourceFile,Fil_t *pDestFile,INT32 
                       *piDontCopyList)
{
  INT32 iAttrType = 0;
  INT32 iAttrLen = 0;
  INT32 CopyFl = TRUE;
  INT32 iInd = 0;
  Attr_t Attr;
  char *pAttrBuff;
  INT32 iRc = OK;

  pAttrBuff = (char *)Attr.buff;

  /**************************************************************************/
  /* copy until last attribute                                              */
  /**************************************************************************/

  for (iAttrType = 0; iAttrType <= Period_Attr; iAttrType++)
    {
      CopyFl = TRUE;
      fiReadAttr(pSourceFile, 
                 (Attr_t *)pAttrBuff, 
                 iAttrType, 
                 &iAttrLen, 
                 &iRc);
      if (iRc == OK)
        {
          iInd = 0;
          while ((iInd < MAX_DONT_COPY_TAB) && (piDontCopyList[iInd] != 0))
            {
              if (iAttrType == piDontCopyList[iInd])
                CopyFl = FALSE;
              iInd++;
            } 
          if (CopyFl == TRUE)
            fiWriteAttr(pDestFile, 
                        (Attr_t *)pAttrBuff, 
                        iAttrType, 
                        iAttrLen, 
                        &iRc);
        } 
    } 
} 

INT32 ValidateFileType(char *pFileNameStr,char *IdStr,INT32 iLen,long lPos,
                       INT32 iType)
{
  FILE *fValFile;
  INT32 iBytesRead = 0;
  INT32 iRc = OK;
  char ReadValStr[100];

  fValFile = fopen(pFileNameStr, 
                   "rb");
  if (fValFile != NULL)
    {
      fseek(fValFile, 
            lPos, 
            SEEK_SET);
      iBytesRead = fread(ReadValStr, 
                         sizeof(char), 
                         iLen, 
                         fValFile);
      if ((iBytesRead != iLen) || (strncmp(ReadValStr, 
                                           IdStr, 
                                           iLen) != 0))
        {
          switch (iType)
            {
              case  BUFR_TYPE :
                iRc = BUFILLPROD;
                break;
              case  BUFR_PARAM_TYPE :
                iRc = BUFPARCONT;
                break;
              default  :
                iRc = NOK;
            } 
        } 
    } 
  else
    {
      switch (iType)
        {
          case  BUFR_TYPE :
            iRc = BUFFILNOTFND;
            break;
          case  BUFR_PARAM_TYPE :
            iRc = BUFPARNAME;
            break;
          default  :
            iRc = NOK;
        } 
    } 
  fclose(fValFile);
  return  iRc;
} 

