/****************************************************************/
/*								*/
/* file.c:	file I/O					*/
/*								*/
/*		Design: Walter Benzing 1994			*/
/*								*/
/*		NO RIGHTS RESERVED				*/
/****************************************************************/

/* standard includes */

#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <setjmp.h>

/* my includes */

#include "xdim.h"

char *FI_StripFilename(char *fileName)
   {
    int i, len;
    char *cp;
    
    len = strlen(fileName);
    cp = fileName + len;
    for(i=0; i< len; i++)
       {
	if(*(--cp) == FILE_SEP)
	  break;
       }
    return(cp);
   }

/*
 * Save a preference file
 */

int FI_SavePref(XDimInfo *XDim)
   {
    FILE *out;
    XDColorInfo *XDC;
    int i;

    XDC = &(XDim->colors);
    out = fopen(XDC->pref, "w");
    if(out)
      {
       fprintf(out, "XDim preference file:\n");
       fprintf(out, "Window width: %d\n", XDC->wwidth);
       fprintf(out, "Window height: %d\n", XDC->wheight);
       fprintf(out, "Picture width: %d\n", XDC->pwidth);
       fprintf(out, "Picture height: %d\n", XDC->pheight);
       fprintf(out, "Fast Redraw: %s\n",
	RMethods[XT_GetRedrawIndex((funcCast)(XDim->FastRedraw), XDim)]);
       fprintf(out, "Normal Redraw: %s\n",
	RMethods[XT_GetRedrawIndex((funcCast)(XDim->NormalRedraw), XDim)]);
       fprintf(out, "Interpolate Colors: %d\n", XDC->interCol);
       fprintf(out, "Default foreground: %d\n", XDC->fore);
       fprintf(out, "Default background: %d\n", XDC->back);
       fprintf(out, "Text color: %d\n", XDC->textFore);
       fprintf(out, "Axis color: %d\n", XDC->axisFore);
       fprintf(out, "Axis background: X: %d   Y: %d   Z: %d\n",
		XDC->axisBackX, XDC->axisBackY, XDC->axisBackZ);
       fprintf(out, "Time interval: %ld\n", XDC->tInterval);
       fprintf(out, "Deco area from %d to %d\n", XDC->colS, XDC->colE);
       fprintf(out, "Color rows: %d\n", XDC->rowNum);
       for(i=0; i<XDC->rowNum; i++)
          {
           fprintf(out,"%d. START:  R: %d   G: %d   B: %d\n",
             (i+1),(XDC->beginR)[i], (XDC->beginG)[i], (XDC->beginB)[i]);
           fprintf(out,"   END:  R: %d   G: %d   B: %d   Depth: %d\n",
             (XDC->endR)[i], (XDC->endG)[i], (XDC->endB)[i], (XDC->colors)[i]);
           
          }
       fclose(out);
       return(OK);
      }
    else
      {
       sprintf(XDim->error, "Couldn't open %s for write access", XDC->pref);
       return(ERROR);
      }
   }

/*
 * Load a preference file
 */

