/******************************************************************************
 * program:     wp2latex                                                      *
 * function:    convert WordPerfect files into LaTeX                          *
 * modul:       images.cc                                                     *
 * description: Procedures for converting WP images into into PostScripts ones*
 *              that could be inserted into a LaTeX.                          *
 * licency:     GPL		                                              *
 ******************************************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>

//Atoms library
#include <strings.h>
#include "lists.h"
#include "sets.h"

#include "wp2latex.h"
#include "cp_lib/cptran.h"

#ifdef _MSC_VER
 #pragma warning (disable : 4244)	/* double to float conversion - stupid warning */
 #pragma warning (disable : 4305)
#endif

#ifdef NO_IMG
 #define SupportART 0
 #define SupportBMP 2	//Read procedure only
 #define SupportCUT 0
 #define SupportFITS 0
 #define SupportGIF 0
 #define SupportHRZ 0
 #define SupportICO 0
 #define SupportMAC 0
 #define SupportMAT 0
 #define SupportOKO 0
 #define SupportPBM 0
 #define SupportPCX 2	//Read procedure only
 #define SupportRAS 0
 #define SupportRAS_SUN 0
 #define SupportRAW 0
 #define SupportTGA 0
 #define SupportTIFF 0
 #define SupportTXT 0
 #define SupportTXTgm 0
 #define SupportWMF 1
 #define SupportWPG 1	//Compile only supporting stub, build-in reader included
#else
 #define SupportART 2 	//Read procedure only
 #define SupportBMP 2	//Read procedure only
 #define SupportFITS 2	//Read procedure only
 #define SupportICO 2	//Read procedure only
 #define SupportMAT 2	//Read procedure only
 #define SupportOKO 2	//Read procedure only
 #define SupportPCX 2	//Read procedure only
 #define SupportRAS 2	//Read procedure only
 #define SupportRAW 2	//Read procedure only
 #define SupportTGA 2	//Read procedure only
 #define SupportTXT 2	//Read procedure only
 #define SupportWMF 2
 #define SupportWPG 1	//Compile only supporting stub, build-in reader included
#endif
#include "images/ras_img.cc"

extern string wpd_filename;

#define DEFAULT_BOX_WIDTH 10	///< Use 10cm as a default width

string CutFileName(const char *FullFilename); //from wp2lfuti.cc

#ifndef FINAL
void CrackObject(TconvertedPass1 *cq, DWORD end_of_code);
#endif


#define WPGu2PSu(x) ( (float)(x)*71/(25.4*47.0) )
#define mm2PSu(x)   ( (float)(x)*71/25.4 )
static SWORD Rd_word_MMX(FILE *F,float &Min,float &Max)
{
SWORD w;
  Rd_word(F,(WORD *)&w);
  if(w<Min) Min=w;
  if(w>Max) Max=w;
  return(w);
}

typedef struct EmbeddedImg {
   DWORD Offset;
   DWORD Length;
   char *Extension;
   char *ImgName;
   struct EmbeddedImg *Next;
   }EmbeddedImg;


typedef struct {
	DWORD PS_unknown1;
	WORD PS_unknown2;
	WORD PS_unknown3;
       } WPGPSl1Record;


static void Wr_WP_DWORD(FILE *f, DWORD d, char Format=0)
{
   unsigned char b;

   if(d<0xFF && Format<1)
       {
       b=d;
       fwrite(&b, 1, 1, f);
       return;
       }

  b=0xff;
  fwrite(&b, 1, 1, f);

  if(d<0x8000 && Format<2)
       {
       b = d & 255;
       fwrite(&b, 1, 1, f);
       b = d / 256;
       fwrite(&b, 1, 1, f);
       return;
       }

  b = (BYTE)((d >> 8*2) & 0x00ffl);
  fwrite( &b, 1,1,f);
  b = (BYTE)((d >> 8*3) & 0x00ffl) | 0x80;
  fwrite( &b, 1,1,f);
  b = (BYTE)((d >> 8*0) & 0x00ffl);
  fwrite( &b, 1,1,f);
  b = (BYTE)((d >> 8*1) & 0x00ffl);
  fwrite( &b, 1,1,f);
  return;
}


static void PS_text(FILE *F,int x,int y,const char *Text)
{
fprintf(F,"/Times-Roman ff 375.00 scalefont setfont\n"
	  "%d %d m\n"
	  "gs 1 -1 sc (%s) col-1 sh gr\n",x,y,Text);
}


/*This procedure creates empty PostScript image with warning about inability to convert given image*/
static void MakeDummyPS(TconvertedPass1 *cq, const char *Filename, const char *NewFilename)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#MakeDummyPS(%s,%s) ",Filename,NewFilename);fflush(cq->log);
#endif

FILE *PostScript;
char c1,c2;

/*  static int count = 0;    !!!!! vyhodit !!!!!!
  if(string("274945_754511723_1544526310_q.eps") IN string(NewFilename))
  {
    fprintf(cq->log,"!! %d !!", count++);
  }
  else fprintf(cq->log,"## %d ##", count++);
  if(count==20)
  {
    fprintf(cq->log,"pred ...");
  } */

  if((PostScript=fopen(NewFilename,"r"))!=NULL)
    {
    string s;
    c1=getc(PostScript);
    c2=getc(PostScript);
    if(c1=='%' && c2=='!')
      {
      fGets2(PostScript,s);
      fGets2(PostScript,s);
      fGets2(PostScript,s);
      if(!(string("wp2latex") IN s))
        {
	fclose(PostScript);
	return;  //file already exist, do not overwrite
	}
      }
    fclose(PostScript);
    }

  PostScript=fopen(NewFilename,"w");
  if(PostScript==NULL)
	{
	if(cq->err!=NULL && Verbosing>=0)
	       {
	       cq->perc.Hide();
	       fprintf(cq->err, _("\nError: Cannot write to the file %s !"),NewFilename);
	       }
        if(cq->log) fprintf(cq->log, _("\nError: Cannot write to the file %s !"),NewFilename);
	return;
	}

  fprintf(PostScript,"\
%%!PS-Adobe-2.0 EPSF-2.0\n\
%%%%Title: dummy for %s\n\
%%%%Creator: wp2latex Version %s Patchlevel 0\n\
%%%%CreationDate: %s\n\
%%%%For: wp2latex@wp2latex ()\n\
%%Magnification: 1.00\n\
%%%%Orientation: Portrait\n\
%%%%BoundingBox: 0 0 246 141\n\
%%%%Pages: 0\n\
%%%%BeginSetup\n\
%%%%IncludeFeature: *PageSize Letter\n\
%%%%EndSetup\n\
%%%%EndComments\n",
Filename,version,versiondate);

fprintf(PostScript,"\
/$F2psDict 200 dict def\n\
$F2psDict begin\n\
$F2psDict /mtrx matrix put\n\
/col-1 {0 setgray} bind def\n\
\n\
end\n\
save\n\
-77.0 169.0 translate\n\
1 -1 scale\n\
\n\
/cp {closepath} bind def\n\
/gr {grestore} bind def\n\
/gs {gsave} bind def\n\
/l {lineto} bind def\n\
/m {moveto} bind def\n\
/n {newpath} bind def\n\
/s {stroke} bind def\n\
/sh {show} bind def\n\
/slw {setlinewidth} bind def\n\
/sc {scale} bind def\n\
/ff {findfont} bind def\n\
/sf {setfont} bind def\n\
/scf {scalefont} bind def\n\
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def\n\
/$F2psEnd {$F2psEnteredState restore end} def\n\
%%%%EndProlog\n\
\n\
$F2psBegin\n\
10 setmiterlimit\n\
n 0 792 m 0 0 l 612 0 l 612 792 l cp clip\n\
 0.06000 0.06000 sc\n\
7.500 slw\n\
%% Polyline\n\
n 1305 495 m 5370 495 l 5370 2790 l 1305 2790 l cp gs col-1 s gr\n");

   PS_text(PostScript,1595,915,"Please convert an image");
   PS_text(PostScript,2340,1455,Filename);
   PS_text(PostScript,2115,2025,"to the PostScript");
   PS_text(PostScript,2520,2550,"manually!");

 fprintf(PostScript,"\n$F2psEnd\n");

 fclose(PostScript);
}


static void NoImgMemory(TconvertedPass1 *cq,int Width,int Height)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#NoImgMemory() ");fflush(cq->log);
#endif
if (cq->err != NULL)
   {
   cq->perc.Hide();
   if(Width==0 || Height==0)
       fprintf(cq->err, _("\nWarning: Zero size raster (%dx%d)?"),Width,Height);
   else
       fprintf(cq->err, _("\nError: Not enough memory to store image raster (%dx%d)!"),Width,Height);
   }
}


/*static int SetCategory(FILE *strip,const set & FixChars)
{
unsigned char ch;
int i=0;

if(strip==NULL) return(0);
for(ch=1;ch<255;ch++)
	{
	if(FixChars[ch])
		{
		i++;
		fprintf(strip,"\\catcode`\\%c=12\n",ch);
		}
	}
return(i);
}*/
#define PSS_LineColor 1
#define PSS_LineStyle 2
#define PSS_LineWidth 4
typedef struct
	{
	WORD FontSize;
	char dirty;
	char FillPattern;
	BYTE LineStyle;
	float LineWidth;
	RGB_Record FillColor;
	RGB_Record LineColor;
	RGB_Record TextColor;
	} PS_State;


static void PS_Attr(string & PSData, PS_State *PSS)
{
char tmp[40];

if(PSS->dirty & PSS_LineColor)
  {
  sprintf(tmp,"\n%0.2g %0.2g %0.2g setrgbcolor",
	(float)PSS->LineColor.Red/256.0,
	(float)PSS->LineColor.Green/256.0,
	(float)PSS->LineColor.Blue/256.0);
  PSData += tmp;
  PSS->dirty &= ~PSS_LineColor;
  }
if(PSS->dirty & PSS_LineStyle)
  {
  switch(PSS->LineStyle)
	{
	case 2:PSData+="\n[12 4]0"; break;
	case 3:PSData+="\n[2 2]0"; break;
	case 4:PSData+="\n[8 3 2 3]0"; break;
	case 5:PSData+="\n[8 8]0"; break;
	case 6:PSData+="\n[6 2 2 2 2 2]0"; break;
	case 7:PSData+="\n[4 4]0"; break;
	case 8:PSData+="\n[8 2 3 2]0"; break;
	case 9:PSData+="\n[14 2]0"; break;
	case 10:PSData+="\n[1 1]0"; break;
	case 11:PSData+="\n[1 3]0"; break;
	case 12:PSData+="\n[3 5]0"; break;
	case 13:PSData+="\n[8 2 4 2]0"; break;
	case 14:PSData+="\n[2 2 10 2]0"; break;
	case 15:PSData+="\n[10 2 2 2]0"; break;
	case 16:PSData+="\n[10 2 2 2 2 2]0"; break;	//type No13 in wpg2
	case 17:PSData+="\n[12 4 12 4 4 4]0"; break;	//type No14 in wpg2
	case 18:PSData+="\n[12 2 12 2 3 2 3 2]0"; break;//type No15 in wpg2
	case 19:PSData+="\n[1 2 1 2 1 5]0"; break;	//type No7 in wpg2
	case 1:
	//case 0: //no line
	default:PSData+="\n[]0";
	}
  PSData+=" setdash";
  PSS->dirty &= ~PSS_LineStyle;
  }
if(PSS->dirty & PSS_LineWidth)
  {
  sprintf(tmp,"\n%2.2f setlinewidth",PSS->LineWidth);
  PSData += tmp;
  PSS->dirty &= ~PSS_LineWidth;
  }
}


