/******************************************************************************
 * program:     wp2latex                                                      *
 * function:    Convert WordPerfect files into LaTeX.			      *
 * modul:       pass1wmf.cc                                                   *
 * description: Opens Windows MetaFile.					      *
 * libraries:	cole   (modified for wp2latex)				      *
 * licency:     GPL		                                              *
 ******************************************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

//Atoms library
#include <strings.h>

#include "wp2latex.h"
#include "cole/cole.h"
#include"images/raster.h"


void WMF_STRETCHDIB(Image &Img, FILE *f, DWORD ParamFilePos);
int SavePictureEPS(const char *Name,const Image &Img);
string CutFileName(const char *FullFilename); //from wp2lfuti.cc


class TconvertedPass1_WMF: public TconvertedPass1
     {
protected:
     int NoConvertImage;

public:
     TconvertedPass1_WMF(void): NoConvertImage(0) {};

     virtual int Convert_first_pass(void);
     virtual int Dispatch(int FuncNo, ...);

     Image Img;
     };

/*Register translators here*/
TconvertedPass1 *Factory_WMF(void) {return new TconvertedPass1_WMF;}
FFormatTranslator FormatWMFWrapper("WMF",Factory_WMF);

typedef struct _WindowsMetaHeader
{
  WORD  FileType;       /* Type of metafile (0=memory, 1=disk) */
  WORD  HeaderSize;     /* Size of header in WORDS (always 9) */
  WORD  Version;        /* Version of Microsoft Windows used */
  DWORD FileSize;       /* Total size of the metafile in WORDs */
  WORD  NumOfObjects;   /* Number of objects in the file */
  DWORD MaxRecordSize;  /* The size of largest record in WORDs */
  WORD  NumOfParams;    /* Not Used (always 0) */
} WMFHEAD;


typedef struct _StandardMetaRecord
{
    DWORD Size;          /* Total size of the record in WORDs */
    WORD  Function;      /* Function number (defined in WINDOWS.H) */
    DWORD ParamFilePos;
    //WORD  Parameters[];  /* Parameter values passed to function */
} WMFRECORD;


inline long LoadWMFHeader(FILE *f, _WindowsMetaHeader & SU)
{
#if defined(__PackedStructures__)
return(fread(&SU,1,sizeof(_WindowsMetaHeader),f));
#else
return(loadstruct(f,"wwwdwdw",&SU.FileType,&SU.HeaderSize,
	&SU.Version,&SU.FileSize,&SU.NumOfObjects,&SU.MaxRecordSize,&SU.NumOfParams));
#endif
}


inline _StandardMetaRecord *LoadWmfRecord(FILE *f)
{
DWORD Size;
_StandardMetaRecord *WmfRec;

  Rd_dword(f,&Size);
  if(feof(f) || Size<3) return NULL;
  WmfRec=(_StandardMetaRecord *)malloc(sizeof(_StandardMetaRecord));
  WmfRec->Size=Size;
  Rd_word(f,&WmfRec->Function);
  WmfRec->ParamFilePos = ftell(f);
/*
  for(Size=0;Size<WmfRec->Size-3;Size++)
    {
    Rd_word(f,&WmfRec->Parameters[Size]);
    }
*/
  return(WmfRec);
}


typedef struct _EnhancedMetaHeader
{
    DWORD   RecordType;       /* Record type */
    DWORD   RecordSize;       /* Size of the record in bytes */
    SDWORD  BoundsLeft;       /* Left inclusive bounds */
    SDWORD  BoundsRight;      /* Right inclusive bounds */
    SDWORD  BoundsTop;        /* Top inclusive bounds */
    SDWORD  BoundsBottom;     /* Bottom inclusive bounds */
    SDWORD  FrameLeft;        /* Left side of inclusive picture frame */
    SDWORD  FrameRight;       /* Right side of inclusive picture frame */
    SDWORD  FrameTop;         /* Top side of inclusive picture frame */
    SDWORD  FrameBottom;      /* Bottom side of inclusive picture frame */
    DWORD   Signature;        /* Signature ID (always 0x464D4520) */
    DWORD   Version;          /* Version of the metafile */
    DWORD   Size;             /* Size of the metafile in bytes */
    DWORD   NumOfRecords;     /* Number of records in the metafile */
    WORD    NumOfHandles;     /* Number of handles in the handle table */
    WORD    Reserved;         /* Not used (always 0) */
    DWORD   SizeOfDescrip;    /* Size of description string in WORDs */
    DWORD   OffsOfDescrip;    /* Offset of description string in metafile */
    DWORD   NumPalEntries;    /* Number of color palette entries */
    SDWORD  WidthDevPixels;   /* Width of reference device in pixels */
    SDWORD  HeightDevPixels;  /* Height of reference device in pixels */
    SDWORD  WidthDevMM;       /* Width of reference device in millimeters */
    SDWORD  HeightDevMM;      /* Height of reference device in millimeters */
} ENHANCEDMETAHEADER;