int FI_LoadPref(XDimInfo *XDim)
   {
    FILE *in;
    XDColorInfo *XDC;
    XDHardwareInfo *HWI;
    char buf[MAX_NAME_LENGTH];
    char FRedraw[32], NRedraw[32];
    int i,dummy, rowNum, row, wanted, depth,status;
    int colS, colE, fore, back, textFore, axisFore, axisBX, axisBY, axisBZ;
    unsigned short sR, sG, sB, eR, eG, eB;
    unsigned long int tInterval;
    int interCol;
    void *redfunc;

    XDC = &(XDim->colors);
    HWI = &(XDim->hwInfo);
    in = fopen(XDC->pref, "r");
    if(in)
      {
       fgets(buf, MAX_NAME_LENGTH, in);
       if(strncmp(buf, "XDim preference file:\n", MAX_NAME_LENGTH))
	 {
	  strcpy(XDim->error, "No XDim preference file");
	  fclose(in);
          return(ERROR);
         }
       i=0;
       status = OK;
       fore = XDC->fore;
       back = XDC->back;
       textFore = XDC->textFore;
       axisFore = XDC->axisFore;
       axisBX = XDC->axisBackX;
       axisBY = XDC->axisBackY;
       axisBZ = XDC->axisBackZ;
       tInterval = XDC->tInterval;
       colS = XDC->colS;
       colE = XDC->colE;
       rowNum = 0;
       interCol = XDC->interCol;
       strcpy(FRedraw,RMethods[XT_GetRedrawIndex((funcCast)(XDim->FastRedraw),
	XDim)]);
       strcpy(NRedraw,RMethods[XT_GetRedrawIndex((funcCast)(XDim->NormalRedraw)
       , XDim)]);
       while(i<NUM_PREF && fgets(buf, MAX_NAME_LENGTH, in))
          {
	   if(*buf != '#')
	     {
	      if(!sscanf(buf, "Window width: %d", &(XDC->wwidth))
	        &&!sscanf(buf, "Window height: %d", &(XDC->wheight))
	        &&!sscanf(buf, "Picture width: %d", &(XDC->pwidth))
	        &&!sscanf(buf, "Picture height: %d", &(XDC->pheight))
		&&!sscanf(buf, "Fast Redraw: %s", FRedraw)
		&&!sscanf(buf, "Normal Redraw: %s", NRedraw)
		&&!sscanf(buf, "Interpolate Colors: %d", &interCol)
	        &&!sscanf(buf, "Default foreground: %d", &fore)
	        &&!sscanf(buf, "Default background: %d", &back)
		&&!sscanf(buf, "Text color: %d", &textFore)
		&&!sscanf(buf, "Axis color: %d", &axisFore)
		&&!sscanf(buf, "Axis background: X: %d   Y: %d   Z: %d",
		&axisBX, &axisBY, &axisBZ)
		&&!sscanf(buf, "Time interval: %ld", &tInterval)
		&&sscanf(buf, "Deco area from %d to %d",
			&colS, &colE) != 2
	        &&!sscanf(buf, "Color rows: %d", &rowNum))
	        {
		 sprintf(XDim->error, "Syntax error near:\n %s", buf);
		 status =ERROR;
		 break;
	        }
	      i++;
	     }
	  }
       row = 0;
       wanted = 0;
       for(i=0; i<rowNum;)
          {
	   if(*buf != '#')
	     {
              if(fgets(buf, MAX_NAME_LENGTH, in)
                 && sscanf(buf,"%d. START:  R: %hu   G: %hu   B: %hu",
        	    &dummy,&sR, &sG, &sB)==4
        	 && fgets(buf, MAX_NAME_LENGTH, in)
        	 && sscanf(buf,"   END:  R: %hu   G: %hu   B: %hu   Depth: %d\n",
        	    &eR, &eG, &eB, &depth))
        	{
		 if(depth >0)
		   {
        	    row++;
        	    wanted += depth;
        	    (XDC->colors)[i] = depth;
       		    (XDC->beginR)[i] = sR;
       		    (XDC->beginG)[i] = sG;
       		    (XDC->beginB)[i] = sB;
       		    (XDC->endR)[i] = eR;
       		    (XDC->endG)[i] = eG;
       		    (XDC->endB)[i] = eB;
		    i++;
       		   }
        	}
              else
        	{
        	 /* syntax error */
		 sprintf(XDim->error, "Syntax error near:\n %s", buf);
		 status = ERROR;
		 break;
        	}
	     }
          }
        if(row > 0)
          {
           XDC->rowNum = row;
           for(i=0; i< XDC->wantedColors; i++)
              if((HWI->colStat)[i])
                (HWI->colStat)[i] = HW_COLORCLAIMED;
           XDC->wantedColors = wanted;
          }
       if(colS >= XDC->wantedColors)
          XDC->colS = 0;
       else
          XDC->colS = colS;
       if(colE >= XDC->wantedColors)
          XDC->colE = XDC->wantedColors -1;
       else
          XDC->colE = colE;
       if(fore < XDC->wantedColors)
         XDC->fore = fore;
       else
         XDC->fore = 0;
       if(fore < XDC->wantedColors)
         XDC->back = back;
       else
         XDC->back = 1;
       if(textFore < XDC->wantedColors)
         XDC->textFore = textFore;
       else
         XDC->textFore = fore;
       if(axisFore < XDC->wantedColors)
         XDC->axisFore = axisFore;
       else
         XDC->axisFore = fore;
       if(axisBX < XDC->wantedColors)
         XDC->axisBackX = axisBX;
       else
         XDC->axisBackX = back;
       if(axisBY < XDC->wantedColors)
         XDC->axisBackY = axisBY;
       else
         XDC->axisBackY = back;
       if(axisBZ < XDC->wantedColors)
         XDC->axisBackZ = axisBZ;
       else
         XDC->axisBackZ = back;
       XDC->tInterval = tInterval;
       if((redfunc = XT_GetNamedRedraw(FRedraw, XDim)) != NULL)
	WD_SetFastRedraw(NULL, (funcCast)redfunc, NULL);
       if((redfunc = XT_GetNamedRedraw(NRedraw, XDim)) != NULL)
	WD_SetNormalRedraw(NULL, (funcCast)redfunc, NULL);
       XDC->interCol = interCol;
       fclose(in);
       return(status);
      }
    sprintf(XDim->error, "Couldn't open %s for read access", XDC->pref);
    return(ERROR);
   }

/*
 * Save a deco file
 */