static void FillObject(float MinPolyX,float MaxPolyX,float MinPolyY,float MaxPolyY, string & PSData, PS_State *PSS)
{
char tmp[120],color[40];
float Distance;

  sprintf(color,"\n%0.2g %0.2g %0.2g setrgbcolor",
		(float)PSS->FillColor.Red/256.0,
		(float)PSS->FillColor.Green/256.0,
		(float)PSS->FillColor.Blue/256.0);

  switch(PSS->FillPattern)
		{
		case 1:if(PSS->LineStyle!=0)
			 PSData+="\ngsave";
		       PSData+=color;
		       PSData+="\nfill";
		       if(PSS->LineStyle!=0)
			 PSData+=" grestore";
		       else
			 PSS->dirty |= PSS_LineColor;
		       break;
		case 2:Distance = 2.8;
		       goto FINALDiagonal;
		case 3:Distance = 5.7;
		       goto FINALDiagonal;
		case 4:Distance = 11.3;
FINALDiagonal:	       sprintf(tmp,"\n%2.2f %2.1f %2.2f {%2.2f moveto %2.2f %2.2f rlineto}",
			       MinPolyX-(MaxPolyY-MinPolyY),Distance,MaxPolyX,MinPolyY,
			       MaxPolyY-MinPolyY, MaxPolyY-MinPolyY  );
		       goto FINALLY;
		case 5:Distance=2.8;
		       goto FINALCross;
		case 6:Distance=5.7;
		       goto FINALCross;
		case 7:Distance=11.3;
FINALCross:	       sprintf(tmp,"\n%2.2f %2.1f %2.2f {%2.2f moveto %2.2f %2.2f rlineto}for",
			       MinPolyX-(MaxPolyY-MinPolyY),Distance,MaxPolyX,MinPolyY,
			       MaxPolyY-MinPolyY, MaxPolyY-MinPolyY );
			PSData+='\n';
			if(PSS->LineStyle!=0) PSData+="gsave";
			PSData+=" clip newpath 0 setlinewidth\n";
			PSData+=color;
			PSData+=tmp;
			sprintf(tmp,"\n%2.2f %2.1f %2.2f {%2.2f moveto %2.2f %2.2f rlineto}",
			       MinPolyX,Distance,(MaxPolyX+(MaxPolyY-MinPolyY)),MinPolyY,
			       -(MaxPolyY-MinPolyY), MaxPolyY-MinPolyY  );
			goto FINALLY2;
		case 8: Distance=2;
			goto FINALVertical;
		case 9: Distance=4;
			goto FINALVertical;
		case 10:Distance=8;
FINALVertical:		sprintf(tmp,"\n%2.2f %2.1f %2.2f {%2.2f moveto 0 %2.2f rlineto}",
			       MinPolyX,Distance,MaxPolyX,MinPolyY,
			       (MaxPolyY-MinPolyY)  );
FINALLY:		PSData+='\n';
			if(PSS->LineStyle!=0) PSData+="gsave";
			PSData+=" clip newpath 0 setlinewidth\n";
			PSData+=color;
FINALLY2:		PSData+=tmp;
			PSData+="for\nstroke";
			if(PSS->LineStyle!=0) PSData+=" grestore";
			break;
				case 11:Distance=16;
FINALDot:		sprintf(tmp,"\n[0.5 %2.1f] 0 setdash\n %2.2f %2.1f %2.2f {%2.2f moveto 0 %2.2f rlineto %2.2f %2.2f rmoveto 0 %2.2f rlineto}",
			       Distance-0.5,
			       MinPolyX,Distance,MaxPolyX,
			       MinPolyY,
			       MaxPolyY-MinPolyY,
			       Distance/2.0,-Distance/2.0 - (MaxPolyY-MinPolyY),
			       (MaxPolyY-MinPolyY)+Distance/2.0  );
			goto FINALLY;
		case 12:Distance=8;
			goto FINALDot;
		case 13:Distance=4;
			goto FINALDot;
		case 14:Distance=2;
			goto FINALDot;
		case 15:Distance=1;
			goto FINALDot;
		}

  if(PSS->LineStyle!=0)
    PSData+="\nstroke";		//draw frame line
}


static void Line2PS(float *Points, int Count, string & PSData, PS_State *PSS, bool ClosePath=false)
{
int i;
char tmp[40];

  if(Points==NULL || Count<=0) return;

  PS_Attr(PSData,PSS);
  for(i=0;i<Count;i++)
	{
	sprintf(tmp,i==0?"\nnewpath\n%2.2f %2.2f moveto":"\n%2.2f %2.2f lineto",
		    WPGu2PSu(Points[0]),WPGu2PSu(Points[1]));
	PSData+=tmp;
	Points+=2;
	}

  if(ClosePath) PSData+="\nclosepath";
  PSData+="\nstroke";
}


/** Render polygonal curve. */
static void Curve2PS(float *Points, int Count, string & PSData, PS_State *PSS, bool Filled=true, bool Outline=true)
{
int i;
char tmp[80];
float MinPolyX=65537,MaxPolyX=-1,MinPolyY=65537,MaxPolyY=-1;
float xi,yi,xa,ya,xt,yt,xt_old,yt_old;

  if(Points==NULL || Count<=0) return;

  PS_Attr(PSData,PSS);
  for(i=0;i<Count;i++)
	{
        xi=WPGu2PSu(*Points++);
	yi=WPGu2PSu(*Points++);
	xa=WPGu2PSu(*Points++);
	ya=WPGu2PSu(*Points++);
        xt=WPGu2PSu(*Points++);
	yt=WPGu2PSu(*Points++);

	if(xi<MinPolyX) MinPolyX=xi;  if(xi>MaxPolyX) MaxPolyX=xi;
	if(yi<MinPolyY) MinPolyY=yi;  if(yi>MaxPolyY) MaxPolyY=yi;

	if(xa<MinPolyX) MinPolyX=xa;  if(xa>MaxPolyX) MaxPolyX=xa;
	if(ya<MinPolyY) MinPolyY=ya;  if(ya>MaxPolyY) MaxPolyY=ya;

	if(xt<MinPolyX) MinPolyX=xt;  if(xt>MaxPolyX) MaxPolyX=xt;
	if(yt<MinPolyY) MinPolyY=yt;  if(yt>MaxPolyY) MaxPolyY=yt;

	if(i==0)
	  {
          sprintf(tmp,"\nnewpath\n%2.2f %2.2f moveto",xa,ya);
          PSData+=tmp;
          }
        else
	  {
	  sprintf(tmp,"\n%2.2f %2.2f %2.2f %2.2f %2.2f %2.2f curveto",
		       xt_old,yt_old,xi,yi,xa,ya);
	  PSData+=tmp;
          }
        xt_old=xt;
        yt_old=yt;
	}

  if(Filled)
    {
    PSData+="\nclosepath";
    i=PSS->LineStyle;
    if(!Outline) PSS->LineStyle=0;  //temporarily disable line
    FillObject(MinPolyX,MaxPolyX,MinPolyY,MaxPolyY,PSData,PSS);
    PSS->LineStyle=i;
    }
  else
    PSData+="\nstroke";
}



static void Polygon2PS(float *Points, int Count, string & PSData, PS_State *PSS, bool Outline=true)
{
int i;
char tmp[120];
float MinPolyX=65537,MaxPolyX=-1,MinPolyY=65537,MaxPolyY=-1,x,y;
float *p;

  if(Points==NULL || Count<=0) return;

  PS_Attr(PSData,PSS);
  for(p=Points,i=0;i<Count;i++)
	{
	x=WPGu2PSu(*p);
	if(x<MinPolyX) MinPolyX=x;
	if(x>MaxPolyX) MaxPolyX=x;
	p++;
	y=WPGu2PSu(*p);
	if(y<MinPolyY) MinPolyY=y;
	if(y>MaxPolyY) MaxPolyY=y;
	p++;
	sprintf(tmp,i==0?"\nnewpath\n%2.2f %2.2f moveto":"\n%2.2f %2.2f lineto",
		    x,y);
	PSData+=tmp;
	}

  PSData+="\nclosepath";
  i=PSS->LineStyle;
  if(!Outline) PSS->LineStyle=0;  //temporarily disable line
  FillObject(MinPolyX,MaxPolyX,MinPolyY,MaxPolyY,PSData,PSS);
  PSS->LineStyle=i;
}


static void FixPsAccent(string & s, const char *TexAccent, const char *PsAccent)
{
string Text2;
const char *pos;

 while((pos=strstr(s(),TexAccent))!=NULL)
   {
   if(pos[3]==0 || pos[3]=='}')
     {
     Text2 = copy(s,0,pos-s());
     Text2 += PsAccent;
     Text2 += pos+4;
     }
   else
     {
     if(pos>s())
       {
       Text2 = copy(s,0,pos-s());
       Text2 += ") show ";
       }     
     Text2 += "gsave (";
     Text2 += PsAccent;
     Text2 += ") show grestore (";

     pos += 3;
     while(*pos!='}')
     {
       if(*pos==0) goto SKIP_TAIL;
       Text2 += *pos++;
     }
     Text2 += pos+1;
     }
SKIP_TAIL:
  s = Text2;
  }
}


/** Store color in PS notation. */
static void Color2PS(string & Text, const RGB_Record & TextColor)
{
char tmp[40];	// minimally 7+7+7+11 = 32
  sprintf(tmp,"%0.2g %0.2g %0.2g setrgbcolor",
	         (float)TextColor.Red/256.0,
	         (float)TextColor.Green/256.0,
	         (float)TextColor.Blue/256.0);            
  Text += tmp;  
}


static void Font2PS(string & Text, WORD FontSize)
{
char tmp[80];

  sprintf(tmp,"\n/Times-Roman findfont\n%2.2f scalefont setfont",
     (float)FontSize/50.0);
  Text += tmp;
}


static void StoreText2PS(string & PSData, string & Text, PS_State *PSS, WORD RotAngle,
		float UpRightX, float UpRightY, float LowLeftX, float LowLeftY,
		const RGB_Record & LocTextColor, WORD FontSize)
{
char tmp[80];
float AdjY;

  if(Text=="") return;
  if(RotAngle>0)
	  {
	  float Xs,Ys;
	  Xs=(UpRightX+LowLeftX)/2;
	  Ys=(UpRightY+LowLeftY)/2;
	  sprintf(tmp,"\ngsave\n%2.2f %2.2f translate\n%d rotate\n%2.2f %2.2f translate",
		  Xs,Ys, RotAngle, -Xs,-Ys);
	  PSData+=tmp;
	  }

  Font2PS(PSData,FontSize);
  AdjY = LowLeftY+0.3*(UpRightY-LowLeftY);
  sprintf(tmp,"\nnewpath %2.2f %2.2f moveto\n",
          LowLeftX,AdjY);
  PSData += tmp;
  Color2PS(PSData,LocTextColor);  
  PSS->dirty |= PSS_LineColor;

  FixPsAccent(Text,"\\'{","\\251");	// acute
  FixPsAccent(Text,"\\`{","\\301");	// grave
  FixPsAccent(Text,"\\v{","\\317");	// charon
  FixPsAccent(Text,"\\r{","\\312");	// ring

  PSData+="\n(";
  PSData+=Text;
  PSData+=")\nshow";
  if(RotAngle>0) PSData+="\ngrestore";
}


/** Convert a block of WP5.x text into PostScript. */
static void Textl2_2PS(TconvertedPass1 *cq, long ldblk, string & PSData, PS_State *PSS, WPG_records *WPG)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#Textl2_2PS() ");fflush(cq->log);
#endif
BYTE TextColorIdx;
string Text;
RGB_Record LocTextColor = PSS->TextColor;
WORD FontSize = 1100;		// Default font size
long ActualPos;
TconvertedPass1 *cq5;

  if(ldblk<=0) return;
  cq5=GetConvertor("WP5.x");
  if(cq5==NULL) 
    {
    if(cq->err!=NULL && Verbosing>=0)
      {
      cq->perc.Hide();
      fprintf(cq->err, _("\nError: WP5.x converter is not available in this build!"));
      }
    return;
    }

  cq5->InitMe(cq->wpd,cq->table,cq->strip,cq->log,cq->err);
  cq5->recursion=cq->recursion+1;
  if(cq5->ConvertCpg==NULL)
    cq5->ConvertCpg = GetTranslator("wp5TOinternal");

  cq5->ActualPos=cq->ActualPos+21;
  ldblk+=cq5->ActualPos;
  fseek(cq5->wpd,cq5->ActualPos,SEEK_SET);
  cq5->flag = Nothing;
  while(cq5->ActualPos<ldblk)
    {
    *cq5->ObjType=0;
    cq5->by=fgetc(cq5->wpd);
    if(feof(cq5->wpd)) break;

    if(cq5->by==0xC0)
      {
      ActualPos = ftell(cq5->wpd);
      WORD WChar;
      Rd_word(cq->wpd, &WChar);      
      const char *str = Ext_chr_str(WChar, cq5, cq5->ConvertCpg);
      if(str==NULL)
        Text += '_';
      else
        Text += str;
      fseek(cq5->wpd,ActualPos,SEEK_SET);
      } 
  
    if(cq5->by<=0x80)
      {
      if(cq5->by==')' || cq5->by=='(') Text+='\\';
      if(cq5->by>=' ') Text+=cq5->by;
      }

    if(cq5->by == 0xD1)
      {
      ActualPos=ftell(cq5->wpd);
      fread(&cq5->subby, 1, 1, cq5->wpd);
      if(cq5->subby==1)
	{
        WORD FontSize2;
	fseek(cq5->wpd,28+2,SEEK_CUR);
        Rd_word(cq5->wpd, &FontSize2);
        sprintf(cq5->ObjType,"Font Size %dWPu",FontSize2);

        if(length(Text)<=0)	// 1st font size change
	  FontSize = FontSize2;
        else
          {
          if(FontSize2!=FontSize)
            {
            Text += ") show\n";
            Font2PS(PSData,FontSize2);
            Text += "\n(";
            }
          }
	}
      if(cq5->subby==2)
	{
	fseek(cq5->wpd,1+2,SEEK_CUR);
	TextColorIdx=fgetc(cq5->wpd);
        if(length(Text)<=0)	// 1st color change
          {
	  LocTextColor = WPG_Palette[TextColorIdx];
          }
        else  // The color might be changed more than once.
          {          
          RGB_Record NewColor = WPG_Palette[TextColorIdx];
          if(memcmp(&NewColor,&LocTextColor,sizeof(LocTextColor)))
            {            
            Text += ") show\n";
            Color2PS(Text,NewColor);
            Text += " (";
            }
          }
	}
      fseek(cq5->wpd,ActualPos,SEEK_SET);
      }

    cq5->Dispatch(DISP_PROCESSKEY);
    }

 if(cq5!=cq)
	delete cq5;

 StoreText2PS(PSData,Text,PSS,WPG->TextL2.RotAngle,
	      WPGu2PSu(WPG->TextL2.UpRightX),WPGu2PSu(WPG->TextL2.UpRightY),
	      WPGu2PSu(WPG->TextL2.LowLeftX),WPGu2PSu(WPG->TextL2.LowLeftY),
	      LocTextColor,FontSize);
}