/*
static WORD ParU16(_StandardMetaRecord *WmfRec, unsigned long index)
{
WORD sp1,sp2;

  if(index >= WmfRec->Size)
    {
    //WMF_ERROR (API,"Bad record - unexpectedly short!");
    //	API->err = wmf_E_BadFormat;
    return (0);
    }

  //index <<= 1;
  return(WmfRec->Parameters[index]);
/ *
//  sp1 = WmfRec->Parameters[index];
//  index++;
//  sp2 = WmfRec->Parameters[index];
//  return ((sp2 << 8) | sp1);
* /
}
*/


static void wmf_ESCAPE(TconvertedPass1_WMF *cq, _StandardMetaRecord *WmfRec)
{
static WORD MathType[]={15,12,'M'+256*'a','t'+256*'h','T'+256*'y','p'+256*'e',0};
int Size;
WORD w;

  if(WmfRec->Size-3<sizeof(MathType)/sizeof(WORD)) goto NoMTEF;

  fseek(cq->wpd,WmfRec->ParamFilePos,SEEK_SET);
  for(Size=0;Size<sizeof(MathType)/sizeof(WORD);Size++)
      {
      Rd_word(cq->wpd,&w);
      if(w!=MathType[Size]) goto NoMTEF;
      }

  strcpy(cq->ObjType+6," MTEF");
  if(cq->err != NULL)
    {
    cq->perc.Hide();
    fprintf(cq->err, _("\nNote: MTEF formulas inside WMF are not converted yet."));
    }

NoMTEF: ;
}


int TconvertedPass1_WMF::Dispatch(int FuncNo, ...)
{
#ifdef DEBUG
  fprintf(log,"\n#TconvertedPass1_WMF::Dispatch(%d) ",FuncNo);fflush(log);
#endif
va_list ap;

 va_start(ap, FuncNo);
 switch(FuncNo)
   {
   case DISP_EXTRACTIMAGE:
         {
	 Image **FillME = va_arg(ap,Image **);
         if(FillME) *FillME = new Image(Img);
	 return 0;
	 }
   case DISP_NOCONVERTIMAGE:
	 NoConvertImage = va_arg(ap,int);
         return 0;
   }

return(-1);
}