int FI_SaveDeco(XDimInfo *XDim)
   {
    FILE *out;
    ViewportInfo *VWI;
    int i;
    myPixel *deco;

    if(XDim->port >=0)
      {
       VWI = &((XDim->Views)[XDim->port]);
       out = fopen(VWI->dfile, "w");
       if(out)
	 {
	  fprintf(out, "XDim deco file:\n");
	  fprintf(out, "Decoding entries: %d\n", MAX_DECO_NUMBER);
          deco = VWI->deco;
	  for(i=0; i<MAX_DECO_NUMBER; i++)
             {
              fprintf(out,"%d. %d\n",(i+1),*deco++);
             }
	  fclose(out);
	  return(OK);
	 }
       else
	 {
	  sprintf(XDim->error, "Couldn't open %s for write access", VWI->dfile);
	  return(ERROR);
	 }
      }
    strcpy(XDim->error, "No viewport available");
    return(ERROR);
   }

/*
 * Load a deco file
 */

int FI_LoadDeco(XDimInfo *XDim)
   {
    FILE *in;
    ViewportInfo *VWI;
    XDColorInfo *XDC;
    char buf[MAX_NAME_LENGTH], *status;
    int i, num, Sum, dummy;
    unsigned long buffer[MAX_DECO_NUMBER], *val, max;
    myPixel *deco;
    double fact;

    if(XDim->port >=0)
      {
       VWI = &((XDim->Views)[XDim->port]);
       in = fopen(VWI->dfile, "r");
       if(in)
	 {
	  fgets(buf, MAX_NAME_LENGTH, in);
	  if(strncmp(buf, "XDim deco file:\n", MAX_NAME_LENGTH))
	    {
	     strcpy(XDim->error, "No XDim decoding vector file");
	     fclose(in);
             return(ERROR);
            }
	  num = -1;
	  while(fgets(buf, MAX_NAME_LENGTH, in))
             {
	      if(*buf != '#')
		{
		 if(sscanf(buf, "Decoding entries: %d", &num))
		   break;
		 else
	           {
		    sprintf(XDim->error, "Syntax error near:\n %s", buf);
		    return(ERROR);
	           }
	        }
	     }
	  if(num < 0)
	    {
	     sprintf(XDim->error, "Couldn't find number of decoding enties");
	     return(ERROR);
	    }
	  if(num <= MAX_DECO_NUMBER)
	    {
	     Sum = MAX_DECO_NUMBER-1;
	     val = buffer;
	     for(i=0; i<MAX_DECO_NUMBER;i++)
	        {
	         Sum += num;
	         if(Sum >= MAX_DECO_NUMBER)
	           {
	            Sum -= MAX_DECO_NUMBER;
	            while(status=fgets(buf, MAX_NAME_LENGTH, in))
	              {
	               if(*buf != '#')
	                 {
		          if(sscanf(buf,"%d. %ld\n",&dummy,&max)==2)
		             break;
		          else
		            {
		             sprintf(XDim->error, "Syntax error near: %s", buf);
		             return(ERROR);
		            } 
		         }            
	              }
	            if(!status)
	              {
		       strcpy(XDim->error, "Unexpected EOF !!");
		       return(ERROR);
	              }
	           }
	         *val++ = max;
	        }
	    }
	  else
	    {
	     /* num > MAX_DECO_NUMBER */
	     Sum = num-1;
	     val = buffer;
	     for(i=0; i<num;)
	        {
	         if(!fgets(buf, MAX_NAME_LENGTH, in))
	           {
		    strcpy(XDim->error, "Unexpected EOF !!");
		    return(ERROR);
	           }
	         if(*buf != '#')
	           {
	            Sum += MAX_DECO_NUMBER;
	            if(Sum >= num)
	              {
	               Sum -= num;
		       if(sscanf(buf,"%d. %ld\n",&dummy,val)==2)
		         {
		          i++;
		          val++;
		         }
		       else
		         {
		          sprintf(XDim->error, "Syntax error near: %s", buf);
		          return(ERROR);
		         } 
	              }
	           }
	        }
	    }
          val = buffer;
          deco = VWI->deco;
          VWI->changed |= TRANS_AND_CHANGE;
	  XDC = &(XDim->colors);
	  max = *val;
          for(i=1; i<MAX_DECO_NUMBER; i++)
             {
              if(*val > max)
                max = *val;
              val++;
             }
          if(max > (XDC->wantedColors-1))
	    fact = ((double) (XDC->wantedColors-1))/max;
	  else
	    fact =1.0;
	  val = buffer;
	  for(i=0; i<MAX_DECO_NUMBER; i++)
	     *deco++ = (myPixel)(fact* *val++);
	  return(OK);
	 }
       else
	 {
	  sprintf(XDim->error, "Couldn't open %s for read access", VWI->dfile);
	  return(ERROR);
	 }
      }
    strcpy(XDim->error, "No viewport available");
    return(ERROR);
   }