/** Convert a block of WP6.x text into PostScript. */
static void TextWPG2_2PS(TconvertedPass1 *cq,long ldblk, string & PSData, PS_State *PSS,WPG_records *WPG, float x, float y, int Angle)
{
string Text;
WORD FontSize=1100;
RGB_Record LocTextColor=PSS->TextColor;
TconvertedPass1 *cq6;
long ActualPos;

  cq6=GetConvertor("WP6.x");
  if(cq6==NULL) return;

  cq->ActualPos = ftell(cq->wpd);
  ldblk+=cq->ActualPos;			//end position
//  Rd_word(cq->wpd, &StringSize); ?????

  cq6->InitMe(cq->wpd,cq->table,cq->strip,cq->log,cq->err);
  if(cq6->ConvertCpg==NULL)
    cq6->ConvertCpg = GetTranslator("wp6TOinternal");
  cq6->recursion=cq->recursion+1;
  cq6->ActualPos=cq->ActualPos;
  cq6->flag = Nothing;

  while(cq6->ActualPos<ldblk)
    {
    *cq6->ObjType = 0;
    cq6->by = fgetc(cq6->wpd);

    if(cq6->by==0xD4 || cq6->by==0xE1)
      {
      ActualPos = ftell(cq6->wpd);
      cq6->subby = fgetc(cq6->wpd);
      if(cq6->by==0xD4)
	{
	if(cq6->subby==0x1B)
	  {
	  fseek(cq6->wpd,6+2,SEEK_CUR); //<flags><PIDsNo>[descriptor][NDelSize]
          if(length(Text)<=0)	// 1st font size change
            {
	    Rd_word(cq6->wpd, &FontSize);
            sprintf(cq6->ObjType,"Font Size %dWPu",FontSize);
            }
          else
            {
            WORD FontSize2;
            Rd_word(cq6->wpd, &FontSize2);
            if(FontSize2!=FontSize)
              {
              Text += ") show\n";
              Font2PS(PSData,FontSize2);
              Text += "\n(";
              }
            }	  
	  }
	}
      if(cq6->by==0xE1)
	{
	if(cq6->subby==0xC)
	  {
          RGB_Record NewColor;

	  fseek(cq6->wpd,3+2,SEEK_CUR);
	  NewColor.Red=fgetc(cq6->wpd);
	  NewColor.Green=fgetc(cq6->wpd);
	  NewColor.Blue=fgetc(cq6->wpd);

          if(length(Text)<=0)
            LocTextColor=NewColor;
          else
            {
	      if(memcmp(&NewColor,&LocTextColor,sizeof(LocTextColor)))
              {              
              Text += ") show\n";
              Color2PS(Text,NewColor);              
              Text += " (";
              }          
	    }

	  //transparency is ignored
	  sprintf(cq6->ObjType,"Pen Fore Color %d,%d,%d",LocTextColor.Red,LocTextColor.Green,LocTextColor.Blue);
	  }
	}
      fseek(cq6->wpd,ActualPos,SEEK_SET);
      }

    if(cq6->by == 0xF0)       /*extended character*/
      {
      ActualPos = ftell(cq6->wpd);
      WORD WChar;      
      Rd_word(cq->wpd, &WChar);      
      const char *str = Ext_chr_str(WChar, cq6, cq6->ConvertCpg);
      if(str==NULL)
        Text += '_';
      else
        Text += str;
      fseek(cq6->wpd,ActualPos,SEEK_SET);
      }

    if(cq6->by>0x20 && cq6->by<=0x7f)
      {
      Text += cq6->by;   /* Normal_char  */
      }

    cq6->Dispatch(DISP_PROCESSKEY);
    }
  if(cq6!=cq)
	delete cq6;

  StoreText2PS(PSData,Text,PSS,Angle,
	       x+1,y+1,x,y,LocTextColor,FontSize);
}


static float *LoadPoints(TconvertedPass1 *cq,int n,float & MinX,float & MaxX,float & MinY,float & MaxY)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#LoadPoints(%d) ",n);fflush(cq->log);
#endif
float *Points,*p;

  if(n<=0) return(NULL);
  p=Points=(float*)calloc(2*n,sizeof(*Points));
  if(Points==NULL) return(NULL);

  while(n-->0)
	{
	*p++=Rd_word_MMX(cq->wpd,MinX,MaxX);
	*p++=Rd_word_MMX(cq->wpd,MinY,MaxY);
	}
#ifdef DEBUG
  fprintf(cq->log,"\n#~LoadPoints(%d) ",n);fflush(cq->log);
#endif
  return(Points);
}


static void FixPolySize(TconvertedPass1 *cq, WORD *P_size, DWORD ObjSize)
{
  if(ObjSize < 2+2*(DWORD)*P_size)
    {
    if (cq->err != NULL)
       {
       cq->perc.Hide();
       fprintf(cq->err, _("\nError: The size of polygon %ld is not enough to fit %d elements!"),ObjSize,*P_size);
       }
    if(ObjSize<=2) *P_size=0;
              else *P_size=(ObjSize-2)/2;
    }
}


/**This function generates unique name for the image - if the original one is empty*/
/* Please use extension maximally 3 characters long, othervise crash occurs. */
char *GetSomeImgName(const char *Ext)
{
static char tmp_img[11] = "00_img.wpg";
char *ptrch;

  switch(tmp_img[0])	/*Actualise a name*/
    {
    case '9':tmp_img[0] = 'a';
	     break;
    case 'z':tmp_img[0] = '0';
	     switch(tmp_img[1])
	       {
	       case '9':tmp_img[1] = 'a'; break;
	       case 'z':tmp_img[1] = '0';
			if(tmp_img[2]=='_') tmp_img[2]='0';
				       else tmp_img[2]++;
			break;
	       default: tmp_img[1]++; break;
	       }
	     break;
    default: tmp_img[0]++; break;
    }

  ptrch=tmp_img+6;	/*prepare extension*/
  *ptrch=0;
  if(Ext)
    do
     {
     *ptrch++=*Ext;
     } while(*Ext++!=0);
  return(tmp_img);
}