/*******************************************************************/
/* This procedure provides all needed processing for the first pass*/
int TconvertedPass1_WMF::Convert_first_pass(void)
{
#ifdef DEBUG
  fprintf(log,"\n#Convert_pass1_WMF() ");fflush(log);
#endif
_WindowsMetaHeader WmfHead;
_StandardMetaRecord *WmfRec;
int Rec;
int RetVal=0;
DWORD NewPos;
string NewFilename="image.eps";
//DWORD fsize=filesize(wpd);

  if(Verbosing >= 1) printf(_("Opening Windows MetaFile:"));

  if(LoadWMFHeader(wpd,WmfHead)!=18) return(-1);
  if(WmfHead.HeaderSize!=9) return(-1);

  //perc.Init(ftell(wpd), fsize,_("First pass WMF:") );

  ActualPos=ftell(wpd);
  Rec=0;
  while(!feof(wpd))
    {
    WmfRec=LoadWmfRecord(wpd);
    if(WmfRec!=NULL)
      {
      *ObjType=0;
      NewPos=0;

      switch(WmfRec->Function)
	{
	case 0x0000: strcpy(ObjType,"WMF End"); break;

	case 0x001E: strcpy(ObjType,"!SaveDC"); break;

	case 0x0035: strcpy(ObjType,"!RealizePalette"); break;
	case 0x0037: strcpy(ObjType,"!SetPalEntries"); break;

	case 0x004F: strcpy(ObjType,"!StartPage"); break;
        case 0x0050: strcpy(ObjType,"!EndPage"); break;

	case 0x0052: strcpy(ObjType,"!AbortDoc"); break;
        case 0x005E: strcpy(ObjType,"!EndDoc"); break;

	case 0x00F7: strcpy(ObjType,"!CreatePalette"); break;
	case 0x00F8: strcpy(ObjType,"!CreateBrush"); break;

	case 0x0102: strcpy(ObjType,"!SetBkMode"); break;
	case 0x0103: strcpy(ObjType,"!SetMapMode"); break;
	case 0x0104: strcpy(ObjType,"!SetROP2"); break;
	case 0x0105: strcpy(ObjType,"!SetRelabs"); break;
	case 0x0106: strcpy(ObjType,"!SetPolyFillMode"); break;
	case 0x0107: strcpy(ObjType,"!SetStretchBltMode"); break;
	case 0x0108: strcpy(ObjType,"!SetTextCharExtra"); break;

	case 0x0127: strcpy(ObjType,"!RestoreDC"); break;
	case 0x012A: strcpy(ObjType,"!InvertRegion"); break;
	case 0x012B: strcpy(ObjType,"!PaintRegion"); break;
	case 0x012C: strcpy(ObjType,"!SelectClipRegion"); break;
	case 0x012D: strcpy(ObjType,"!SelectObject"); break;
	case 0x012E: strcpy(ObjType,"!SetTextAlign"); break;

	case 0x0139: strcpy(ObjType,"!ResizePalette"); break;

	case 0x0142: strcpy(ObjType,"!DibCreatePatternBrush"); break;

	case 0x014C: strcpy(ObjType,"!ResetDc"); break;
	case 0x014D: strcpy(ObjType,"!StartDoc"); break;

	case 0x01F0: strcpy(ObjType,"!DeleteObject"); break;

	case 0x01F9: strcpy(ObjType,"!CreatePatternBrush"); break;

	case 0x0201: strcpy(ObjType,"!SetBkColor"); break;

	case 0x0209: strcpy(ObjType,"!SetTextColor"); break;
	case 0x020A: strcpy(ObjType,"!SetTextJustification"); break;
	case 0x020B: strcpy(ObjType,"!SetWindowOrg"); break;
	case 0x020C: strcpy(ObjType,"!SetWindowExt"); break;
	case 0x020D: strcpy(ObjType,"!SetViewportOrg"); break;
	case 0x020E: strcpy(ObjType,"!SetViewportExt"); break;
	case 0x020F: strcpy(ObjType,"!OffsetWindowOrg"); break;

	case 0x0211: strcpy(ObjType,"!OffsetViewportOrg"); break;
	case 0x0213: strcpy(ObjType,"!LineTo"); break;
	case 0x0214: strcpy(ObjType,"!MoveTo"); break;

	case 0x0220: strcpy(ObjType,"!OffsetClipRgn"); break;

	case 0x0228: strcpy(ObjType,"!FillRegion"); break;

	case 0x0231: strcpy(ObjType,"!SetMapperFlags"); break;

	case 0x0234: strcpy(ObjType,"!SelectPalette"); break;

	case 0x02FA: strcpy(ObjType,"!CreatePenIndirect"); break;
	case 0x02FB: strcpy(ObjType,"!CreateFontIndirect"); break;
	case 0x02FC: strcpy(ObjType,"!CreateBrushIndirect"); break;
	case 0x02FD: strcpy(ObjType,"!CreateBitmapIndirect"); break;

	case 0x0324: strcpy(ObjType,"!Polygon"); break;
	case 0x0325: strcpy(ObjType,"!Polyline"); break;

	case 0x0410: strcpy(ObjType,"!ScaleWindowExt"); break;

	case 0x0412: strcpy(ObjType,"!ScaleViewportExt"); break;

	case 0x0415: strcpy(ObjType,"!ExcludeClipRect"); break;
	case 0x0416: strcpy(ObjType,"!IntersectClipRect"); break;

	case 0x0418: strcpy(ObjType,"!Ellipse"); break;
	case 0x0419: strcpy(ObjType,"!FloodFill"); break;

	case 0x041B: strcpy(ObjType,"!Rectangle"); break;

	case 0x041F: strcpy(ObjType,"!SetPixel"); break;

	case 0x0429: strcpy(ObjType,"!FrameRegion"); break;

	case 0x0436: strcpy(ObjType,"!AnimatePalette"); break;

	case 0x0521: strcpy(ObjType,"!TextOut"); break;

	case 0x0538: strcpy(ObjType,"!PolyPolygon"); break;

	case 0x0548: strcpy(ObjType,"!ExtFloodFill"); break;

	case 0x626: 
	   {wmf_ESCAPE(this,WmfRec);strcpy(ObjType,"Escape");break;}

	case 0x061C: strcpy(ObjType,"!RoundRect"); break;
	case 0x061D: strcpy(ObjType,"!PatBlt"); break;

	case 0x062F: strcpy(ObjType,"!DrawText"); break;

	case 0x06FE: strcpy(ObjType,"!CreateBitmap"); break;
	case 0x06FF: strcpy(ObjType,"!CreateRegion"); break;

        case 0x0817: strcpy(ObjType,"!Arc"); break;

	case 0x081A: strcpy(ObjType,"!Pie"); break;

 	case 0x0830: strcpy(ObjType,"!Chord"); break;

	case 0x0922: strcpy(ObjType,"!BitBlt"); break;

	case 0x0940: strcpy(ObjType,"!DibBitblt"); break;

	case 0x0A32: strcpy(ObjType,"!ExtTextOut"); break;

	case 0x0B23: strcpy(ObjType,"!StretchBlt"); break;

	case 0x0B41: strcpy(ObjType,"!DibStretchBlt"); break;

	case 0x0d33: strcpy(ObjType,"!SetDibToDev"); break;

	case 0x0F43: WMF_STRETCHDIB(this->Img, this->wpd, WmfRec->ParamFilePos);
		     strcpy(ObjType,"StretchDIBits"); 
		     break;
	}

      if(log!=NULL)
	{   /**/
	fprintf(log,_("\n%*s{WMF function:%3Xh; size:%4lu; pos:%lX}"),
		  recursion*2,"",WmfRec->Function,2*WmfRec->Size,ActualPos);
	if(*ObjType!=0) fprintf(log," %s",ObjType);

	fprintf(log,"{");
	fseek(wpd,WmfRec->ParamFilePos,SEEK_SET);
	for(int i=0;i<WmfRec->Size-3;i++)
	  //fprintf(log,"%X ",WmfRec->Parameters[i]);
	  {
	  WORD w;
          Rd_word(wpd,&w);
	  if(feof(wpd)) break;
	  int j=w%256;
	  fprintf(log,"%X",j);
	  if(j>=' ') fprintf(log,"(%c)",j);
	  j=w/256;
	  fprintf(log,",%X",j);
	  if(j>=' ') fprintf(log,"(%c)",j);
	  fprintf(log,",");

	  if(i>100) {fprintf(log," ... ");break;}
	  }
	fprintf(log,"}");
	}
      if(*ObjType==0) UnknownObjects++;

      if(NewPos!=0) ActualPos=NewPos;
	       else ActualPos+=2*WmfRec->Size;
      free(WmfRec); WmfRec=NULL;

      fseek(wpd,ActualPos,SEEK_SET);
      }
    else
      ActualPos=ftell(wpd);

    Rec++;
    }

  if(!NoConvertImage && Img.Raster!=NULL)
    {
    NewFilename=MergePaths(OutputDir,RelativeFigDir)+GetFullFileName(NewFilename);
    if(SavePictureEPS(NewFilename(),Img)<0)
	{
        if(err != NULL)
	  {
	  perc.Hide();
	  fprintf(err, _("\nError: Cannot save file:%s !"),NewFilename());
	  }
	return 0;
        }

    NewFilename=CutFileName(NewFilename); 	//New Filename only

    if(InputPS & 2)	//graphicx.sty
      {
      fprintf(strip," \\begin{center}");
      fprintf(strip,"\\includegraphics");
      fprintf(strip,"[width=\\textwidth]");
      fprintf(strip,"{%s.eps}",NewFilename() );
      fprintf(strip," \\end{center}");
      putc('\n',strip);  rownum++;
    }
    else if(InputPS & 4)	//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 & 8)	//graphics.sty
      {
      fprintf(strip," \\begin{center}");
      fprintf(strip,"\\includegraphics");
      fprintf(strip,"{%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++;
      }

    InputPS|=1;		//mark style as used
    Finalise_Conversion(this);
    RetVal++;
    }

  return(RetVal);
}


/*--------------------End of PASS1_WMF--------------------*/