/*
 * Save a data file
 */

int FI_SaveData(XDimInfo *XDim)
   {
    FILE *out;
    ViewportInfo *VWI;
    char *link2File;
    int i, Size, Num;
    double *dp;

    if(XDim->port >=0)
      {
       VWI = &((XDim->Views)[XDim->port]);
       if(VWI->actData == NULL)
         {
	  strcpy(XDim->error, "No data field available to save");
	  return(ERROR);
         }
       out = fopen(VWI->fileName, "w");
       if(out)
	 {
	  if(VWI->dataType)
	    fprintf(out, "XDim data file: Type %d\n", VWI->dataType);
	  else
	    fprintf(out, "XDim data file:\n");
	  fprintf(out, "Max X: %d\n", VWI->Width);
	  fprintf(out, "Max Y: %d\n", VWI->Height);
	  fprintf(out, "Dim X: %s\n", VWI->DimX);
	  fprintf(out, "Dim Y: %s\n", VWI->DimY);
	  fprintf(out, "Dim Z: %s\n", VWI->DimZ);
	  fprintf(out, "Offset X: %e\n", VWI->OffX);
	  fprintf(out, "Form Factor X: %e\n", VWI->FactX);
	  fprintf(out, "Offset Y: %e\n", VWI->OffY);
	  fprintf(out, "Form Factor Y: %e\n", VWI->FactY);
	  if(XDim->useLinks && VWI->links >0)
	    {
	     fprintf(out,"links:\n");
	     Num = 1;
	     for(i=0;i<VWI->links;i++)
		{
		 link2File = ((XDim->Views)[(VWI->Link2)[i]]).fileName;
		 if(*link2File != '\0')
	            fprintf(out,"link %d: %s to %s in %s\n", Num++,
			(VWI->LinkItself)[i], (VWI->LinkName)[i], link2File);
		}
	    }
	  fprintf(out, "Data:\n");
	  Size = VWI->Width * VWI->Height;
	  dp = VWI->actData;
	  for(i=0; i<Size; i++)
             {
              fprintf(out,"%e\n",*dp++);
             }
	  fclose(out);
	  return(OK);
	 }
       else
	 {
	  sprintf(XDim->error, "Couldn't open %s for write access", VWI->fileName);
	  return(ERROR);
	 }
      }
    strcpy(XDim->error, "No viewport available");
    return(ERROR);
   }

/*
 * Load a data file
 */