/* Processing one token inside separate procedure allows to recurse tokens. */
static void ProcessWPG2Token(TconvertedPass1 *cq, WPG2Record & Rec2,
      WPG2Start & StartWPG, Image & Img, float_matrix & CTM, APalette **Palette,
      string & PSData, PS_State & PSS, EmbeddedImg **EmImg,
      DWORD & NewObject, DWORD & ResourceEnd, Image **CurrImg,
      float & x, float & y, float & dx, float & dy, float & RotAngle,
      float & MinX, float & MaxX, float & MinY, float & MaxY)
{
WPG_records WPG;
WORD i;
Raster2DAbstract *Raster=NULL;
long ldblk;

    switch(Rec2.Type)
	{
	case 0x1:strcpy(cq->ObjType,"Start WPG");
		 LoadWPG2Start(cq->wpd,StartWPG);
		 if(StartWPG.PosSizePrecision!=0)
		   {
		   cq->perc.Hide();
		   fprintf(cq->err, _("\nError: Unsupported precision, please send me this image for analysis."));
		   }
		 break;
	case 0x2:strcpy(cq->ObjType,"End WPG");
		 NewObject=ResourceEnd;    //skip everything after this
		 break;
	case 0x3:strcpy(cq->ObjType,"!Form Settings"); break;
	case 0x4:strcpy(cq->ObjType,"!Ruller Settings"); break;
	case 0x5:strcpy(cq->ObjType,"!Grid Settings"); break;
	case 0x6:strcpy(cq->ObjType,"!Layer"); break;
	case 0x7:strcpy(cq->ObjType,"!Object Link"); break;
	case 0x8:strcpy(cq->ObjType,"!Pen style definition"); break;
	case 0x9:strcpy(cq->ObjType,"!Pattern Definition"); break;
	case 0xA:strcpy(cq->ObjType,"!Comment"); break;
	case 0x0B:strcpy(cq->ObjType,"!Color Transfer"); break;
	case 0x0C:strcpy(cq->ObjType,"Color Palette");
		  LoadWPGColormap(cq->wpd,WPG.ColorMapRec);
		  if(*Palette!=NULL && (*Palette)->UsageCount==0) delete *Palette;
		  *Palette = BuildPalette(WPG.ColorMapRec.NumOfEntries+WPG.ColorMapRec.StartIndex,8);
		  if(Palette!=NULL)
		     {
		     for(i=WPG.ColorMapRec.StartIndex;i<WPG.ColorMapRec.NumOfEntries;i++)
			 {
			 (*Palette)->R(i,fgetc(cq->wpd));
			 (*Palette)->G(i,fgetc(cq->wpd));
			 (*Palette)->B(i,fgetc(cq->wpd));
			 fgetc(cq->wpd);//Opacity?
			 }
		     }
		  break;
	case 0x0D:strcpy(cq->ObjType,"!DP Color Palette"); break;
	case 0x0E:strcpy(cq->ObjType,"Bitmap Data");
	          LoadWPG2BitmapData(cq->wpd,WPG._2BitmapData);
	          if(WPG._2BitmapData.Compression>1)
		    {
		    cq->perc.Hide();
		    fprintf(cq->err,_("Error: Unsupported WPG2 compression %d, please report."),WPG._2BitmapData.Compression);
		    goto Skip_WP_BMP;
		    }
		  switch(WPG._2BitmapData.Depth)
		    {
		    case 1:i=1;break;
		    case 2:i=2;break;
		    case 3:i=4;break;
		    case 4:i=8;break;
		    case 8:i=24;break;
		    default:goto Skip_WP_BMP;  /*Ignore raster with unknown depth*/
		    }
		  Raster=CreateRaster2D(WPG._2BitmapData.Width,WPG._2BitmapData.Height,i);
		  if(Raster==NULL)
		    {NoImgMemory(cq,WPG._2BitmapData.Width,WPG._2BitmapData.Height);goto Skip_WP_BMP;}

	          if(WPG._2BitmapData.Compression==1)
		    {
		    if(UnpackWPG2Raster(Raster,cq->wpd)<0)
			{
			Raster->Erase();
			if (cq->err != NULL)
			   {
			   cq->perc.Hide();
			   fprintf(cq->err, _("\nError: cannot decompress current WPG raster, skipping!"));
			   }
			}
		    }
		  if(WPG._2BitmapData.Compression==0)
		    {
		    ldblk=(Raster->GetPlanes()*Raster->Size1D+7)/8;
		    for(i=0;i<Raster->Size2D;i++)
			{
			if(fread(Raster->GetRow(i),ldblk,1,cq->wpd)!=1) break;
	      //        AlineProc(i,p);
			}
		    }
		  if(Img.Raster!=NULL)
		    {
		    (*CurrImg)->Next=new Image;
		    (*CurrImg)=(*CurrImg)->Next;
		    }
		  (*CurrImg)->x=x;
		  (*CurrImg)->y=y;
		  (*CurrImg)->dx=dx;
		  (*CurrImg)->dy=dy;
		  x=y=dx=dy=0;
		  if(Raster!=NULL)
		    {
		    if(CTM.member(0,0)<0)
		      {
		      Flip1D(Raster); //?? RotAngle=360-RotAngle;
			/* Try to change CTM according to Flip - I am not sure, must be checked. */
		      float_matrix Tx(3,3);
		      Tx(0,0)=-1;      Tx(1,0)=0;   Tx(2,0)=0;
		      Tx(0,1)= 0;      Tx(1,1)=1;   Tx(2,1)=0;
		      Tx(0,2)=(WPG._2Rect.X_ur+WPG._2Rect.X_ll);
			               Tx(1,2)=0;   Tx(2,2)=1;
		      CTM *= Tx;
		      }
		    if(CTM.member(1,1)<0)
		      {
		      Flip2D(Raster); //?? RotAngle=360-RotAngle;
			  /* Try to change CTM according to Flip - I am not sure, must be checked. */
		      float_matrix Tx(3,3);
		      Tx(0,0)= 1;   Tx(1,0)= 0;   Tx(2,0)=0;
		      Tx(0,1)= 0;   Tx(1,1)=-1;   Tx(2,1)=0;
		      Tx(0,2)= 0;   Tx(1,2)=(WPG._2Rect.Y_ur+WPG._2Rect.Y_ll);
						  Tx(2,2)=1;
		      CTM *= Tx;
		      }
		    (*CurrImg)->Raster=Raster;(*CurrImg)->Raster->UsageCount++;Raster=NULL;
		    }
		  AssignPalette(*CurrImg,*Palette);
		          break;
	case 0x0F:{//CrackObject(cq,NewObject);
		  TextWPG2_2PS(cq,Rec2.RecordLength,PSData,&PSS,&WPG,WPGu2PSu(x),WPGu2PSu(y),0);
		  strcpy(cq->ObjType,"Text Data");
		  break;
		  }
	case 0x10:strcpy(cq->ObjType,"!Chart Style");break;
	case 0x11:strcpy(cq->ObjType,"Chart Data");break;
	case 0x12:{strcpy(cq->ObjType,"Object Image"); /* PostScript WPG2*/
		  //CrackObject(cq,NewObject);//!!!!

	          WORD AccessoryDataLen;
		  Rd_word(cq->wpd,&AccessoryDataLen);
		  if(Rec2.RecordLength>0x12)
		    if(EmImg!=NULL)
		      {
		      EmbeddedImg *Ei2=(EmbeddedImg *)malloc(sizeof(EmbeddedImg));
		      Ei2->Offset=cq->ActualPos+AccessoryDataLen+sizeof(AccessoryDataLen);   /*skip accessory data in the wpg2*/
		      Ei2->Length=Rec2.RecordLength-AccessoryDataLen-sizeof(AccessoryDataLen);
		      Ei2->Extension=Ei2->ImgName=NULL;
		      Ei2->Next=*EmImg;
		      *EmImg=Ei2;
		      }
		  break;
		  }
	case 0x15:{strcpy(cq->ObjType,"Polyline");
		  float *Points,RotAngle;
		  WORD Flags;

		  Flags=LoadWPG2Flags(cq->wpd,CTM,StartWPG.PosSizePrecision,&RotAngle);
			//!!RotAngle Ignored!!!
		  Rd_word(cq->wpd,&WPG.Curve.Count);
		  FixPolySize(cq, &WPG.Curve.Count, Rec2.RecordLength); //insufficient fix -sizeof(CTM)!!!
		  Points=LoadPoints(cq,WPG.Curve.Count,MinX,MaxX,MinY,MaxY);
		  if(Points==NULL) break;
		  if(Flags & 0x2000)	//check Fill flag
		      Polygon2PS(Points, WPG.Curve.Count, PSData, &PSS, Flags&0x8000);
		  else
		      Line2PS(Points, WPG.Curve.Count, PSData, &PSS, Flags&0x4000);
		  free(Points);
		  break;
		  }
	case 0x16:strcpy(cq->ObjType,"!Polyspline");break;
	case 0x17:{strcpy(cq->ObjType,"Polycurve");
		  float *Points,RotAngle;
		  WORD Flags;

		  Flags=LoadWPG2Flags(cq->wpd,CTM,StartWPG.PosSizePrecision,&RotAngle);
			//!!RotAngle Ignored!!!
		  Rd_word(cq->wpd,&WPG.Curve.Count);
		  WPG.Curve.Count*=3;
		  FixPolySize(cq, &WPG.Curve.Count, Rec2.RecordLength); //insufficient fix -sizeof(CTM)!!!
		  Points=LoadPoints(cq,3*WPG.Curve.Count,MinX,MaxX,MinY,MaxY);
		  WPG.Curve.Count/=3;
		  if(Points==NULL) break;
		  Curve2PS(Points,WPG.Curve.Count,PSData,&PSS,
		           Flags&0x2000, Flags&0x8000); //check Fill + Frame flags
		  free(Points);
		  break;
		  }
	case 0x18:{strcpy(cq->ObjType,"Rectangle");
		  WORD Flags;
		  char tmp[80];
		  float Ty=1;

		  Flags=LoadWPG2Flags(cq->wpd,CTM,StartWPG.PosSizePrecision,&RotAngle);
		  LoadWPG2Rectangle(cq->wpd,WPG._2Rect);
		  UpdateBBox(MinX,MaxX,MinY,MaxY, 0,
				   WPG._2Rect.X_ur,WPG._2Rect.Y_ll,WPG._2Rect.X_ll-WPG._2Rect.X_ur,WPG._2Rect.Y_ur-WPG._2Rect.Y_ll);
		  if(WPG._2Rect.H_radius!=WPG._2Rect.V_radius && WPG._2Rect.H_radius!=0  && WPG._2Rect.V_radius!=0)
		     {	//Horizontal and Vertical radiuses are different - scale canvas
		     Ty=WPG._2Rect.V_radius/(float)WPG._2Rect.H_radius;
		     sprintf(tmp,"\ngsave\n0 %2.2f translate\n1 %2.3f scale",
				 WPGu2PSu(WPG._2Rect.Y_ll), 1.0/Ty);
				 WPG._2Rect.Y_ur-=WPG._2Rect.Y_ll;
		     WPG._2Rect.Y_ll=0;
		     PSData+=tmp;
		     }

		  PSData+="\nnewpath";
		  sprintf(tmp,"\n%2.2f %2.2f moveto",WPGu2PSu(WPG._2Rect.X_ur+WPG._2Rect.H_radius),Ty*WPGu2PSu(WPG._2Rect.Y_ll));
		  PSData+=tmp;
		  sprintf(tmp,"\n%2.2f %2.2f %2.2f 270 0 arc",WPGu2PSu(WPG._2Rect.X_ll-WPG._2Rect.H_radius),WPGu2PSu(Ty*WPG._2Rect.Y_ll+WPG._2Rect.H_radius),WPGu2PSu(WPG._2Rect.H_radius));
		  PSData+=tmp;
		  sprintf(tmp,"\n%2.2f %2.2f %2.2f 0 90 arc",WPGu2PSu(WPG._2Rect.X_ll-WPG._2Rect.H_radius),WPGu2PSu(Ty*WPG._2Rect.Y_ur-WPG._2Rect.H_radius),WPGu2PSu(WPG._2Rect.H_radius));
		  PSData+=tmp;
		  sprintf(tmp,"\n%2.2f %2.2f %2.2f 90 180 arc",WPGu2PSu(WPG._2Rect.X_ur+WPG._2Rect.H_radius),WPGu2PSu(Ty*WPG._2Rect.Y_ur-WPG._2Rect.H_radius),WPGu2PSu(WPG._2Rect.H_radius));
		  PSData+=tmp;
		  sprintf(tmp,"\n%2.2f %2.2f %2.2f 180 270 arc",WPGu2PSu(WPG._2Rect.X_ur+WPG._2Rect.H_radius),WPGu2PSu(Ty*WPG._2Rect.Y_ll+WPG._2Rect.H_radius),WPGu2PSu(WPG._2Rect.H_radius));
		  PSData+=tmp;

			  PSData+="\nclosepath";
			  FillObject(WPGu2PSu(WPG._2Rect.X_ur),WPGu2PSu(WPG._2Rect.X_ll),
				     Ty*WPGu2PSu(WPG._2Rect.Y_ll),Ty*WPGu2PSu(WPG._2Rect.Y_ur),
				     PSData,&PSS);
			  if(Ty!=1) PSData+="\ngrestore";
			  break;
			  }
		case 0x19:{strcpy(cq->ObjType,"Arc");
			  char tmp[80];
			  float RotAngle=0;
			  WORD Flags;

			  Flags=LoadWPG2Flags(cq->wpd,CTM,StartWPG.PosSizePrecision,&RotAngle);
			  LoadWPG2Arc(cq->wpd,WPG._2Arc);

			  UpdateBBox(MinX,MaxX,MinY,MaxY, RotAngle, //WPG.Ellipse.RotAngle,
					   WPG._2Arc.Sx-WPG._2Arc.rx,WPG._2Arc.Sy-WPG._2Arc.ry,2*WPG._2Arc.rx,2*WPG._2Arc.ry);

			  PS_Attr(PSData,&PSS);
			  if(fabs(RotAngle)>1e-10)
				  {
				  sprintf(tmp,"\ngsave\n%2.2f %2.2f translate\n%2.2f rotate\n%2.2f %2.2f translate",
						 WPGu2PSu(WPG._2Arc.Sx),WPGu2PSu(WPG._2Arc.Sy), RotAngle, -WPGu2PSu(WPG._2Arc.Sx),-WPGu2PSu(WPG._2Arc.Sy));
				  PSData+=tmp;
				  }
			  PSData+="\nnewpath";
			  sprintf(tmp,"\n%2.2f %2.2f %2.2f %2.2f %d %d DrawEllipse",
				 WPGu2PSu(WPG._2Arc.Sx),WPGu2PSu(WPG._2Arc.Sy),
				 WPGu2PSu(WPG._2Arc.rx),WPGu2PSu(WPG._2Arc.ry),
				 (int)0,(int)360 );
			  PSData+=tmp;
			  PSData+=" closepath";
			  FillObject(WPGu2PSu(WPG._2Arc.Sx-WPG._2Arc.rx),WPGu2PSu(WPG._2Arc.Sx+WPG._2Arc.rx),
				     WPGu2PSu(WPG._2Arc.Sy-WPG._2Arc.ry),WPGu2PSu(WPG._2Arc.Sy+WPG._2Arc.ry),
				     PSData,&PSS);
			  if(RotAngle>0) PSData+="\ngrestore";
			  break;
			  }
		case 0x1A:strcpy(cq->ObjType,"!Compound Polygon");break;
		case 0x1B:{strcpy(cq->ObjType,"Bitmap position");
			  //CrackObject(cq,NewObject);//!!!!
			  WORD Flags;

			  Flags=LoadWPG2Flags(cq->wpd,CTM,StartWPG.PosSizePrecision,&RotAngle);

			  if(StartWPG.PosSizePrecision==0)
			     {
			     LoadWPG2BitmapRectangle(cq->wpd,WPG._2BitmapRectangle);
			     x=WPG._2BitmapRectangle.LowLeftX;
			     y=WPG._2BitmapRectangle.LowLeftY;
			     dx=(WPG._2BitmapRectangle.UpRightX-WPG._2BitmapRectangle.LowLeftX);
			     dy=(WPG._2BitmapRectangle.UpRightY-WPG._2BitmapRectangle.LowLeftY);
			     //break;
			     }
			  if(StartWPG.PosSizePrecision==1)
			     {
			     LoadWPG2DblBitmapRectangle(cq->wpd,WPG._2DblBitmapRectangle);
			     x=WPG._2DblBitmapRectangle.LowLeftX/0x10000;
			     y=WPG._2DblBitmapRectangle.LowLeftY/0x10000;
			     dx=(WPG._2DblBitmapRectangle.UpRightX-WPG._2DblBitmapRectangle.LowLeftX)/(0xFFFF);
			     dy=(WPG._2DblBitmapRectangle.UpRightY-WPG._2DblBitmapRectangle.LowLeftY)/(0xFFFF);
			     //break;
			     }
//			  x=Transform(0,0);  dx=Transform(0,1)-x;
//			  y=Transform(1,0);  dy=Transform(1,1)-y;

			  x /= 47.0;  dx /= 47.0;
			  y /= 47.0;  dy /= 47.0;
			  break;
			  }
		case 0x1C:{
			  strcpy(cq->ObjType,"Text Line");
			  WORD Flags;
			  Flags=LoadWPG2Flags(cq->wpd,CTM,StartWPG.PosSizePrecision,&RotAngle);

			  LoadWPG2TextLine(cq->wpd,WPG._2TxtLine);
			  x=WPG._2TxtLine.Xref;
			  y=WPG._2TxtLine.Yref;
			  UpdateBBox(MinX,MaxX,MinY,MaxY, 0,
					   x,y,0,0);
			  break;
			  }
		case 0x1D:strcpy(cq->ObjType,"!Text Block");break;
		case 0x1E:strcpy(cq->ObjType,"!Text Path");break;
		case 0x1F:strcpy(cq->ObjType,"!Chart");break;
		case 0x20:strcpy(cq->ObjType,"!Group");break;
		case 0x21:{strcpy(cq->ObjType,"!Object Capsule");break;

              		  }
		case 0x22:strcpy(cq->ObjType,"!Font Settings");break;
		case 0x23:strcpy(cq->ObjType,"!Line Cap Definition");break;
		case 0x24:strcpy(cq->ObjType,"!Line Join Definition");break;
		case 0x25:{strcpy(cq->ObjType,"Pen Fore Color");
			  PSS.LineColor.Red=fgetc(cq->wpd);
			  PSS.LineColor.Green=fgetc(cq->wpd);
			  PSS.LineColor.Blue=fgetc(cq->wpd);
			  //PSS.LineColor.Transparency=fgetc(cq->wpd);
			  PSS.dirty |= PSS_LineColor;
			  break;
			  }
		case 0x26:strcpy(cq->ObjType,"!DP Pen Fore Color");break;
		case 0x27:strcpy(cq->ObjType,"!Pen Back Color");break;
		case 0x28:strcpy(cq->ObjType,"!DP Pen Back Color");break;
		case 0x29:{strcpy(cq->ObjType,"Pen Style");
			  BYTE PenStyle;
			  static const BYTE ConvertPen[16]={0,1,2,5,7,10,3,19/*11*/,4,6,8,12,13,16,17/*14*/,18/*15*/};

			  PenStyle=fgetc(cq->wpd);
			  if(PenStyle<16) PenStyle=ConvertPen[PenStyle];
			  if(PSS.LineStyle!=PenStyle)
				{PSS.LineStyle=PenStyle;PSS.dirty|=PSS_LineStyle;}
			  break;
			  }
		case 0x2A:strcpy(cq->ObjType,"!Pen Pattern");break;
		case 0x2B:{strcpy(cq->ObjType,"Pen Size");
			  WORD Width,Height;
			  float LineWidth;

			  Rd_word(cq->wpd,(WORD*)&Width);
			  Rd_word(cq->wpd,(WORD*)&Height);
			  LineWidth=WPGu2PSu(Width>Height?Width:Height);
			  if(PSS.LineWidth!=WPGu2PSu(LineWidth))
				{
				PSS.LineWidth=WPGu2PSu(LineWidth);
				PSS.dirty|=PSS_LineWidth;
				}
			  break;
			  }
		case 0x2C:strcpy(cq->ObjType,"!DP Pen Size");break;
		case 0x2D:strcpy(cq->ObjType,"!Line Cap");break;
		case 0x2E:strcpy(cq->ObjType,"!Line Join");break;
		case 0x2F:strcpy(cq->ObjType,"!Brush Gradient");break;
		case 0x30:strcpy(cq->ObjType,"!DP Brush Gradient");break;
		case 0x31:{strcpy(cq->ObjType,"Brush Fore Color");
			  char GradientType;
			  GradientType=fgetc(cq->wpd);
			  PSS.FillColor.Red=fgetc(cq->wpd);
			  PSS.FillColor.Green=fgetc(cq->wpd);
			  PSS.FillColor.Blue=fgetc(cq->wpd);
			  //PSS.FillColor.Transparency=fgetc(cq->wpd);
			  break;
			  }
		case 0x32:strcpy(cq->ObjType,"!DP Brush Fore Color");break;
		case 0x33:strcpy(cq->ObjType,"!Brush Back Color");break;
		case 0x34:strcpy(cq->ObjType,"!DP Brush Back Color");break;
		case 0x35:strcpy(cq->ObjType,"Brush Pattern");
			  WORD Pattern;
			  Rd_word(cq->wpd,&Pattern);
			  if(Pattern==0) PSS.FillPattern=1;
			  break;
		case 0x36:strcpy(cq->ObjType,"!Horizontal Line");break;
		case 0x37:strcpy(cq->ObjType,"!Vertical Line");break;
		case 0x38:strcpy(cq->ObjType,"!Poster Settings");break;
		case 0x39:strcpy(cq->ObjType,"!Image State");break;
		case 0x3A:strcpy(cq->ObjType,"!Envelope Definition");break;
		case 0x3B:strcpy(cq->ObjType,"!Envelope");break;
		case 0x3C:strcpy(cq->ObjType,"!Texture Definition");break;
		case 0x3D:strcpy(cq->ObjType,"!Brush Texture");break;
		case 0x3E:strcpy(cq->ObjType,"!Texture Alignment");break;
		case 0x3F:strcpy(cq->ObjType,"!Pen Texture");break;

		default: sprintf(cq->ObjType,"?%d?",(int)Rec2.Type); break;
		}
Skip_WP_BMP: ;
}


