/*
 *  CELLS       An Implementation of the WireWorld cellular automata
 *              as described in Scientific American, Jan 1990.
 *
 *              Copyright 1990 by Davide P. Cervone.
 *  You may use this code, provided this copyright notice is kept intact.
 *  See the CELLS.HELP file for complete information on distribution conditions.
 */

/*
 *  File:  cWrite.c         Handles writing of Circuit and Library files.
 */


#include "cGadget.h"
#include "cRequest.h"
#include "cParts.h"
#include <stdio.h>

extern char FileName[MAXFNAME];     /* the name in the File Requester */

static FILE *theFile;               /* the current file being written */
static int noError;                 /* TRUE if no errors while writing */
static char Line[256];              /* output buffer */

static short BoundsX,BoundsY,BoundsW,BoundsH;       /* size of circuit */

/* the characters to use for each cell state number */
/*  BLANK = '. '  TAIL = '=='  HEAD = '##'  WIRE = '[]' */

static char *CellSymbol[] = {"  ","  ","  ",". ","==","##","  ","[]"};


/*
 *  Write()
 *
 *  If no errors have occured,
 *    Format the outpu string and send it to the file
 *    If something went wrong, give an error, and note that one occurred
 */

void Write(s,x1,x2,x3,x4,x5)
char *s,*x1,*x2,*x3,*x4,*x5;
{
   char Line[132];

   if (noError)
   {
      sprintf(Line,s,x1,x2,x3,x4,x5);
      if (fputs(Line,theFile))
      {
         DosError("Write","Line");
         noError = FALSE;
      }
   }
}


/*
 *  WriteGrid()
 *
 *  For each cell in the specified patch
 *    Set the next characters in the output line to the proper symbols
 *    Trim any trailing spaces on each line, and add a newline at the end
 *    Send the line to the file, and check for errors
 */

static void WriteGrid(Grid,x,y,w,h,GridWidth)
UBYTE Grid[];
short x,y,w,h;
short GridWidth;
{
   register short i,j;
   register short X,Y;
   char Line[256];
   
   w += x; h += y;
   for (Y=y; Y<h && noError; Y++)
   {
      for (X=x,i=X+GridWidth*Y,j=0; X<w; X++,i++)
      {
         Line[j++] = CellSymbol[Grid[i]][0];
         Line[j++] = CellSymbol[Grid[i]][1];
      }
      while (j>0 && Line[--j] == ' ');
      Line[++j] = '\n'; Line[++j] = 0;
      if (fputs(Line,theFile))
      {
         DosError("Write","Line");
         noError = FALSE;
      }
   }
}


/*
 *  WriteCurGen()
 *
 *  Copy the contents of the current generation into the scratch array
 *  Clear any blank cells to zeros (won't be written to file)
 *  Write the contents of the grid to the file
 */

static void WriteCurGen()
{
   register short i;

   CopyGrid(CurGen,NewGen);
   for (i=0; i<ARRAYSIZE; i++) if (NewGen[i] == BLANK) NewGen[i] = 0;
   WriteGrid(NewGen,BoundsX,BoundsY,BoundsW,BoundsH,MAXGRIDW);
}


/*
 *  WriteParts()
 *
 *  For each part in the Parts List
 *    write the part name and its defining data
 *    go on to the nect part
 */

static void WriteParts()
{
   PART *thePart = PartsList.FirstPart;
   
   while (thePart)
   {
      Write("\n\nPart %s\n\n",thePart->Name);
      WriteGrid(thePart->Data,0,0,thePart->w,thePart->h,thePart->w);
      thePart = thePart->Next;
   }
}

/*
 *  WriteLibraries()
 *
 *  If there are libraries other than the parts list include a litle space
 *    For each library in the list
 *      if the library is not the parts list write it to the file
 *      go on to the next library
 */

static void WriteLibraries()
{
   LIBRARY *theLibrary = FirstLibrary;
   
   if (FirstLibrary->Next) Write("\n\n"); 
   while (theLibrary)
   {
      if (theLibrary != &PartsList)
         Write("Include %s\n",theLibrary->Name);
      theLibrary = theLibrary->Next;
   }
}


/*
 *  CloseFile()
 *
 *  close the file, and clear the file pointer
 *  if an error occured while writing the file
 *    ask if the user want to keep the file on disk any way
 *    if no, try to delete the file.
 */

static void CloseFile(Name)
char *Name;
{
   fclose(theFile);
   theFile = NULL;
   if (noError == FALSE)
   {
      if (DoQuestion("File not Completely Written: Delete it?"))
         if (DeleteFile(Name) == FALSE) DosError("Delete","File");
   }
}


/*
 *  WriteFile()
 *
 *  If the specified file can be opened for writing
 *    clear the error flag
 *    if the save-as-library gadget was checked
 *      put up a message about writing a library
 *      indicate that the file is a library
 *      write the parts list to the library
 *    otherwise if a selection is in effect
 *      put up a message about writing a selection
 *      get the circuits size
 *      write the pertinent data about the seleted part
 *      write its data
 *    otherwise
 *      put up a message about writing a circuit
 *      get the size of the whole circuit
 *      write the pertinent data about the circuit
 *      write the circuit to the file
 *      write its parts list and library list
 *    clear the info message
 *    close the file
 *    if no error occured and we were writing a circuit
 *      set the UNDO and RESET arrays
 *      save the circuit's name and clear the changes flag
 *  Otherwise (can't open the file)
 *    report the error message
 *  Put the SAVE button back to normal
 */

void WriteFile(Name,Check)
char *Name;
int Check;
{
   if (theFile = fopen(Name,"w"))
   {
      noError = TRUE;
      if (Check)
      {
         DoInfoMessage("Writing Library '%s'",Name);
         Write("Library %s\n",Name);
         WriteParts();
      } else if (SelectType) {
         DoInfoMessage("Writing Selection '%s'",Name);
         GetBounds(NewGen,&BoundsX,&BoundsY,&BoundsW,&BoundsH,0);
         Write("Circuit %s\n",Name);
         Write("CellSize %d\n",CellSize);
         Write("Origin %d %d\n",BoundsX,BoundsY);
         Write("View %d %d\n",GridX,GridY);
         Write("\n");
         WriteGrid(NewGen,BoundsX,BoundsY,BoundsW,BoundsH,MAXGRIDW);
      } else {
         DoInfoMessage("Writing Circuit '%s'",Name);
         GetBounds(CurGen,&BoundsX,&BoundsY,&BoundsW,&BoundsH,BLANK);
         Write("Circuit %s\n",Name);
         Write("CellSize %d\n",CellSize);
         Write("Origin %d %d\n",BoundsX,BoundsY);
         Write("View %d %d\n",GridX,GridY);
         Write("\n");
         WriteCurGen();
         WriteParts();
         WriteLibraries();
      }
      ClearInfoMessage();
      CloseFile(Name);
      if (noError && Check == 0 && SelectType == SEL_NONE)
      {
         CopyGrid(CurGen,UndoArray);
         CopyGrid(CurGen,ResetArray);
         strcpy(FileName,Name);
         Changed = FALSE;
      }
   } else {
      DosError("Write","File");
   }
   InvertGadget(&cGadget[ID_SAVE]);
}