int FI_LoadData(XDLinks *hLinks, XDimInfo *XDim)
   {
    FILE *in;
    ViewportInfo *VWI;
    char buf[MAX_NAME_LENGTH+2*MAX_LINK_LENGTH+16];
    unsigned char *cp, cin;
    int Size, i, NewWidth, NewHeight, dataType, dum;
    char DimX[MAX_DIM_LENGTH], DimY[MAX_DIM_LENGTH], DimZ[MAX_DIM_LENGTH];
    double val, *dp, FactX, FactY,OffX,OffY;

    if(XDim->port >=0)
      {
       VWI = &((XDim->Views)[XDim->port]);
       if(VWI->edit && VWI->port == XDim->aView.edPort)
         XDim->aView.edPort = -1;
       in = fopen(VWI->fileName, "r");
       if(in)
	 {
	  fgets(buf, MAX_NAME_LENGTH, in);
	  if(strncmp(buf, "XDim data file\n", 9))
	    {
	     strcpy(XDim->error, "No XDim data file");
	     fclose(in);
             return(ERROR);
            }
          dataType = MY_DOUBLE;
          sscanf(buf,"XDim data file: Type %d", &dataType);
	  i= 0;
	  NewWidth = 2;
	  NewHeight = 2;
	  DimX[0] = '\0';
	  DimY[0] = '\0';
	  DimZ[0] = '\0';
	  FactX = 1.0;
	  FactY = 1.0;
	  OffX = 0.0;
	  OffY = 0.0;
          VWI->links = 0;
          if(hLinks != NULL)
            {
             hLinks->links = 0;
	     *((hLinks->hLinks)[0]).Itself = '\0';
	     *((hLinks->hLinks)[0]).LinkName = '\0';
	     *((hLinks->hLinks)[0]).Link2File = '\0';
	    }
	  while(i<NUM_DATA && fgets(buf, MAX_NAME_LENGTH, in))
             {
	      if(*buf != '#')
		{
		 if(!sscanf(buf,"Max X: %d" , &NewWidth)
	           &&!sscanf(buf, "Max Y: %d", &NewHeight)
	           &&!sscanf(buf, "Dim X: %s", DimX)
	           &&!sscanf(buf, "Dim Y: %s", DimY)
	           &&!sscanf(buf, "Dim Z: %s", DimZ)
	           &&!sscanf(buf, "Offset X: %le", &OffX)
	           &&!sscanf(buf, "Form Factor X: %le", &FactX)
	           &&!sscanf(buf, "Offset Y: %le", &OffY)
	           &&!sscanf(buf, "Form Factor Y: %le", &FactY))
	           {
		    sprintf(XDim->error, "Syntax error near:\n %s", buf);
		    return(ERROR);
	           }
		 i++;
		}
	     }
	  if(i!=NUM_DATA)
	    {
	     strcpy(XDim->error, "Some information missing in data file");
	     return(ERROR);
	    }
	  if(CO_NewData(NewWidth, NewHeight, dataType, XDim))
	    return(ERROR);
	
	  Size = NewWidth*NewHeight;
	  i = 0;
	  strcpy(VWI->DimX, DimX);
	  strcpy(VWI->DimY, DimY);
	  strcpy(VWI->DimZ, DimZ);
	  VWI->FactX = FactX;
	  VWI->FactY = FactY;
	  VWI->OffX = OffX;
	  VWI->OffY = OffY;
	  if(NewWidth > NewHeight)
	    {
	     if(VWI->gNum > NewHeight)
	       VWI->gNum = NewHeight;
	     if(VWI->gStep > NewHeight)
	       VWI->gStep = NewHeight >> 2;
	    }
	  else
	    {
	     if(VWI->gNum > NewWidth)
	       VWI->gNum = NewWidth;
	     if(VWI->gStep > NewWidth)
	       VWI->gStep = NewWidth >> 2;
	    }
	  if(VWI->gStep == 0)
	    VWI->gStep = 1;
	  while(fgets(buf, MAX_NAME_LENGTH, in) != NULL &&
		strncmp(buf, "Data:", 4))
	      {
               if(hLinks != NULL && hLinks->links < MAX_VIEWPORT_NUMBER &&
		sscanf(buf, "link %d: %s to %s in %s", &dum,
			((hLinks->hLinks)[hLinks->links]).Itself,
			((hLinks->hLinks)[hLinks->links]).LinkName,
			((hLinks->hLinks)[hLinks->links]).Link2File))
		 {
		  (hLinks->links)++;
		  if(hLinks->links < MAX_VIEWPORT_NUMBER)
		    {
		     *((hLinks->hLinks)[hLinks->links]).Itself = '\0';
		     *((hLinks->hLinks)[hLinks->links]).LinkName = '\0';
		     *((hLinks->hLinks)[hLinks->links]).Link2File = '\0';
		    }
		 }
	      }

	  /* Now read data in according to the type */

	  switch (dataType)
             {
              case MY_UCHAR:
	      cp = VWI->charData;
              while(i < Size && fgets(buf, MAX_NAME_LENGTH, in) != NULL)
        	  {
        	   if(sscanf(buf, "%cu", &cin))
                     {
                      i++;
                      *cp++ = cin;
                     }
        	  }
              break;
              default:
	      dp = VWI->actData;
              while(i < Size && fgets(buf, MAX_NAME_LENGTH, in) != NULL)
        	  {
        	   if(sscanf(buf, "%le", &val))
                     {
                      i++;
                      *dp++ = val;
                     }
        	  }
	      break;
	     }
	  if(i!=Size)
	    {
	     strcpy(XDim->error, "Unexpected EOF !!");
	     return(ERROR);
	    }
	  else
	    return(OK);
	 }
       else
	 {
	  sprintf(XDim->error, "Couldn't open %s for read access", VWI->fileName);
	  return(ERROR);
	 }
      }
    strcpy(XDim->error, "No viewport available");
    return(ERROR);
   }

/*
 * Process buffer for ASCII import
 */

void FI_ProcASCIIBuf(char *s, int max)
   {
    char ch, *sp;
    int i;
    
    sp = s;
    for(i= 0; i<max; i++)
       {
        ch = *sp++;
        if(ch == '\0')
          break;
        if(ch == ',')
          {
           if(isdigit(*sp) || (i>0 && isdigit(*(sp-2))))
              *(sp-1) = '.';
          }
       }
    
   }

/*
 * Get next number from ASCII buffer
 */

char *FI_GetNextNum(char *s, double *val)
   {
    char ch, *sp;
    
    do
      {
       sp = strpbrk(s, "+-.0123456789");
      }
    while(sp != NULL && !sscanf(sp, "%le", val));
    if(sp !=NULL)
      {
       while((ch = *sp)!='\0')
          {
           if(ch == ' ' || ch == ',' || ch == ';' || ch == '\t' || ch == ':')
	      break;
	   sp++;             
          }
      }
    return(sp);
   }