/** This procedure reads both embedded and WPG files */
Image LoadEmbeddedPictureWPG(TconvertedPass1 *cq, const char *Filename, TBox & Box, EmbeddedImg **EmImg)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#LoadEmbeddedPictureWPG(%s) ",Filename);fflush(cq->log);
#endif
long ldblk;
char ch,NumFormat;
WPGHeader Hdr;
WPGRecord Rec;
WPG2Record Rec2;
WPG_records WPG;
WPG2Start StartWPG;
FILE *SrcImage;
string NewFilename;
float x,y,dx,dy,RotAngle,MinX=65537,MaxX=-1,MinY=65537,MaxY=-1;
Image Img,*CurrImg;
DWORD ResourceEnd,NewObject,i;
Raster2DAbstract *Raster=NULL;
APalette *Palette=NULL;
string PSData;
PS_State PSS={0,0,0};

  CurrImg=&Img;
  RotAngle=x=y=dx=dy=0;
  if(Box.Image_type==1 && Box.Image_size>0) //WPG level 1
    {
TryWPG1:
    if(Filename==NULL) Filename=GetSomeImgName(".wpg");
    if(*Filename==0) Filename=GetSomeImgName(".wpg");
    NewFilename=MergePaths(OutputDir,RelativeFigDir)+GetFullFileName(Filename);

    SrcImage=NULL;
    if(SaveWPG)	// make an attempt to extract resource
      {
/*	  SrcImage=fopen(NewFilename.ch,"r");
      if(SrcImage!=NULL)
	     {
	     fclose(SrcImage);
	     goto NoCopyImage;
	     }*/
      if((SrcImage=fopen(NewFilename,"wb"))==NULL) goto NoCopyImage;
      Hdr.FileId=0x435057FF;
      Hdr.DataOffset=0x10;
      Hdr.ProductType=0x1601;
      Hdr.FileType=0x1;
      Hdr.MajorVersion=0;
      Hdr.MinorVersion=0;
      Hdr.EncryptKey=0;

      savestruct(SrcImage,"ddwwbbw",
	      Hdr.FileId,Hdr.DataOffset,Hdr.ProductType,Hdr.FileType,
	      Hdr.MajorVersion,Hdr.MinorVersion,Hdr.EncryptKey);
      }

    fseek(cq->wpd,Box.Image_offset,SEEK_SET);
    cq->ActualPos=Box.Image_offset;
    ResourceEnd=Box.Image_offset+Box.Image_size; //end of resource

    Palette=BuildPalette(256,8);
    if(Palette!=NULL)
      for(i=0;i<256;i++)
	 {
	 Palette->R(i,WPG_Palette[i].Red);
	 Palette->G(i,WPG_Palette[i].Green);
	 Palette->B(i,WPG_Palette[i].Blue);
	 }

    while(cq->ActualPos<ResourceEnd)
	{
	Rec.RecType=fgetc(cq->wpd);
	Rd_WP_DWORD(cq->wpd,&Rec.RecordLength);
	if(feof(cq->wpd)) break;
	cq->ActualPos=ftell(cq->wpd);
	NewObject=cq->ActualPos+Rec.RecordLength;

	NumFormat=0;
	switch(Rec.RecType)
	  {
	  case  0x1:{strcpy(cq->ObjType,"Fill Attributes");
//		     CrackObject(cq,NewObject);//!!!!
		     PSS.FillPattern=fgetc(cq->wpd);
		     BYTE index=fgetc(cq->wpd);
		     PSS.FillColor=WPG_Palette[index];
		     if(Palette!=NULL)
			 {
			 if(index<Palette->Size1D)
			   {
			   PSS.FillColor.Red = Palette->R(index);
			   PSS.FillColor.Green = Palette->G(index);
			   PSS.FillColor.Blue = Palette->B(index);
			   }
		         }
		     break;
		     }
	  case  0x2:{strcpy(cq->ObjType,"Line Attributes");
		   // CrackObject(cq,NewObject);
		      BYTE LineColor,c;
		      WORD LineWidth;

		      c=fgetc(cq->wpd);
		      if(PSS.LineStyle!=c) {PSS.LineStyle=c;PSS.dirty|=PSS_LineStyle;}
		      LineColor=fgetc(cq->wpd);
		      PSS.LineColor=WPG_Palette[LineColor];
		      if(Palette!=NULL)
			 {
			 if(LineColor<Palette->Size1D)
				{
				PSS.LineColor.Red=Palette->R(LineColor);
				PSS.LineColor.Green=Palette->G(LineColor);
				PSS.LineColor.Blue=Palette->B(LineColor);
				}
			 }
		      PSS.dirty|=PSS_LineColor;
		      Rd_word(cq->wpd,&LineWidth);
		      if(PSS.LineWidth!=WPGu2PSu(2*LineWidth))
			{
			PSS.LineWidth=WPGu2PSu(2*LineWidth);
			PSS.dirty|=PSS_LineWidth;
			}
		      break;
		      }
	  case  0x3:strcpy(cq->ObjType,"!Symbol Attributes"); break;
	  case  0x4:strcpy(cq->ObjType,"!Polysymbol"); break;
	  case  0x5:strcpy(cq->ObjType,"!Line"); break;
	  case  0x6:{strcpy(cq->ObjType,"Curve");
		      float *Points;

		      Rd_word(cq->wpd,&WPG.Curve.Count);
                             FixPolySize(cq, &WPG.Curve.Count, Rec.RecordLength);
		      Points=LoadPoints(cq,WPG.Curve.Count,MinX,MaxX,MinY,MaxY);
		      if(Points==NULL) break;
		      Line2PS(Points,WPG.Curve.Count,PSData,&PSS);
		      free(Points);
		      break;
		      }
	  case  0x7:strcpy(cq->ObjType,"!Rectangle"); break;
	  case  0x8:{strcpy(cq->ObjType,"Polygon");
		      float *Points;

		      Rd_word(cq->wpd,&WPG.Curve.Count);
                             FixPolySize(cq,&WPG.Curve.Count,Rec.RecordLength);
		      Points=LoadPoints(cq,WPG.Curve.Count,MinX,MaxX,MinY,MaxY);
		      if(Points==NULL) break;
		      Polygon2PS(Points, WPG.Curve.Count, PSData, &PSS);
		      free(Points);
		      break;
		      }
	  case  0x9:{strcpy(cq->ObjType,"Elipsis");
//				 CrackObject(cq,NewObject);
		      char tmp[80];

		      Rd_word(cq->wpd,(WORD*)&WPG.Ellipse.Sx);
		      Rd_word(cq->wpd,(WORD*)&WPG.Ellipse.Sy);
		      Rd_word(cq->wpd,(WORD*)&WPG.Ellipse.rx);
		      Rd_word(cq->wpd,(WORD*)&WPG.Ellipse.ry);
		      Rd_word(cq->wpd,&WPG.Ellipse.RotAngle);
		      Rd_word(cq->wpd,&WPG.Ellipse.bAngle);
		      Rd_word(cq->wpd,&WPG.Ellipse.eAngle);
		      WPG.Ellipse.style=fgetc(cq->wpd);

		      UpdateBBox(MinX,MaxX,MinY,MaxY,   WPG.Ellipse.RotAngle,
				   WPG.Ellipse.Sx-WPG.Ellipse.rx,WPG.Ellipse.Sy-WPG.Ellipse.ry,2*WPG.Ellipse.rx,2*WPG.Ellipse.ry);

		      PS_Attr(PSData,&PSS);
		      if(WPG.Ellipse.RotAngle>0)
			  {
			  sprintf(tmp,"\ngsave\n%2.2f %2.2f translate\n%d rotate\n%2.2f %2.2f translate",
					 WPGu2PSu(WPG.Ellipse.Sx),WPGu2PSu(WPG.Ellipse.Sy), (int)WPG.Ellipse.RotAngle, -WPGu2PSu(WPG.Ellipse.Sx),-WPGu2PSu(WPG.Ellipse.Sy));
			  PSData+=tmp;
			  }

		      PSData+="\nnewpath";
		      if(WPG.Ellipse.style==1)
			 {                                          //pie is detected here
			 sprintf(tmp," %2.2f %2.2f moveto",WPGu2PSu(WPG.Ellipse.Sx),WPGu2PSu(WPG.Ellipse.Sy));
			 PSData+=tmp;
			 }
		      sprintf(tmp,"\n%2.2f %2.2f %2.2f %2.2f %d %d DrawEllipse",
			 WPGu2PSu(WPG.Ellipse.Sx),WPGu2PSu(WPG.Ellipse.Sy),
			 WPGu2PSu(WPG.Ellipse.rx),WPGu2PSu(WPG.Ellipse.ry),
			 (int)WPG.Ellipse.bAngle,(int)WPG.Ellipse.eAngle );
		      PSData+=tmp;
		      if( WPG.Ellipse.style!=0 || WPG.Ellipse.bAngle==WPG.Ellipse.eAngle%360)
			{
			PSData+=" closepath";
			FillObject(WPGu2PSu(WPG.Ellipse.Sx-WPG.Ellipse.rx),WPGu2PSu(WPG.Ellipse.Sx+WPG.Ellipse.rx),
				   WPGu2PSu(WPG.Ellipse.Sy-WPG.Ellipse.ry),WPGu2PSu(WPG.Ellipse.Sy+WPG.Ellipse.ry),
				   PSData,&PSS);
			}
		      else PSData+="\nstroke";
		      if(WPG.Ellipse.RotAngle>0) PSData+="\ngrestore";
		      break;
		      }
	  case  0xA:strcpy(cq->ObjType,"!Elipsis"); break;
	  case  0xB:strcpy(cq->ObjType,"Bitmap l1");
		      LoadWPGBitmapType1(cq->wpd,WPG.BitmapType1);
		      if(Raster!=NULL) break;
		      Raster=CreateRaster2D(WPG.BitmapType1.Width,WPG.BitmapType1.Height,WPG.BitmapType1.Depth);

		      if(Raster==NULL) {NoImgMemory(cq,WPG.BitmapType1.Width,WPG.BitmapType1.Height);break;}
		      if(UnpackWPGRaster(Raster,cq->wpd)<0)
				{delete Raster;Raster=NULL;break;}

LoadRaster:	      if(CurrImg->Raster!=NULL)
			{
			CurrImg->Next=new Image;
			CurrImg=CurrImg->Next;
			}
		      RotAngle-=360*((long)RotAngle/360);
		      CurrImg->x=x;
		      CurrImg->y=y;
		      CurrImg->dx=dx;
		      CurrImg->dy=dy;
		      CurrImg->RotAngle=RotAngle;
		      RotAngle=x=y=dx=dy=0;
		      CurrImg->Raster=Raster;CurrImg->Raster->UsageCount++;Raster=NULL;
		      if(CurrImg->Raster->GetPlanes()>1)
                        AssignPalette(CurrImg,Palette);
		      break;
	  case  0xC:strcpy(cq->ObjType,"!Graphics Text");NumFormat=1; break; //This is a bug fix for Draw Perfect WPG
	  case  0xD:{strcpy(cq->ObjType,"Text Attributes");
		      BYTE TextColor;
		      fseek(cq->wpd, 19, SEEK_CUR);
		      TextColor=fgetc(cq->wpd);
		      PSS.TextColor=WPG_Palette[TextColor];
		      break;
		      }
	  case  0xE:strcpy(cq->ObjType,"Color Map");
		      LoadWPGColormap(cq->wpd,WPG.ColorMapRec);
		      if(Palette!=NULL && Palette->UsageCount==0) delete Palette;
		      Palette=BuildPalette(WPG.ColorMapRec.NumOfEntries+WPG.ColorMapRec.StartIndex,8);
		      if(Palette!=NULL)
			 {
			 fread((char *)Palette->Data1D + 3*WPG.ColorMapRec.StartIndex,
				3*WPG.ColorMapRec.NumOfEntries,1,cq->wpd);
			  }
		      break;	// NumFormat=1; // default DR
	  case  0xF:strcpy(cq->ObjType,"!Start WPG l1"); break;
	  case 0x10:strcpy(cq->ObjType,"!End WPG l1"); break;
	  case 0x11:strcpy(cq->ObjType,"Start PS l1");
		      if(Rec.RecordLength>8)
			{
			if(EmImg!=NULL)
			  {
			  EmbeddedImg *Ei2=(EmbeddedImg *)malloc(sizeof(EmbeddedImg));
			  Ei2->Offset=cq->ActualPos+8;   /*skip PS header in the wpg*/
			  Ei2->Length=Rec.RecordLength-8;
			  Ei2->Extension=Ei2->ImgName=NULL;
			  Ei2->Next=*EmImg;
			  *EmImg=Ei2;
			  }
			}
		      break;
	  case 0x12:strcpy(cq->ObjType,"!Output Attributes"); break;
	  case 0x13:{strcpy(cq->ObjType,"Plain Curve");
		      fseek(cq->wpd, 4, SEEK_CUR);
		      char tmp[60];

		      PS_Attr(PSData,&PSS);
		      Rd_word(cq->wpd,&WPG.Curve.Count);
                             FixPolySize(cq, &WPG.Curve.Count, Rec.RecordLength);
		      WPG.Curve.x=Rd_word_MMX(cq->wpd,MinX,MaxX);
		      WPG.Curve.y=Rd_word_MMX(cq->wpd,MinY,MaxY);
		      sprintf(tmp,"\nnewpath\n%2.2f %2.2f moveto",WPGu2PSu(WPG.Curve.x),WPGu2PSu(WPG.Curve.y));
		      PSData+=tmp;
		      if((WPG.Curve.Count-1)%3==0)
			   while(WPG.Curve.Count>1)
			    {
			    WORD rx,ry,qx,qy;
			    rx=Rd_word_MMX(cq->wpd,MinX,MaxX);
			    ry=Rd_word_MMX(cq->wpd,MinY,MaxY);
			    qx=Rd_word_MMX(cq->wpd,MinX,MaxX);
			    qy=Rd_word_MMX(cq->wpd,MinY,MaxY);
			    WPG.Curve.x=Rd_word_MMX(cq->wpd,MinX,MaxX);
			    WPG.Curve.y=Rd_word_MMX(cq->wpd,MinY,MaxY);
			    sprintf(tmp,"\n%2.2f %2.2f %2.2f %2.2f %2.2f %2.2f curveto",
				WPGu2PSu(rx),WPGu2PSu(ry),WPGu2PSu(qx),WPGu2PSu(qy),
				WPGu2PSu(WPG.Curve.x),WPGu2PSu(WPG.Curve.y) );
			    PSData+=tmp;
			    WPG.Curve.Count-=3;
			    }
		      else while(WPG.Curve.Count-->1)
			    {
			    WPG.Curve.x=Rd_word_MMX(cq->wpd,MinX,MaxX);
			    WPG.Curve.y=Rd_word_MMX(cq->wpd,MinY,MaxY);
			    sprintf(tmp,"\n%2.2f %2.2f lineto",WPGu2PSu(WPG.Curve.x),WPGu2PSu(WPG.Curve.y));
			    PSData+=tmp;
			    }
		      PSData+="\nstroke";
		      break;
		      }
	  case 0x14:{
		      strcpy(cq->ObjType,"Bitmap l2");
		      LoadWPGBitmapType2(cq->wpd,WPG.BitmapType2);
		      if(Raster!=NULL) break;
		      Raster=CreateRaster2D(WPG.BitmapType2.Width,WPG.BitmapType2.Height,WPG.BitmapType2.Depth);
		      if(Raster==NULL) {NoImgMemory(cq,WPG.BitmapType2.Width,WPG.BitmapType2.Height);break;}
		      x=WPG.BitmapType2.LowLeftX/47.0;
		      y=WPG.BitmapType2.LowLeftY/47.0;
		      dx=(WPG.BitmapType2.UpRightX-WPG.BitmapType2.LowLeftX)/47.0;
		      dy=(WPG.BitmapType2.UpRightY-WPG.BitmapType2.LowLeftY)/47.0;
		      RotAngle=WPG.BitmapType2.RotAngle & 0x0FFF;
		      if(UnpackWPGRaster(Raster,cq->wpd)<0)
				{delete Raster;Raster=NULL;break;}

		      if(WPG.BitmapType2.RotAngle & 0x8000)
			   {Flip1D(Raster);RotAngle=360-RotAngle;}
		      if(WPG.BitmapType2.RotAngle & 0x2000)
			   {
			   Flip2D(Raster);
			   if((WPG.BitmapType2.RotAngle & 0x8000)==0)
				RotAngle=360-RotAngle;
			   }
		      goto LoadRaster;
		      }
	  case 0x15:strcpy(cq->ObjType,"!Start Image"); break;
	  case 0x16:strcpy(cq->ObjType,"!Start Graph"); break;
	  case 0x17:strcpy(cq->ObjType,"!Plan Perfect"); break;
	  case 0x18:  // NumFormat=1; // default DR
//			      CrackObject(cq,NewObject);
		      ldblk=Rec.RecordLength-21;
		      if(ldblk>0)
			{
			fseek(cq->wpd,cq->ActualPos+4,SEEK_SET);
			Rd_word(cq->wpd,&WPG.TextL2.RotAngle);
			WPG.TextL2.RotAngle=WPG.TextL2.RotAngle%360;
			fseek(cq->wpd,cq->ActualPos+8,SEEK_SET);
			Rd_word(cq->wpd,(WORD *)&WPG.TextL2.LowLeftX);
			Rd_word(cq->wpd,(WORD *)&WPG.TextL2.LowLeftY);
			Rd_word(cq->wpd,(WORD *)&WPG.TextL2.UpRightX);
			Rd_word(cq->wpd,(WORD *)&WPG.TextL2.UpRightY);
			UpdateBBox(MinX,MaxX,MinY,MaxY, WPG.TextL2.RotAngle,
				   WPG.TextL2.LowLeftX,WPG.TextL2.LowLeftY,WPG.TextL2.UpRightX-WPG.TextL2.LowLeftX,WPG.TextL2.UpRightY-WPG.TextL2.LowLeftY);
			Textl2_2PS(cq,ldblk,PSData, &PSS,&WPG);
			}
		      strcpy(cq->ObjType,"Graphics Text l2");
		      break;
	  case 0x19:strcpy(cq->ObjType,"!Data Start l2");  break;
	  case 0x1A:strcpy(cq->ObjType,"!Graphics Text l3"); break;
	  case 0x1B:strcpy(cq->ObjType,"PostScript l2");
		    if(Rec.RecordLength>0x3B)
		      if(EmImg!=NULL)
		        {
		        EmbeddedImg *Ei2=(EmbeddedImg *)malloc(sizeof(EmbeddedImg));
		        Ei2->Offset=cq->ActualPos+0x3C;   /*skip PS l2 header in the wpg*/
		        Ei2->Length=Rec.RecordLength-0x3C;
		        Ei2->Extension=Ei2->ImgName=NULL;
		        Ei2->Next=*EmImg;
		        *EmImg=Ei2;
			}
		      break;
	  default: sprintf(cq->ObjType,"?%d?",(int)Rec.RecType); break;
	  }

//Save WPG to the disk file
    if(SrcImage)
	      {
	      fseek(cq->wpd,cq->ActualPos,SEEK_SET);
	      fputc(Rec.RecType,SrcImage);
	      Wr_WP_DWORD(SrcImage, Rec.RecordLength, NumFormat);
	      for(i=0;i<Rec.RecordLength;i++)
		      {
		      ch=fgetc(cq->wpd);
		      if(feof(cq->wpd)) break;
		      fputc(ch,SrcImage);
		      }
	      }

//Log a graphical image object into report
	    if(cq->log!=NULL)
		    {
		    fprintf(cq->log,"\n%*s{GRtyp#%X;len:%lx;%s}",cq->recursion * 2, "",
		       (int)Rec.RecType,(long)Rec.RecordLength,cq->ObjType);
		    #ifdef DEBUG
		    fflush(cq->log);
		    #endif //DEBUG
		    }
	    if(*cq->ObjType=='!') {UnknownObjects++;*cq->ObjType=0;}

	    if(NewObject!=ftell(cq->wpd))
		    fseek(cq->wpd,NewObject,SEEK_SET);
	    cq->ActualPos=NewObject;
	    } /**/

    if(SrcImage) {fclose(SrcImage);SrcImage=NULL;}
    Box.Image_size=0;
    }

  if(Box.Image_type==2 && Box.Image_size>0) //WPG level 2 (might contain l.1 or different content)
    {
    float_matrix CTM(3,3);

    if(Filename==NULL) Filename=GetSomeImgName(".wpg");
    if(*Filename==0) Filename=GetSomeImgName(".wpg");
    NewFilename=MergePaths(OutputDir,RelativeFigDir)+GetFullFileName(Filename);

    fseek(cq->wpd,Box.Image_offset,SEEK_SET);
    ResourceEnd = Box.Image_offset+Box.Image_size; //end of resource

    loadstruct(cq->wpd,"ddwwbbw",
	      &Hdr.FileId,&Hdr.DataOffset,&Hdr.ProductType,&Hdr.FileType,
	      &Hdr.MajorVersion,&Hdr.MinorVersion,&Hdr.EncryptKey);
    if(Hdr.FileId!=0x435057FF || Hdr.EncryptKey!=0) goto NoCopyImage;

    if((Hdr.ProductType>>8)==0x30)
      {
      cq->perc.Hide();
      if(SaveWPG)
        {
	printf("\n!!!! MAC WPG1 detected!!!! %X",Box.Image_offset);
        if((SrcImage=fopen(NewFilename,"wb"))==NULL)
	   {
	   if(cq->err!=NULL && Verbosing>=0)
	       {
	       cq->perc.Hide();
	       fprintf(cq->err, _("\nError: Cannot write to the file %s !"),NewFilename());
	       }
	   goto NoCopyImage;
	   }
        fseek(cq->wpd,Box.Image_offset,SEEK_SET);
        for(i=0;i<Box.Image_size;i++)
	   {
	   ch = fgetc(cq->wpd);
	   //if(feof(cq->wpd)) putchar('!');
	   fputc(ch,SrcImage);
	   }
        fclose(SrcImage);
	//printf("...extracted.%X......",ftell(cq->wpd));
        }

      cq->ActualPos = Box.Image_offset+0x10;
      fseek(cq->wpd, cq->ActualPos, SEEK_SET);
      while(cq->ActualPos<ResourceEnd)
	{
	RdDWORD_HiEnd(&Rec2.RecordLength, cq->wpd);
	NewObject = ftell(cq->wpd) + Rec2.RecordLength;
	Rec2.Class = fgetc(cq->wpd);
	Rec2.Type = fgetc(cq->wpd);

	switch(Rec2.Type)
	  {
	  case 0:   strcpy(cq->ObjType,"!Start WPG MAC"); break;
	  case 0x11:strcpy(cq->ObjType,"!Graphics Text"); break;
	  default:  cq->ObjType[0] = 0;
	  }

	if(cq->log!=NULL)
	  {
	  fprintf(cq->log,"\n%*s{GRtyp#%X;len:%lXh;%s}",cq->recursion * 2, "",
		     (int)Rec2.Type,(long)Rec2.RecordLength,cq->ObjType);
		    //fprintf(cq->log,"MaxY= %2.2f",MaxY);
	  fprintf(cq->log," Pos= %lX",cq->ActualPos);
	  }
	cq->ActualPos = (NewObject+1) & ~1;
        fseek(cq->wpd,cq->ActualPos,SEEK_SET);
	}
      goto NoCopyImage;
      }

    if((Hdr.ProductType>>8)!=0x16)  goto NoCopyImage;
    if(Hdr.FileType==1)  /*WPG level 1 with header*/
	{
	Box.Image_offset+=Hdr.DataOffset;
	Box.Image_size-=Hdr.DataOffset;
	if(Box.Image_size>0) goto TryWPG1;
	}
    if(Hdr.FileType!=2) goto NoCopyImage;

    if(SaveWPG)	// make an attempt to extract resource
      {
      /*  SrcImage=fopen(NewFilename.ch,"r");  // Check for file existency.
      if(SrcImage!=NULL)
	     {
	     fclose(SrcImage);
	     goto NoCopyImage;
	     }*/
      if((SrcImage=fopen(NewFilename,"wb"))==NULL)
	   {
	   if(cq->err!=NULL && Verbosing>=0)
	       {
	       cq->perc.Hide();
	       fprintf(cq->err, _("\nError: Cannot write to the file %s !"),NewFilename());
	       }
	   goto NoCopyImage;
	   }
      fseek(cq->wpd,Box.Image_offset,SEEK_SET);
      for(i=0;i<Box.Image_size;i++)
		{
		ch=fgetc(cq->wpd);
		fputc(ch,SrcImage);
		}
      fclose(SrcImage);
      }

    fseek(cq->wpd,Box.Image_offset+Hdr.DataOffset,SEEK_SET);
    cq->ActualPos=Box.Image_offset+Hdr.DataOffset;
    StartWPG.PosSizePrecision=0;
    PSS.LineStyle=1;

    while(cq->ActualPos<ResourceEnd)
	    {
	    Rec2.Class=fgetc(cq->wpd);
	    Rec2.Type=fgetc(cq->wpd);
	    Rd_WP_DWORD(cq->wpd,&Rec2.Extension);
	    Rd_WP_DWORD(cq->wpd,&Rec2.RecordLength);
	    cq->ActualPos=ftell(cq->wpd);
	    NewObject=cq->ActualPos+Rec2.RecordLength;

	    if(feof(cq->wpd)) break;

            ProcessWPG2Token(cq, Rec2, StartWPG, Img, CTM, &Palette,
              PSData, PSS, EmImg, NewObject, ResourceEnd, &CurrImg,
              x, y, dx, dy, RotAngle, MinX, MaxX, MinY, MaxY);

		//Log a graphical image object into report
	    if(cq->log!=NULL)
		    {
		    fprintf(cq->log,"\n%*s{GRtyp#%X;len:%lXh;%s}",cq->recursion * 2, "",
		       (int)Rec2.Type,(long)Rec2.RecordLength,cq->ObjType);
		    //fprintf(cq->log,"MaxY= %2.2f",MaxY);
		    fprintf(cq->log," Pos= %lX",cq->ActualPos);
		    }
	    if(*cq->ObjType=='!') {UnknownObjects++;*cq->ObjType=0;}

	    if(NewObject!=ftell(cq->wpd))
		    fseek(cq->wpd,NewObject,SEEK_SET);
	    cq->ActualPos=NewObject;
	    }
    Box.Image_size=0;
    }

 if(PSData!="")		//Transfer PostScript part into Image
   {
   if(Img.Raster!=NULL || Img.Comment!=NULL)
	{
	CurrImg->Next=new Image;
	CurrImg=CurrImg->Next;
	}
   if(CurrImg!=NULL)
	{
	CurrImg->x = MinX/47.0;
	CurrImg->y = MinY/47.0;
	CurrImg->dx=(MaxX-MinX)/47.0;
	CurrImg->dy=(MaxY-MinY)/47.0;
	CurrImg->RotAngle=0;
	CurrImg->Comment=PSData.ExtractString();
	}
   }

 if(Palette!=NULL && Palette->UsageCount==0) {delete Palette;Palette=NULL;}
 if(Raster!=NULL && Raster->UsageCount==0) {delete Raster;Raster=NULL;}

