#include <string.h>
#include <stdio.h>
#include <stdlib.h>

//Atoms library
#include "stringa.h"

#include "wp2latex.h"
#include "raster.h"
#include "images/vecimage.h"
#include "images.h"
#include "cp_lib/cptran.h"

#include "wmfsupp.h"


DeviceContext_xMF & DeviceContext_xMF::operator=(const DeviceContext_xMF & BaseDC)
{
  PSS = BaseDC.PSS;
  MapMode = BaseDC.MapMode;
  MixMode = BaseDC.MixMode;
return *this;
}


////////////////////////////////////////////////


ObjectTable::ObjectTable(const ObjectTable &OT)
{
  if(OT.Count==0 || OT.Attributes==NULL)
  {
    Attributes = NULL;
AllocationError:
    Count = 0;
    return;
  }
  Attributes = (VectorAttribute**)malloc(OT.Count*sizeof(VectorAttribute*));
  if(Attributes==NULL) goto AllocationError;
  for(Count=0; Count<OT.Count; Count++)
  {
    Attributes[Count] = OT.Attributes[Count];
    if(Attributes[Count]!=NULL) Attributes[Count]->AddRef();
  }
}


ObjectTable::~ObjectTable()
{
  Erase();
}

void ObjectTable::Erase(void)
{
  if(Count>0)
  {
    if(Attributes!=NULL)
    {
      for(unsigned i=0; i<Count; i++)
      {
	if(Attributes[i] != NULL)
        {
          Attributes[i]->Release();
          Attributes[i] = NULL;
	}
      }
      free(Attributes);
      Attributes = NULL;
    }
    Count = 0;
  }
}


ObjectTable &ObjectTable::operator=(const ObjectTable &OT)
{
  if(&OT==this) return *this;

  Erase();
  if(OT.Count==0 || OT.Attributes==NULL) return *this;

  Attributes = (VectorAttribute**)malloc(OT.Count*sizeof(VectorAttribute*));
  if(Attributes==NULL) return *this;
  for(Count=0; Count<OT.Count; Count++)
  {
    Attributes[Count] = OT.Attributes[Count];
    if(Attributes[Count]!=NULL) Attributes[Count]->AddRef();
  }
return *this;
}


void ObjectTable::AddObject(VectorAttribute *NewAttr)
{
  if(NewAttr==NULL) return;

  if(Attributes==NULL || Count<=0)
  {
    Attributes = (VectorAttribute**)malloc(sizeof(VectorAttribute*));
    if(Attributes==NULL)
    {
      ReportNoMemory();
      NewAttr->Release();
      return;
    }
    Attributes[0] = NewAttr;
    Count = 1;
    //printf("\nAdded object at index #%u, ref count %u", 0, NewAttr->getRefCounter());  
    return;
  }

  for(unsigned i=0; i<Count; i++)
  {
    if(Attributes[i]==NULL)
    {
      Attributes[i] = NewAttr;
      //printf("\nAdded object at index #%u, ref count %u", i, NewAttr->getRefCounter());  
      return;
    }
  }

  Count++;
  VectorAttribute **tmp = (VectorAttribute**)realloc(Attributes, Count*sizeof(VectorAttribute*));
  if(tmp==NULL)		// memory exhausted, but Attributes contains original array.
    {ReportNoMemory();NewAttr->Release();return;}
  Attributes = tmp;
  Attributes[Count-1] = NewAttr;
  //printf("\nAdded object at index #%u, ref count %u", Count-1, NewAttr->getRefCounter()); 
}


void ObjectTable::DeleteObject(unsigned ObjectIndex)
{
  if(ObjectIndex>=Count || Attributes==NULL) return;
  if(Attributes[ObjectIndex]!=NULL)
  {
    //printf("\nDeleted object at index #%u, ref count %u", ObjectIndex, Attributes[ObjectIndex]->getRefCounter());  
    Attributes[ObjectIndex]->Release();
    Attributes[ObjectIndex] = NULL;
  }
}


const VectorAttribute *ObjectTable::GetObjectAt(unsigned ObjectIndex) const
{
  if(ObjectIndex>=Count || Attributes==NULL) return NULL;
  return Attributes[ObjectIndex];
}


////////////////////////////////////////////////

TconvertedPass1_Image::TconvertedPass1_Image(void)
{
  InitBBox(bbx);
}


TconvertedPass1_xMF::TconvertedPass1_xMF(void)
{
  NoConvertImage = 0;  
  YOffset = XOffset = 0;
  YExtent = XExtent = 0;
	// PSS has its own CTOR.
  PSS.FillPattern = FILL_SOLID;
  memset(&PSS.FillColor,0xFF,sizeof(PSS.FillColor));	// Default fill color should be white.
  PSS.LineStyle = 1;
  PSS.FontSizeW = PSS.FontSize = 1100/2.66f;		// Default font size [mm]
  PsNativeCP = GetTranslator("internalTOcp1276");
  PsNativeSym = GetTranslator("internalTOsymbol");

  DcList = NULL;
}


TconvertedPass1_xMF::~TconvertedPass1_xMF()
{
  while(DcList != NULL)
  {
    DeviceContextList *pOldDC = DcList;
    DcList = pOldDC->Next;
    delete pOldDC;
  }
}


void TconvertedPass1_Image::PutImageIncluder(const char *NewFilename)
{
  if(InputPS & IMG_graphicx)	//graphicx.sty
    {
    fprintf(strip," \\begin{center}");
    fprintf(strip,"\\includegraphics");
    fprintf(strip,"[width=\\textwidth]");
    fprintf(strip,"{\\FigDir/%s.eps}",NewFilename);
    fprintf(strip," \\end{center}");
    putc('\n',strip);  rownum++;
  }
  else if(InputPS & IMG_epsfig)	//epsfig.sty
    {
    fprintf(strip," \\begin{center}");
    fprintf(strip,"\\epsfig{file=\\FigDir/%s.eps,",NewFilename);
    fprintf(strip,"width=\\textwidth");
    putc('}',strip);
    fprintf(strip," \\end{center}");
    putc('\n',strip);  rownum++;
    }
  else if(InputPS & IMG_graphics)	//graphics.sty
    {
    fprintf(strip," \\begin{center}");
    fprintf(strip,"\\includegraphics");
    fprintf(strip,"{\\FigDir/%s.eps}",NewFilename);
    fprintf(strip," \\end{center}");
    putc('\n',strip);  rownum++;
    }
  else			//InputPS.sty
    {
    fprintf(strip,"\\begin{forcewidth}");
    fprintf(strip,"{\\textwidth}\n"); rownum++;
    fprintf(strip," \\begin{center}");
    fprintf(strip,"\\InputPS{\\FigDir/%s.eps}",NewFilename);
    putc('\n',strip);  rownum++;
    fprintf(strip," \\end{center}");
    putc('\n',strip);  rownum++;
    fprintf(strip,"\\end{forcewidth}\n");  rownum++;
    }
}


void TconvertedPass1_xMF::PushDC(void)
{
DeviceContextList *pNewDC = new DeviceContextList(*this);
  pNewDC->Next = DcList;
  DcList = pNewDC;
}


void TconvertedPass1_xMF::PopDC(void)
{
DeviceContextList *pOldDC = DcList;
  if(pOldDC != NULL)
  {    
    DcList = pOldDC->Next;

    *(DeviceContext_xMF*)this = *pOldDC;    
    delete pOldDC;
  }
  else
  {
    if(err != NULL)
        fprintf(err, _("\nError: DC stack is empty."));
  }
}