/*
 * Import an ASCII data file
 */

int FI_ImportAsciiData(XDimInfo *XDim)
   {
    FILE *in;
    ViewportInfo *VWI;
    XDColorInfo *XDC;
    char *sp, buf[4*MAX_NAME_LENGTH];
    int Size, i, j, NewWidth, NewHeight, dataType;
    double val, *dp, Repl;

    if(XDim->port >=0)
      {
       VWI = &((XDim->Views)[XDim->port]);
       XDC = &(XDim->colors);
       in = fopen(VWI->fileName, "r");
       if(in)
	 {
	  dataType = MY_DOUBLE;
	  NewWidth = 0;
	  NewHeight = 0;
	  strcpy(VWI->DimX, "XXX");
	  strcpy(VWI->DimY, "XXX");
	  strcpy(VWI->DimZ, "XXX");
	  VWI->FactX = 1.0;
	  VWI->FactY = 1.0;
	  VWI->OffX = 0.0;
	  VWI->OffY = 0.0;
          VWI->links = 0;
          while(fgets(buf, MAX_NAME_LENGTH, in) != NULL)
              {
               if(*buf != '#')
                 {
                  if(XDC->GerNot == True)
                    FI_ProcASCIIBuf(buf, MAX_NAME_LENGTH);
                  sp = buf;
                  if(NewWidth)
                    {
                     if(FI_GetNextNum(sp, &val) != NULL)
                       NewHeight++;
                    }
                  else
                    {
                     while((sp=FI_GetNextNum(sp, &val)) != NULL)
                        NewWidth++;
                     if(NewWidth != 0)
                        NewHeight++;
                    }
                 }
              }
	  Size = NewWidth*NewHeight;
	  if(Size == 0)
	    {
	     strcpy(XDim->error, "Sorry couldn't import this format !!");
	     return(ERROR);
	    }
	  if(CO_NewData(NewWidth, NewHeight, dataType, XDim))
	    return(ERROR);
	  if(NewWidth > NewHeight)
	    {
	     if(VWI->gNum > NewHeight)
	       VWI->gNum = NewHeight;
	     if(VWI->gStep > NewHeight)
	       VWI->gStep = NewHeight >> 2;
	    }
	  else
	    {
	     if(VWI->gNum > NewWidth)
	       VWI->gNum = NewWidth;
	     if(VWI->gStep > NewWidth)
	       VWI->gStep = NewWidth >> 2;
	    }
	  if(VWI->gStep == 0)
	    VWI->gStep = 1;
	  Repl = XDC->Repl;
	  dp = VWI->actData;
          rewind(in);
          for(i= 0; i< NewHeight; i++)
             {
              fgets(buf, MAX_NAME_LENGTH, in);
              if(*buf != '#')
                {
                 sp = buf;
                 if(XDC->GerNot == True)
                    FI_ProcASCIIBuf(buf, MAX_NAME_LENGTH);
                 if((sp=FI_GetNextNum(sp, &val)) != NULL)
                   {
                    *dp++ = val;
                    for(j=1; j< NewWidth; j++)
                       {
                	if((sp=FI_GetNextNum(sp, &val)) == NULL)
                	  val = Repl;
                	*dp++ = val;
                       }
                   }
                 else
                   i--;
                }
              else
                i--;
             }
	  return(OK);
	 }
       else
	 {
	  sprintf(XDim->error, "Couldn't open %s for read access", VWI->fileName);
	  return(ERROR);
	 }
      }
    strcpy(XDim->error, "No viewport available");
    return(ERROR);
   }


/*
 * Export an ASCII data file
 */