NoCopyImage:
return Img;
}


/** This is replacement for LoadPicture for the wp2latex purposes. */
Image WP2L_LoadPictureWPG(TconvertedPass1 *cq,const char *FileName)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#WP2L_LoadPictureWPG(%s) ",FileName);fflush(cq->log);
#endif
TBox Box;
FILE *WPD_Backup,*f;
DWORD ActualPos_Backup,fsize;
EmbeddedImg *EmImTmp,*EmImg=NULL;
Image Img;
boolean Bk_SaveWPG;

  if((f=fopen(FileName,"rb"))==NULL) return(NULL);
  if(cq->log) fprintf(cq->log,_("\nOpening external image %s "),FileName);

  WPD_Backup = cq->wpd;
  ActualPos_Backup=cq->ActualPos;

  cq->wpd = f;
  cq->ActualPos=0;
  fsize = filesize(cq->wpd);

  Box.HorizontalPos=3;		/*3-Full */
  Box.Image_offset=0;
  Box.Image_size=fsize-Box.Image_offset;
  Box.Image_type=2;		/*WPG l2 embedded parser has also autodetect for WPG l.1*/
  Box.Contents = 3; 		/*content image - every images are internally converted into WPG*/
  Box.CaptionPos=0;
  Box.CaptionSize=0;

  Bk_SaveWPG=SaveWPG;
  SaveWPG=false;
  Img = LoadEmbeddedPictureWPG(cq,FileName,Box,&EmImg);

  while(EmImg!=NULL)	//embedded PS and other files should be processed here
     {
     if(EmImg->Length>0)
       if(cq->err!=NULL && Verbosing>=0)
         {
         cq->perc.Hide();
         fprintf(cq->err, _("\nError: Embedded image discarded!"));
         }
     EmImTmp = EmImg->Next;
     free(EmImg);
     EmImg = EmImTmp;
     }

  SaveWPG = Bk_SaveWPG;

  fclose(f);
  cq->wpd=WPD_Backup;
  cq->ActualPos=ActualPos_Backup;

  if(Img.Raster==NULL && Img.Comment==NULL)   // last chance - try to load any file format
        Img = LoadPicture(FileName);
        
  return Img;
}