int FI_AsciiExportData(char *FName, XDimInfo *XDim)
   {
    FILE *out;
    ViewportInfo *VWI;
    XDColorInfo *XDC;
    int i, j;
    double *dp;
    char buf[MAX_NAME_LENGTH], *sp;

    if(XDim->port >=0)
      {
       VWI = &((XDim->Views)[XDim->port]);
       XDC = &(XDim->colors);
       if(VWI->actData == NULL)
         {
	  strcpy(XDim->error, "No data field available to save");
	  return(ERROR);
         }
       out = fopen(FName, "w");
       if(out)
	 {
	  fprintf(out, "#Max X: %d\n", VWI->Width);
	  fprintf(out, "#Max Y: %d\n", VWI->Height);
	  fprintf(out, "#Dim X: %s\n", VWI->DimX);
	  fprintf(out, "#Dim Y: %s\n", VWI->DimY);
	  fprintf(out, "#Dim Z: %s\n", VWI->DimZ);
	  fprintf(out, "#Offset X: %e\n", VWI->OffX);
	  fprintf(out, "#Form Factor X: %e\n", VWI->FactX);
	  fprintf(out, "#Offset Y: %e\n", VWI->OffY);
	  fprintf(out, "#Form Factor Y: %e\n", VWI->FactY);
	  fprintf(out, "#Data:\n");
	  dp = VWI->actData;
          if(XDC->GerNot)
            {
	     for(i=0; i<VWI->Height; i++)
        	{
        	 for(j=0; j < VWI->Width; j++)
                    {
                     sprintf(buf, "\t%e", *dp++);
                     sp = strchr(buf, '.');
                     if(sp != NULL)
                       *sp = ',';
                     fputs(buf, out);
                    }
                  fputc('\n', out);
                 }
             }
           else
             {
	      for(i=0; i<VWI->Height; i++)
        	 {
        	  for(j=0; j < VWI->Width; j++)
                    {
                     fprintf(out,"\t%e",*dp++);
                    }
                  fputc('\n', out);
                 }
             }
	  fclose(out);
	  return(OK);
	 }
       else
	 {
	  sprintf(XDim->error, "Couldn't open %s for write access", FName);
	  return(ERROR);
	 }
      }
    strcpy(XDim->error, "No viewport available");
    return(ERROR);
   }


/*
 * Export a GIF data picture
 */

int FI_GifExportPic(char *FName, XDimInfo *XDim)
   {
    ViewportInfo *view;
    XDColorInfo *XDC;
    XDHardwareInfo *HWI;
    int *red, *green, *blue, *r, *g, *b, Size, bpp, intrlce, back, i;

    if(XDim->port >=0)
      {
       view = &((XDim->Views)[XDim->port]);
       XDC = &(XDim->colors);
       HWI = &(XDim->hwInfo);
       if(view->pict == NULL)
         {
	  strcpy(XDim->error, "No picture available to export");
	  return(ERROR);
         }
       bpp = (sizeof(myPixel)) << CHAR2BITS;
       for(i=1; i <= bpp; i++)
          {
           Size = 1 << i;
           if(Size >= XDC->wantedColors)
             break;
          }
       if(Size > 256)
         {
	  strcpy(XDim->error,
		"To export gif pictures you have to use less then 256 colors");
	  return(ERROR);
         }
       bpp = i;
       Size *= sizeof(int);
       red = (int*) malloc(Size);
       green = (int*) malloc(Size);
       blue = (int*) malloc(Size);
       if(red == NULL || green == NULL || blue == NULL)
         {
          free(red);
          free(green);
          free(blue);
	  strcpy(XDim->error, "Not enough memory to allocate colormap");
	  return(ERROR);
         }
       r = red;
       g = green;
       b = blue;
       for(i=0;i<XDC->wantedColors; i++)
          {
           *r++ = (int) (HWI->red)[i];
           *g++ = (int) (HWI->green)[i];
           *b++ = (int) (HWI->blue)[i];
          }
       intrlce = False;
       back = view->back;
       GIFEncode(FName, view->pwidth, view->pheight, intrlce, back,
		bpp, red, green, blue, GR_ReadPixel);
       return(OK);
      }
    strcpy(XDim->error, "No viewport available");
    return(ERROR);
   }


/* These static variables are needed by GIFerror */

static jmp_buf setjmp_buffer;	/* for return to caller */

static unsigned char *FI_GifPic;
static int FI_GifPWidth;

/*
 * Report GIF import error
 */

void FI_GIFerror(char *s1, char *s2)
  {
   extern XDimInfo XDim;

   if(s2 != NULL)
     sprintf(XDim.error, s1, s2);
   else
     strcpy(XDim.error, s1);
   WD_XDimError(&XDim, NULL);
   GIFfreeAll();
   longjmp(setjmp_buffer, 1);	/* return control to outer routine */
  }

/*
 * Allocate memory to store values
 */

int FI_MemAlloc(int width, int height)
  {
   int ret;
   ViewportInfo *view;
   extern XDimInfo XDim;

   if(CO_NewData(width, height, MY_UCHAR, &XDim))
     ret = False;
   else
     {
      ret = True;
      view = &((XDim.Views)[XDim.port]);
      FI_GifPic = view->charData;
      FI_GifPWidth = view->Width;
     }
   return(ret);
  }

/*
 * Write the value at x,y
 */

int FI_WriteValue(int x, int y, int index)
  {
   *(FI_GifPic+y*FI_GifPWidth+x) = (unsigned char)index;
   return(TRUE);
  }

/*
 * Import a gif picture
 */