/** Patch for LoadPicture that allows to use advanced WPG support. */
inline Image WP2L_LoadPicture(TconvertedPass1 *cq, const char *Name)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#WP2L_LoadPicture(%s) ",Name);fflush(cq->log);
#endif
Image Img;
   Img = WP2L_LoadPictureWPG(cq,Name);
   if(Img.Raster!=NULL || Img.Comment!=NULL) return(Img);
return LoadPicture(Name);
}


/** Main procedure that extracts WPG blocks from WP files and also handles external files. */
void ImageWP(TconvertedPass1 *cq, const char *Filename, TBox & Box,
	   void (*DoCaption)(TconvertedPass1 *,unsigned short))
{
#ifdef DEBUG
  fprintf(cq->log,"\n#ImageWP(%s) ",Filename);fflush(cq->log);
#endif
int i;
int lines=0;
const char *ss;
string NewFilename;
string FileExtension;
Image Img;
EmbeddedImg *EmImTmp,*EmImg=NULL;
FILE *SrcImage;
TconvertedPass1 *cq1_new;

  if(InputPS<false) return;  /* The PS image feature is disabled */

  if(Filename==NULL) Filename=GetSomeImgName(".wpg"); //invent some filename if empty
  if(*Filename==0) Filename=GetSomeImgName(".wpg");

  if(Filename)
  {
    if(!strcmp(Filename,"*OLE*"))
	{
	Filename = GetSomeImgName(".wpg"); //fix for embedded OLE objects
	}
  }

  Img = LoadEmbeddedPictureWPG(cq,Filename,Box,&EmImg);

  NewFilename = MergePaths(OutputDir,RelativeFigDir)+CutFileName(Filename)+".eps";

  ss = GetExtension(Filename);
  if(ss!=NULL) if(*ss!=0) FileExtension=ToUpper(ss+1);

  if(NewFilename!="")
     for(i=StrLen(OutputDir);i<length(NewFilename);i++)
	{
	if(NewFilename[i]==' ' || NewFilename[i]=='#' || NewFilename[i]=='%' || NewFilename[i]=='$' || NewFilename[i]=='*')
		{
		if(cq->err != NULL)
		  {
		  cq->perc.Hide();
		  fprintf(cq->err, _("\nWarning: LaTeX cannot process filenames that contain '%c'-> fixed to '_'!"),NewFilename[i]);
		  }
		NewFilename[i]='_';
		}
	}

  if(FileExtension=="PS" || FileExtension=="EPS")
     {			// Chybi verifikace na ps!!!!!!!
     if(AbsolutePath(Filename))
	{
	if(!CopyFile(NewFilename,Filename)) goto FileIsOK;
	}
     else
	{
	for(i=0;i<length(ImgInputDirs);i++)
	  {
	  if(!CopyFile(NewFilename,(string(ImgInputDirs[i])+Filename)())) goto FileIsOK;
	  }
	}
     }

  if(Img.Raster!=NULL || Img.Comment!=NULL)  /*Convert raster image into the PostScript*/
	{
SavePS: 
#ifndef NO_IMG
	ReducePalette(&Img,256);
#endif
	if(SavePictureEPS(NewFilename(),Img)<0)
	    {
            if(cq->err != NULL)
		  {
		  cq->perc.Hide();
		  fprintf(cq->err, _("\nError: Cannot save file:%s !"),NewFilename());
		  }
            }
	goto FileIsOK;  ///!!!!!!!!!!! Possible leak EmImg, fixed!!!!!
	}

  while(EmImg!=NULL)
     {
     if(EmImg->Offset>8 && EmImg->Length>0) /*Try to extract PS part from WPG metafile*/
	{
        fseek(cq->wpd,EmImg->Offset,SEEK_SET);
	if(CopyFile(NewFilename(),cq->wpd,EmImg->Length)>=-1)
	  {	
	  EmImg->Length = 0;

	  if( (SrcImage=fopen(NewFilename,"rb"))==NULL )
	    {
            if(cq->err)
	      fprintf(cq->err, _("\nError: Cannot open file %s for reading!"),NewFilename());
	    goto FileIsOK;
            }

	  CheckFileFormat(SrcImage,FilForD);
	  if(!strcmp(FilForD.Convertor,"EPS") || !strcmp(FilForD.Convertor,"PS"))
	    {             //EPS is detected
            fclose(SrcImage);
            SrcImage = NULL;
            goto FileIsOK;  ///!!!!!!!!!!! Toohle je blbe - leak EmImg!!!!!
            }

          if(FilForD.Convertor==NULL) {fclose(SrcImage);SrcImage=NULL;}
          else
            {
	    if(*FilForD.Convertor==0) {fclose(SrcImage);SrcImage=NULL;}
            }

	  if(SrcImage)
            {
	    cq1_new = GetConvertor(FilForD.Convertor);
	    if(cq1_new!=NULL)
	      {
	      if(Verbosing >= 1) printf(_("[nested \"%s\" %s] "),NewFilename(),FilForD.Convertor);
	      cq1_new->InitMe(SrcImage,cq->table,cq->strip,cq->log,cq->err);
	      cq1_new->recursion=cq->recursion+1;
	      cq1_new->Dispatch(DISP_NOCONVERTIMAGE,1);
	      i=cq1_new->Convert_first_pass();
	      if(Verbosing >= 1) printf(_("\n[continuing] "));
	      if(cq->log!=NULL) fputs(_("\n--End or nested file.--\n"),cq->log);
	      cq->perc.displayed=false;

	      Image *pImg=NULL;
	      cq1_new->Dispatch(DISP_EXTRACTIMAGE,&pImg);

	      if(pImg)
                {
 	        if(pImg->Raster!=NULL || pImg->Comment!=NULL)  /*Convert raster image into the PostScript*/
	          {		//here should be called reduction of colors
#ifndef NO_IMG
		  ReducePalette(pImg,256);
#endif
		  if(SavePictureEPS(NewFilename(),*pImg)>=0)
                    {
		    delete cq1_new;
		    delete pImg;
		    goto FileIsOK;
                    }
                  }
		delete pImg;
                }

	      delete cq1_new;
	      }
	    else
	       fprintf(cq->err, _("\nError: Conversion module \"%s\" is not available for file %s!"),FilForD.Convertor,NewFilename());
	    fclose(SrcImage);
            }
          else
	    fprintf(cq->err, _("\nError: Cannot detect fileformat of file %s!"),NewFilename());
	  }
	}
    EmImTmp=EmImg->Next;
    free(EmImg);
    EmImg=EmImTmp;
    }

	/* Try to load image from external file */
  if(AbsolutePath(Filename))
     {
     Img = WP2L_LoadPicture(cq,Filename);
     if(Img.Raster!=NULL) goto SavePS;
     }
  else
     for(i=0;i<length(ImgInputDirs);i++)
	{
        string FnamePath = string(ImgInputDirs[i]) + Filename;
#if defined(__MSDOS__) || defined(__WIN32__) || defined(_WIN32) || defined(_WIN64) || defined(__OS2__)
        FnamePath = replacesubstring(FnamePath, "/","\\");
#else
        FnamePath = replacesubstring(FnamePath, "\\","/");
#endif
	Img = WP2L_LoadPicture(cq,FnamePath());
	if(Img.Raster!=NULL) goto SavePS;
	}

  MakeDummyPS(cq, Filename, NewFilename);

FileIsOK:
  while(EmImg!=NULL)		// Check for remaining EmImg fragments and erase them.
     {
     if(EmImg->Length>0)
       printf("\nResource 'embedded image' is lost, please fix.");
     EmImTmp=EmImg->Next;
     free(EmImg);
     EmImg=EmImTmp;
     }

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

  if(cq->char_on_line == -20)    /* Left one enpty line for new enviroment */
	{
	fputc('%', cq->strip);
	NewLines(cq,2);
	}
  if(cq->char_on_line==true)    /* make new line for leader of minipage */
	NewLines(cq,1);

  if(cq->flag == HeaderText || cq->envir=='B') Box.AnchorType=2;

//This writes a TeX program for including an image into the document
  InputPS|=1;
  if(Box.AnchorType!=2)
	{
	if(!BoxTexHeader(cq, Box)) Box.CaptionSize=0;
	putc('\n',cq->strip); lines++;
	}

  if(InputPS & 2)	//graphicx.sty
    {
    if(Box.AnchorType!=2) fprintf(cq->strip," \\begin{center}");
    if(fabs(Box.HScale-1)>1e-4 || fabs(Box.VScale-1)>1e-4)
		fprintf(cq->strip," \\scalebox{%2.2f}[%2.2f]{",Box.HScale,Box.VScale);
    if(Box.RotAngle!=0) fprintf(cq->strip," \\rotatebox{%d}{",Box.RotAngle);
    fprintf(cq->strip,"\\includegraphics");
    switch(Box.HorizontalPos)
	{
	case 4:if(Box.Width>0)
		   {
		   fprintf(cq->strip,"[width=%2.2f\\textwidth]",Box.Width/100);break;
		   }
	case 3:fprintf(cq->strip,"[width=\\textwidth]");break;
	default:fprintf(cq->strip,"[width=%2.2fcm]",
		  (Box.Width>0) ? (Box.Width/10.0) : DEFAULT_BOX_WIDTH);
	}
    fprintf(cq->strip,"{%s.eps}",NewFilename() );
    if(Box.RotAngle!=0) fprintf(cq->strip,"}");
    if(fabs(Box.HScale-1)>1e-4 || fabs(Box.VScale-1)>1e-4) fprintf(cq->strip,"}");
    if(Box.AnchorType!=2) fprintf(cq->strip," \\end{center}");
    putc('\n',cq->strip); lines++;
    }
  else if(InputPS & 4)	//epsfig.sty
    {
    if(Box.AnchorType!=2) fprintf(cq->strip," \\begin{center}");
    fprintf(cq->strip,"\\epsfig{file=\\FigDir/%s.eps,",NewFilename() );
    switch(Box.HorizontalPos)
	{
	case 4:if(Box.Width>0)
		   {
		   fprintf(cq->strip,"width=%2.2f\\textwidth",Box.Width/100);break;
		   }
	case 3:fprintf(cq->strip,"width=\\textwidth");break;
	default:fprintf(cq->strip,"width=%2.2fcm",
                   (Box.Width>0) ? (Box.Width/10.0) : DEFAULT_BOX_WIDTH);
	}
    if(Box.RotAngle!=0) fprintf(cq->strip,",angle=%d",Box.RotAngle);
    putc('}',cq->strip);
    if(Box.AnchorType!=2) fprintf(cq->strip," \\end{center}");
    putc('\n',cq->strip); lines++;
    }
  else if(InputPS & 8)	//graphics.sty
    {
    if(Box.AnchorType!=2) fprintf(cq->strip," \\begin{center}");
    if(fabs(Box.HScale-1)>1e-4 || fabs(Box.VScale-1)>1e-4)
		fprintf(cq->strip," \\scalebox{%2.2f}[%2.2f]{",Box.HScale,Box.VScale);
    else
      {
      if(Box.Width>0 && Box.HorizontalPos!=3)
          fprintf(cq->strip,"\\resizebox{%2.2fcm}{!}{", Box.Width/10);
      }
    if(Box.RotAngle!=0) fprintf(cq->strip," \\rotatebox{%d}{",Box.RotAngle);
    fprintf(cq->strip,"\\includegraphics");
    fprintf(cq->strip,"{%s.eps}",NewFilename() );
    if(Box.RotAngle!=0) fprintf(cq->strip,"}");
    if(fabs(Box.HScale-1)>1e-4 || fabs(Box.VScale-1)>1e-4) 
	fprintf(cq->strip,"}");
    else
      {
      if(Box.Width>0 && Box.HorizontalPos!=3)
          fprintf(cq->strip,"}");
      }
    if(Box.AnchorType!=2) fprintf(cq->strip," \\end{center}");
    putc('\n',cq->strip); lines++;
    }
  else			//InputPS.sty
    {
    char RotFlag=0;
    if(Box.RotAngle!=0)
      {
      switch(Box.RotAngle)
        {
        case 90: RotFlag='l';break;
        case 180:RotFlag='u';break;
        case 270:RotFlag='r';break;
	}
      if(RotFlag)
        {
        if(Rotate>=false) Rotate=true;
                     else RotFlag=0;
	}
      if(!RotFlag)
        if(cq->err!=NULL && Verbosing>=0)
	  {
	  cq->perc.Hide();
	  fprintf(cq->err, _("\nError: InputPS.sty does not support box rotation. Use graphics.sty, graphicx.sty or epsfig.sty instead."));
	  }
      }
    fprintf(cq->strip,"\\begin{forcewidth}");
    switch(Box.HorizontalPos)
	{
	case 4:if(Box.Width>0)
		   {
		   fprintf(cq->strip,"{%2.2f\\textwidth}\n",Box.Width/100);break;
		   }
	case 3:fprintf(cq->strip,"{\\textwidth}\n");break;
	default:fprintf(cq->strip,"{%2.2fcm}\n",
                   (Box.Width>0) ? (Box.Width/10.0) : DEFAULT_BOX_WIDTH);
	}
    lines++;
    if(Box.AnchorType!=2) fprintf(cq->strip," \\begin{center}");
    if(RotFlag)
    {
      WP2LaTeXsty+=sty_rotate;
      fprintf(cq->strip," \\rotate[%c]{",RotFlag);
    }
    fprintf(cq->strip,"\\InputPS{\\FigDir/%s.eps}",NewFilename() );
    if(RotFlag) fprintf(cq->strip,"}");
    if(Box.AnchorType!=2) fprintf(cq->strip," \\end{center}");
    putc('\n',cq->strip); lines++;
    fprintf(cq->strip,"\\end{forcewidth}\n");lines++;
    }
  if(Box.CaptionSize>0 && Box.CaptionPos>0 && Box.AnchorType!=2 && DoCaption)
	{
	fseek(cq->wpd,Box.CaptionPos,SEEK_SET);
	if(lines>0) NewLines(cq,lines,false);
	lines=0;
	DoCaption(cq,Box.CaptionSize);
	}

  if(Box.AnchorType!=2)
	{
	BoxTexFoot(cq, Box);
	fprintf(cq->strip,"\n");
	lines++;
	}

  if(lines>0) NewLines(cq,lines,false);
  cq->char_on_line = (Box.AnchorType==2)?-1:false;
}