int FI_ImportGifPic(XDimInfo *XDim)
   {
    ViewportInfo *view;
    XDColorInfo *XDC;
    XDHardwareInfo *HWI;
    int i, rows, num_colors, ind1, ind2;
    unsigned short dum;
    unsigned char red[256], green[256], blue[256];

    if(XDim->port >=0)
      {
       view = &((XDim->Views)[XDim->port]);
       XDC = &(XDim->colors);
       HWI = &(XDim->hwInfo);
       if (setjmp(setjmp_buffer))
          {
  /* If we get here, the GIF code has signaled an error. */
	   return(ERROR);
	  }
       GIFdecode(view->fileName, red, green, blue, &num_colors, &(view->Width),
       &(view->Height), FI_MemAlloc, FI_WriteValue, FI_GIFerror);
       rows = 0;
       for(i=0; i<num_colors >>1; i++)
          {
           (XDC->colors)[i] = 2;
           ind1 = i<<1;
           ind2 = (i<<1)+1;
	   dum =  red[ind1];
       	   (XDC->beginR)[i] = (dum<<8)|dum;
	   dum =  green[ind1];
       	   (XDC->beginG)[i] = (dum<<8)|dum;
	   dum = blue[ind1];
       	   (XDC->beginB)[i] = (dum<<8)|dum;
	   dum =  red[ind2];
       	   (XDC->endR)[i] = (dum<<8)|dum;
	   dum =  green[ind2];
       	   (XDC->endG)[i] = (dum<<8)|dum;
	   dum =  blue[ind2];
       	   (XDC->endB)[i] = (dum<<8)|dum;
       	   rows++;
          }
       XDC->rowNum = rows;
       GR_InitColorImport( num_colors, XDC, HWI);
       strcpy(view->DimX, "pixel");
       strcpy(view->DimY, "pixel");
       strcpy(view->DimZ, "color");
       view->FactX = 1.0;
       view->FactY = 1.0;
       view->OffX = 0.0;
       view->OffY = 0.0;
       view->links = 0;
       return(OK);
      }
    strcpy(XDim->error, "No viewport available");
    return(ERROR);
   }

/*
 * Remove Links after a viewport was deleted
 */

void FI_RemoveWasteLinks(int ViewNum, XDimInfo *XDim)
   {
    ViewportInfo *view;
    int i, j;

    for(i=0; i<MAX_VIEWPORT_NUMBER; i++)
       {
        view = &((XDim->Views)[i]);
        if(view->pict != NULL)
          {
           for(j=0; j<view->links; j++)
              {
               if((view->Link1)[j] == ViewNum || (view->Link2)[j] == ViewNum)
                  FI_DeleteLink(j, view, XDim);
              }
          }
       }
   }


/*
 * Delete a link from viewport
 */
   
void FI_DeleteLink(int ViewNum, ViewportInfo *view, XDimInfo *XDim)
   {
    int Num;

    for(Num= ViewNum+1; Num<view->links; Num++)
       {
	strncpy((view->LinkItself)[Num-1],
		(view->LinkItself)[Num], MAX_LINK_LENGTH);
	strncpy((view->LinkName)[Num-1],
		(view->LinkName)[Num], MAX_LINK_LENGTH);
	(view->Link1)[Num-1] = (view->Link1)[Num];
	(view->Link2)[Num-1] = (view->Link2)[Num];
       }
    if(view->links > 0)
      (view->links)--;
    view->actLink = view->links -1;
   }

/*
 * Return the port number to the link desciption
 */
 
int FI_GetLink(char *name, ViewportInfo *view, XDimInfo *XDim)
  {
   int i, port;
   
   port = -1;
   for(i=0; i<view->links; i++)
      {
       if(!strncmp((view->LinkName)[i], name, MAX_LINK_LENGTH))
         {
          port = (view->Link2)[i];
          break;
         }       
       if(!strncmp((view->LinkItself)[i], name, MAX_LINK_LENGTH))
         {
          port = (view->Link1)[i];
          break;
         }       
      }
   if(port <0)
     sprintf(XDim->error, "Could not locate a link described as %s !", name);
   return(port);
  }

/*
 * Add link to viewport
 */

void FI_AddLink(int from, int to, char *fromName, char *toName, XDimInfo *XDim)
  {
   ViewportInfo *view1, *view2;
   int Num;
   
   view1 = &((XDim->Views)[from]);
   view2 = &((XDim->Views)[to]);
   Num = view1->links;
   strncpy((view1->LinkItself)[Num], fromName, MAX_LINK_LENGTH);
   strncpy((view1->LinkName)[Num], toName, MAX_LINK_LENGTH);
   (view1->Link1)[Num] = from;
   (view1->Link2)[Num] = to;
   (view1->links)++;
   Num = view2->links;
   strncpy((view2->LinkItself)[Num], toName, MAX_LINK_LENGTH);
   strncpy((view2->LinkName)[Num], fromName, MAX_LINK_LENGTH);
   (view2->Link2)[Num] = from;
   (view2->Link1)[Num] = to;
   (view2->links)++;
  }