/*----------Convertor for external standalone images----------*/

class TconvertedPass1_WPG: public TconvertedPass1
{
public:
    virtual int Convert_first_pass(void);
};


int TconvertedPass1_WPG::Convert_first_pass(void)
{
#ifdef DEBUG
  fprintf(log,"\n#Convert_pass1_WPG() ");fflush(log);
#endif
DWORD fsize;
TBox Box;
boolean Bk_SaveWPG;

  DocumentStart=ftell(wpd);

  fsize = filesize(wpd);
  perc.Init(ftell(wpd), fsize, _("First pass WPG:") );

  ActualPos = 0;

  Box.HorizontalPos=3;		/*3-Full */
  Box.Image_offset=ActualPos;
  Box.Image_size=fsize-Box.Image_offset;
  Box.Image_type=2;		/*WPG l2 parser has also autodetect for WPG l.1*/
  Box.Contents = 3; 		/*content image - every images are internally converted into WPG*/
  Box.CaptionPos=0;
  Box.CaptionSize=0;

  Bk_SaveWPG = SaveWPG;
  SaveWPG = false;
  ImageWP(this, wpd_filename(), Box, NULL);
  SaveWPG = Bk_SaveWPG;

  Finalise_Conversion(this);
  return(1);
}

TconvertedPass1 *Factory_WPG(void) {return new TconvertedPass1_WPG;}
FFormatTranslator FormatWPG("WPG",&Factory_WPG);


#ifndef NO_IMG
 FFormatTranslator FormatBMP("BMP",&Factory_WPG);
 FFormatTranslator FormatPNG("PNG",&Factory_WPG);
#endif

/*-------End of WPG convertor--------*/
