/******************************************************************************
 * program:     wp2latex                                                      *
 * function:    convert WordPerfect 6.x, 7.x, 8.x files into LaTeX	      *
 * modul:       pass1_6.cc                                                    *
 * description: This modul contains functions for first pass. In the first    *
 *              pass information of the WP binary file will splitted in two   *
 *              parts:                                                        *
 *              1) A text file containing the whole text. The special WP      *
 *                 characters are translated.                                 *
 *              2) A binary file which contains information about             *
 *                 environments, tabbings, line endings                       *
 * licency:     GPL		                                              *
 ******************************************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#include "sets.h"
#include "stringa.h"
#include "lists.h"
#include "stacks.h"
#include "struct.h"

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


int set0_60[]={0 ___ 0xFF};		//Everything
int set1_60[]={0 ___ 0xBF,0xC0,0xD2,0xD4 ___ 0xFF}; //Header, Footer, Minipage Text
int set2_60[]={0x1 ___ 0x81,0xA9,0xC0,0xF0,0xF1};  //Characters Only
int set3_60[]={0xF1};  		//Nothing


extern uint8_t ObjWP6SizesF0[0x10]; /*(4,5,3,3,3,3,4,4,4,5,5,6,6,8,8,0);*/

unsigned char CharsWP6_1_32[0x21] = { //Default extended international characters (from 0)
0,  35, 34, 37, 36, 31, 30, 27, 33, 29,
77, 76, 39, 38, 45, 41, 40, 47, 43, 49,
57, 56, 81, 80, 83, 82, 63, 62, 71, 70,
67, 73, 23 };


typedef struct
	{
	uint8_t	Flags;
	uint8_t	PacketType;
	uint16_t	UseCount;
	uint16_t	HiddenCount;
	uint32_t	PacketSize;
	uint32_t	ResourceFilePos;
	} Resource;


class TconvertedPass1_WP6: public TconvertedPass1
     {
public:
     uint16_t ResourceStart;
     stack UndoRedo;

     virtual int Dispatch(int FuncNo, const void *arg);
     virtual int Convert_first_pass(void);

     void ProcessKey60(void);
#ifndef FINAL
     void CrackResources(void);
     void CrackResource(int ResourceNo);
#endif

protected:
     set filter[4];

     void BadResource(int ResourceNo);
     void Box6(void);
     void Comment6(int CommentLevel=1);
     void DecUserCounter(void);
     void DoCaption6(unsigned short CaptionSize);
     void Endnote6(uint32_t & NewPos);
     void ExtractCaptionLabel6(const TBox *Box);
     void Footnote6(uint32_t & NewPos);
     void FootnoteNumber6(uint32_t & NewPos);
     void Header_Footer6(void);
     void IncUserCounter(void);
     void InitFilter60(void);
     bool LoadResource(uint16_t ResourceNo, Resource & Res);
     void MakeIndex60(void);
     void MakeLabel6(void);
     void SetFontShape(void);
     void SetUserCounter(void);
     void TableStart6(uint32_t & NewPos);
     void TableOfContents6(void);
     void Undo(uint32_t & NewPos);
     void UserCounter(uint32_t & NewPos);
     };



/*Register translators here*/
TconvertedPass1 *Factory_WP6(void) {return new TconvertedPass1_WP6;}
FFormatTranslator FormatWP6("WP6.x",&Factory_WP6);



static const char *RefTypes[10] = {
  "Page", "Counter", "CapNum", "SecPage", "Chapter", "Volume", "Paragraph",
  "Footnote", "Endnote", "?"};



bool TconvertedPass1_WP6::LoadResource(uint16_t ResourceNo, Resource & Res)
{
#ifdef DEBUG
  fprintf(log,"\n#LoadResource(%u) ",(unsigned)ResourceNo);fflush(log);
#endif
 bool Corrupt=false;

 if(ResourceStart==0) return true; /* Resources are not available */
 fseek(wpd, (long)ResourceNo*14 + ResourceStart, SEEK_SET);

 Res.Flags = fgetc(wpd);
 Res.PacketType = fgetc(wpd);
 Rd_word(wpd, &Res.UseCount );
 Rd_word(wpd, &Res.HiddenCount );
 Rd_dword(wpd, &Res.PacketSize );
 Rd_dword(wpd, &Res.ResourceFilePos );

 if(feof(wpd))
 	{
        Res.ResourceFilePos=0;
	fseek(wpd, 0l, SEEK_SET);
	Corrupt=true;
	}

 if(ResourceNo==0) return true; // First packet is a header only

 if(Res.ResourceFilePos>DocumentStart) Corrupt=true; /* Fast check of resource data */
 if(Res.ResourceFilePos<=0x10) Corrupt=true;
 if(Res.ResourceFilePos+Res.PacketSize>DocumentStart) Corrupt=true;

 if(Corrupt)
     {
     if (err != NULL)
	{
	perc.Hide();
	fprintf(err, _("\nWarning: Resource #%d seems to be corrupted, its contents will be ignored!"),(int)ResourceNo);
	}
     return true;
     }
 return false;
}


#ifndef FINAL

/** Dump all resources into a log file. */
void TconvertedPass1_WP6::CrackResources(void)
{
uint16_t ResourceNo, Resources;
Resource Res;
long pos;

 if(log==NULL) return;
 pos = ftell(wpd);

 LoadResource(0,Res); // the 0th resource is the header
 Resources = Res.UseCount;
 ResourceNo = 1;
 fprintf(log, _("\nResource array, # of resources:%u\n"),(unsigned)(Resources));

 while(ResourceNo<Resources)
   {
   if(LoadResource(ResourceNo,Res)) fprintf(log, "!");
			       else fprintf(log, " ");

   fprintf(log, _("%2d: Start:%4lx, Len:%4lx, Type:%d, Flags:%d, Use:%d, Hidden:%d\n"),
	(int)ResourceNo, (long)Res.ResourceFilePos, (long)Res.PacketSize,
	(int)Res.PacketType, (int)Res.Flags, (int)Res.UseCount, (int)Res.HiddenCount );

   ResourceNo++;
   }

 fseek(wpd, pos, 0);
}


/** This procedure isn't normally called. It can be used for exploration of new packets. */
void TconvertedPass1_WP6::CrackResource(int ResourceNo)
{
  FILE *txt;
  long pos;
  uint32_t i;
  static char ss[13] = "00_RHack.txt";
  unsigned char c;
  Resource Res;

  c = LoadResource(ResourceNo,Res);

  pos = ftell(wpd);

  if (ss[1] > '9')
     {
     ss[1] = '0';
     ss[0]++;
     }

  txt = OpenWrChk(ss,"w",err);
  if(txt == NULL) return;

  fprintf(txt, "Resource #%d:\n Start:%4lXh, Length:%4lXh, Type:%Xh, Flags:%Xh, Use:%d, Hidden:%d \n"
	       "\nResource data:\n",
	(int)ResourceNo, (long)Res.ResourceFilePos, (long)Res.PacketSize,
	(int)Res.PacketType, (int)Res.Flags, (int)Res.UseCount, (int)Res.HiddenCount );

  if(!c) {
	 fseek(wpd, Res.ResourceFilePos, 0);

	 for (i=0; i<Res.PacketSize; i++)
		{
		c = fgetc(wpd);
		fprintf(txt," %4lu: %u",(long unsigned)i,(unsigned)c);
		if (c >= ' ' && c <= 'z')
			  fprintf(txt, " %c", c);
		putc('\n', txt);
		}
	 }

  fclose(txt);
  txt = NULL;
  ss[1]++;   /**/

  fseek(wpd, pos, 0);
}
#endif


/// Report that a resource is corrupted.
void TconvertedPass1_WP6::BadResource(int ResourceNo)
{
 if(err!=NULL)
   fprintf(err, _("\nWarning: Strange content of the resource #%d, it will be ignored!"),(int)ResourceNo);
}


void TconvertedPass1_WP6::DoCaption6(unsigned short CaptionSize)
{
#ifdef DEBUG
  fprintf(log,"\n#DoCaption6(%u) ",CaptionSize);fflush(log);
#endif
 uint32_t end_of_code;
 unsigned char OldFlag;
 char OldEnvir;
 attribute OldAttr;
 int CaptionChars;

  if(CaptionSize == 0) return;

  ActualPos = ftell(wpd);
  end_of_code = ActualPos + CaptionSize;
  OldFlag = flag;
  OldEnvir = envir;
  recursion++;

  OldAttr = attr;
  attr.InitAttr();

  flag = HeaderText;
  CaptionChars=0;

  fputs("\\caption{", strip);
  while(ActualPos < end_of_code)
  	{
	if(fread(&by, 1, 1, wpd) != 1) break;	// Error during read.

        if(by==0xD0)
          {
          flag = CharsOnly;
	  ProcessKey60();
	  flag = HeaderText;
          if(CaptionChars>0) 
              fputc(' ',strip);		// Fix softline or hardline.
	  continue;
          }

        if(CaptionChars==0)
          {           		// Rule out return before any character 
	  if((by==0xB9)||(by==0xCC)||(by==0xCF)) by=0x80; //WP6 space
          }
	if(by==0xCC) by=0xCF; // Replace [HRt] by [SRt]

        if(isalnum(by)) CaptionChars++;

	ProcessKey60();
	}
  Close_All_Attr(attr,strip);
  fprintf(strip, "}\n");

  line_term = 's';   /* Soft return */
  Make_tableentry_envir_extra_end(this);

  recursion--;
  flag = OldFlag;
  envir = OldEnvir;
  attr = OldAttr;
  char_on_line = false;
  nomore_valid_tabs = false;
  rownum++;
  Make_tableentry_attr(this);
  latex_tabpos = 0;
}


/** This function fixes user Counter name string to be readable from LaTeX. */
static void FixCounterName(string & counter)
{
  counter=replacesubstring(counter,"0","zero");
  counter=replacesubstring(counter,"1","one");
  counter=replacesubstring(counter,"2","two");
  counter=replacesubstring(counter,"3","three");
  counter=replacesubstring(counter,"4","four");
  counter=replacesubstring(counter,"5","five");
  counter=replacesubstring(counter,"6","six");
  counter=replacesubstring(counter,"7","sewen");
  counter=replacesubstring(counter,"8","eight");
  counter=replacesubstring(counter,"9","nine");

  counter=replacesubstring(counter,"\\","backslash");
  counter=replacesubstring(counter,"{","bracketon");
  counter=replacesubstring(counter,"}","bracketoff");
  counter=replacesubstring(counter,"%","percent");
  counter=replacesubstring(counter,",","comma");
  counter=replacesubstring(counter," ","space");
  counter=replacesubstring(counter,"?","question");
}


void TconvertedPass1_WP6::ExtractCaptionLabel6(const TBox *Box)
{
#ifdef DEBUG
  fprintf(log,"\n#ExtractCaptionLabel6() ");fflush(log);
#endif
uint32_t end_of_code;
unsigned char OldFlag;
//bool FoundLabel=false;

  if(Box==NULL) return;
  if(Box->CaptionSize == 0) return;

  fseek(wpd, Box->CaptionPos, SEEK_SET);
  ActualPos = Box->CaptionPos;
  end_of_code = ActualPos + Box->CaptionSize;
  OldFlag = flag;
  recursion++;

  flag = Nothing;
  attr.InitAttr();

  while (ActualPos < end_of_code)
	{
	if(fread(&by, 1, 1, wpd) !=1 ) break; /*Error during read*/

	if(by==0xD4)
		{
		if(fread(&subby, 1, 1, wpd)!=1) break;
		fseek(wpd,-1,SEEK_CUR);
		if(subby==8)	//convert \label{} only
			{
			flag = HeaderText;
			ProcessKey60();
			NewLine(this);
//			FoundLabel=true;
			break;
			}
		}
	ProcessKey60();
	}

  recursion--;
  flag = OldFlag;
}


static void SkipNumber6(TconvertedPass1 *cq, uint32_t & NewPos)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#SkipNumber6() ");fflush(cq->log);
#endif
int i;
unsigned char by;
unsigned char OldFlag;

  OldFlag = cq->flag;
  cq->flag = Nothing;
  fseek(cq->wpd, NewPos, 0);

  i=0;
  while(i<20)		// Read the page number text
	{
	fread(&by, 1, 1, cq->wpd);
	if(!isalnum(by)) break;
        // ProcessKey60(cq);
	i++;
	}

  if(by==0xDA && i<20)	// Skip the page number text after object
	{
	NewPos+=i;
	}

  cq->flag = OldFlag;
}

//---------WP6.x feature conversion procedures----------

static void BackTab(TconvertedPass1 *cq)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#BackTab() ");fflush(cq->log);
#endif
int wpu;

if(!TABs || Columns>=2)
       {
NoTab: putc(' ', cq->strip);
       strcpy(cq->ObjType, "!Back Tab");
       return;
       }

wpu = cq->tabpos[0] - cq->WP_sidemargin;  /* Correctie ivm WP kantlijn */
wpu = abs(wpu);

if(cq->envir == 'B') goto NoTab;
if(cq->envir == 'T')
	{
	fprintf(cq->strip, "\\< ");
	}
else	{
	fprintf(cq->strip, "\\kern-%2.2fcm ", wpu/470.0);
	}

strcpy(cq->ObjType, "Back Tab");
}


/** This procedure converts Boxes (char, paragraph or page anchored) from WP6. x*/
void TconvertedPass1_WP6::Box6(void)
{
#ifdef DEBUG
  fprintf(log,"\n#Box6() ");fflush(log);
#endif
 uint8_t PIDs;
 uint16_t PPIDs,TextBlocks,SizeOfArea;
 uint16_t ResourceNo,DataResNo,CaptionResNo,IDFlags;
 Resource Res;
 int16_t NameLen;
 TBox Box;
 uint32_t OleSize=0,OlePos;
 char OldEnvir;
 unsigned char OldFlag;
 attribute OldAttr;
 string StrBeg, StrEnd, ImageName;
 uint32_t end_of_code,pos,subpos;
 uint32_t BlockOffset, BlockSize;
 uint16_t Wchar;
 int i;
 const char *BoxDescription;
 uint16_t wpu;

  //fseek(wpd, -2L, SEEK_CUR); Rd_word(wpd, &SizeOfArea);
  //CrackObject(this, ActualPos+SizeOfArea);

 BoxDescription="!Box";
  fseek(wpd, 1L, SEEK_CUR);
  if((PIDs = fgetc(wpd)) == 0)
    {				//Box has no resource available
	if(err!=NULL)
       fprintf(err, _("\nWarning: Box contains unexpected amount of resources %d!"),(int)PIDs);
	goto BadResource;
    }

  initBox(Box);
  switch(subby)
	{
	case 0:Box.AnchorType=BOX_ANCHOR_CHAR; break;	//character
	case 1:Box.AnchorType=BOX_ANCHOR_PAR; break;	//paragraph
	case 2:Box.AnchorType=BOX_ANCHOR_PAGE; break;	//page
	default:Box.AnchorType=BOX_ANCHOR_PAR;		//not detected
	}

  DataResNo = CaptionResNo = 0;
  pos = ftell(wpd);
  while(PIDs>0)
	{
	fseek(wpd, pos, SEEK_SET);
	pos += 2;
	Rd_word(wpd, &ResourceNo);

	PIDs--;

	if(ResourceNo==0)
	   {
	   if(err != NULL)
		{
		perc.Hide();
		fprintf(err, _("\nWarning: Resource #0 should not be referred from data!"));
		}
	   continue;
	   }
	if(LoadResource(ResourceNo, Res)) goto BadResource;
        
        //CrackResource(ResourceNo);
	switch(Res.PacketType)
		{
		case 0x08:if(DataResNo==0) DataResNo=ResourceNo; //BoxCaption
				      else CaptionResNo=ResourceNo;
			  if(Box.Contents==0)	//no box contents defined
				{
				if(Box.Type==4) Box.Contents=4;
                                           else Box.Contents=1;
				}
			  break;

                case 0x40:                      //Graphics FileName                          
                          fseek(wpd, Res.ResourceFilePos, SEEK_SET);
                          BlockOffset = Res.ResourceFilePos+Res.PacketSize;	// Store the resource end.
			  if((Res.Flags & 1) != 0)  //are there childrens?
			    {
			    Rd_word(wpd, &PPIDs);
			    subpos = Res.ResourceFilePos + 2;

			    for(i=0; i<PPIDs; i++)
				{
				Rd_word(wpd, &ResourceNo);
				subpos += 2;
				if(!LoadResource(ResourceNo, Res))
				   {
				   if(Res.PacketType==0x6F) //WPG graphics
					{
					Box.Image_type=2;
					Box.Image_offset=Res.ResourceFilePos;
					Box.Image_size=Res.PacketSize;
					}
                                   if(Res.PacketType==0x70) //OLE archive
				     {
				     if(Box.Type==5)
					{
					OleSize=Res.PacketSize;
					OlePos=Res.ResourceFilePos;
					}
				     }
				   }
				fseek(wpd, subpos, SEEK_SET);
				}
			    fseek(wpd, PPIDs * 2l, SEEK_CUR);	// Skip tag flags.
                            }
                          
                          subpos = ftell(wpd);
			  while(!feof(wpd) && subpos<BlockOffset)	// <Res.ResourceFilePos+Res.PacketSize ... res could be overwritten.
                              {                              
                              Rd_word(wpd, &PPIDs);                             
                              if(PPIDs==0 || PPIDs==0xFFFF) break;
                           			      
                               if(PPIDs<0xEFF)		//?? Nonsense characters inside filename ??
                                 {
				 switch(PPIDs)
				   {
                                   case 1:
				   case 0xA:
                                   case 26: break;	// Skip bullshit is the image name.
				   //case 0xFF: break;

				   case '\\':
				   case '$':
				   case '_':
                                   case '-':
					ImageName += (char)PPIDs;
					break;
                                   default:
			             {
				     const char *Ch = Ext_chr_str(PPIDs, this, ConvertCpg);
				     while(*Ch)
                                       {
				       if(*Ch==' ' && Ch[1]==0) break;

				       switch(*Ch)
				         {
					 case '{': if(Ch[1]=='}')
							{Ch++; break;}   //ignore
						   ImageName+="_opb";
						   break;
					 case '}': ImageName+="_clb";
						   break;
					 case '~': ImageName+="_tld";
					 case '\\': break;

					 default: ImageName+=*Ch;
					 }
				       Ch++;
				       }
                                     }
				   }
				 }
                               subpos += 2;
			       }

			  if(DataResNo==0) DataResNo=ResourceNo;
                                      else CaptionResNo=DataResNo;
			  Box.Contents=3;
			  break;

		case 0x41:			//Box template
			  fseek(wpd, Res.ResourceFilePos, SEEK_SET);
			  Rd_word(wpd, &PPIDs);       //Number of prefix packet IDs
			  fseek(wpd, 2L*PPIDs         //skip nested resource indices
				         +2, SEEK_CUR);   //Skip size of box name/library data

			  Rd_word(wpd, &SizeOfArea);  //Read size of box name/library data area
			  BlockOffset = 2L * PPIDs + 2 + 2 + 2 + SizeOfArea;
			  fseek(wpd, 2L, SEEK_CUR);
			  Rd_word(wpd, (uint16_t *)&NameLen); //box namelength
			  switch(NameLen)
				{
				case  0:Box.Type=0;BoxDescription="Fig Box"; break;  //figure box
				case -1:Box.Type=1;BoxDescription="Table Box"; break;//table box
				case -2:Box.Type=3;BoxDescription="Text Box"; break; //text box
				case -3:Box.Type=2;BoxDescription="User Box"; break; //user box
				case -4:Box.Type=4;BoxDescription="Equ Box"; break;  //equation box
				case -5:Box.Type=2;BoxDescription="Button"; break;   //button box as user box

				case -7:Box.Type=5;BoxDescription="OLE Equ Box"; break;//new shape equation box
				default: if(NameLen>0) 
					    {
                                            BoxDescription="User Named";
                                            Box.Type = 100;	//Unknown user named box.
                                            }
				}

			  fseek(wpd, Res.ResourceFilePos+BlockOffset, SEEK_SET);
			  Rd_word(wpd, &SizeOfArea);  //Read size of box counter data
			  BlockOffset += 2 + SizeOfArea;
					  //skip Box counter Area

			  fseek(wpd, Res.ResourceFilePos+BlockOffset, SEEK_SET);
			  Rd_word(wpd, &SizeOfArea);  //Read size of box positioning data
			  BlockOffset += 2 + SizeOfArea;

			  fseek(wpd, 1L, SEEK_CUR);		// skip position prefix ID

                          fseek(wpd, 1L, SEEK_CUR);		// skip anchor type
			  /*fread(&Box.AnchorType, 1, 1, wpd);  // I have no clue what is a purpose of this secondary anchor type.
			  Box.AnchorType &= 0x3;   // 0-Paragraph, 1-Page, 2-Character
			  switch(Box.AnchorType)
				{
				case 0:Box.AnchorType=1;break;	//paragraph
				case 1:Box.AnchorType=0;break;  //page
				case 2:break;			//character
				} */

			  fread(&Box.HorizontalPos, 1, 1, wpd);		// <hpos flags>
			  Box.HorizontalPos = (Box.HorizontalPos>>2)& 3;	// 0-Left, 1-Right, 2-Center, 3-Full

				// [hoffset] <left col> <right col>
                                // <vpos flags> [voffset] <width flags>
			  fseek(wpd, 8L, SEEK_CUR);
			  Rd_word(wpd, &wpu); Box.Width=wpu/47.0;	// width [mm]
				
				// Box content
			  fseek(wpd, Res.ResourceFilePos+BlockOffset, SEEK_SET);
			  Rd_word(wpd, &SizeOfArea);  //Read size of box contents data
			  BlockOffset += 2 + SizeOfArea;
			  if(SizeOfArea<5) break;
			  uint8_t BoxContentType;
			  fseek(wpd, 1L, SEEK_CUR);
			  BoxContentType=fgetc(wpd);
			  fseek(wpd, 1L, SEEK_CUR);
			  Rd_word(wpd, &SizeOfArea);  //Total size of content rendering data
			  if(SizeOfArea>0)
			    {
			    switch(BoxContentType)  //This is not finished yet.
				{
				case 3:break;	//image content rendering flags
				}
			    }

			  break;
		case 0x64:Box.Contents = 4;	//Box Equation Content
			  break;                
		}

	}


  pos+=20;			  //Process override build in data
  fseek(wpd, pos, SEEK_SET);
  Rd_word(wpd, &PPIDs);		//BoxOverrideFlags
  pos+=2;

  if(PPIDs & 0x8000)			//box counter data
	{
	Rd_word(wpd, &SizeOfArea);  //Read size of box counter data
	pos += SizeOfArea+2;
	fseek(wpd, pos, SEEK_SET);
	}

  if(PPIDs & 0x4000)			//box positioning data
	{
	Rd_word(wpd, &SizeOfArea);  //Read size of box positioning data
        uint16_t OwFlags;
        Rd_word(wpd, &OwFlags);	// Override flags 2B

        if(OwFlags & 0x8000) fseek(wpd, 2L, SEEK_CUR); // Position Preffix ID Flags - mask 1B, data 1B
        if(OwFlags & 0x4000) fseek(wpd, 2L, SEEK_CUR); // General Position Flags 1D - mask 1B, data 1B
        if(OwFlags & 0x2000) fseek(wpd, 5L, SEEK_CUR); // Horizontal Position Flags 1B // Horizontal Offset 2B // LeftColumn 1B // RightColumn 1B
        if(OwFlags & 0x1000) fseek(wpd, 3L, SEEK_CUR); // Vertical Position Flags 1B // Vertical Offset 2B
        if(OwFlags & 0x0800)
          {
          fseek(wpd, 1L, SEEK_CUR);		// Width Flags 1B
          Rd_word(wpd, &wpu);			// Width 2B
          if(wpu!=0)		// Use a new value only when not set from packet #42
              Box.Width = wpu/47.0;
          }
          //if(OwFlags & 0x0400)
		// Height flags 1B
		// Height 2B

	pos += SizeOfArea+2;
	fseek(wpd, pos, SEEK_SET);
	}

  if(PPIDs & 0x2000)			//Box content data
	{
	uint8_t ContentType=0;
	Rd_word(wpd, &SizeOfArea);  //Read size of box positioning data
	Rd_word(wpd, &IDFlags);
	BlockOffset=4;

	if(IDFlags & 0x8000) BlockOffset+=2; // <mask><data>
	if(IDFlags & 0x4000)		     // Content type override.
		{
		BlockOffset+=1;
		ContentType=fgetc(wpd);      // <contentType>
		}
	if(IDFlags & 0x2000)		// Content rendering information
	       {
	       uint16_t TotSize;
	       fseek(wpd, pos+BlockOffset, SEEK_SET);
	       Rd_word(wpd, &TotSize);  //Total size of image content override data
	       if(ContentType==3)	//content of box is image
		   {
		   uint16_t ContentsOverrideFlags;
		   Rd_word(wpd, &ContentsOverrideFlags);
		   if(ContentsOverrideFlags & 0x8000)  // bit 15 Prefix Id flags override
			   fseek(wpd, 2L, SEEK_CUR);   // <mask><data>
		   if(ContentsOverrideFlags & 0x4000)  // bit 14 Image native size override
			   fseek(wpd, 4L, SEEK_CUR);   // [NativeWidth][NativeHeight]
		   if(ContentsOverrideFlags & 0x2000)  //bit 13 - image content render override
			   {
			   uint8_t b;
			   fseek(wpd, 1L, SEEK_CUR);	//skip mask
			   b = fgetc(wpd);		// data
			   if(b & 0x80) Box.HScale=-Box.HScale;
			   if(b & 0x40) Box.VScale=-Box.VScale;
			   }
		   if(ContentsOverrideFlags & 0x1000)  //bit 12 - scalling factor
			   fseek(wpd, 8L, SEEK_CUR);
		   if(ContentsOverrideFlags & 0x0800)  //bit 11 - translation factor
			   fseek(wpd, 8L, SEEK_CUR);
		   if(ContentsOverrideFlags & 0x0400)  //bit 10 - rotation
			   {
			   fseek(wpd, 2L, SEEK_CUR);	//skip lo WORD from DWORD
			   Rd_word(wpd, &Box.RotAngle);
			   }
		   // bit 9 Black and white threshold override.
		   // bit 8 Lightness value override
                   // bit 7 Contrast value override
		   // bit 6 Halftone data override
		   // bit 5 Image dither flags override
		   }
	       BlockOffset += TotSize+2;
	       }

	if(IDFlags & 0x1000)	// Content alignment information
	       BlockOffset += 2;  // <mask><data>

	if(IDFlags & 0x0800) // ????? This should not occur
		{
		fseek(wpd, BlockOffset, SEEK_CUR); //1+???
		Rd_word(wpd, &wpu);Box.Width=wpu/47.0;
		}

	pos += SizeOfArea+2;
	fseek(wpd, pos, SEEK_SET);
	}

  if(PPIDs & 0x1000)			//bit 12 - Box caption data
       {
       uint16_t TotCapSize;
       Rd_word(wpd, &TotCapSize);

       pos += TotCapSize+2;
       fseek(wpd, pos, SEEK_SET);
       }

  if(PPIDs & 0x800)			//bit 11 - Box border data
       {
       uint16_t TotBorderSize;
       Rd_word(wpd, &TotBorderSize);

       pos += TotBorderSize+2;
       fseek(wpd, pos, SEEK_SET);
       }

  AttrOff(this,14);  		// ulem
  AttrOff(this,11);		// uulem
  for(i=First_com_section;i<=Last_com_section;i++)
      AttrOff(this,i);		// Any of section's attr cannot be opened.

  OldEnvir = envir;
  OldFlag = flag;
  OldAttr = attr;

  if(Box.Contents==1 && DataResNo>0)	//text
	{
        if(Box.Type==100) Box.Type=3;
	if(LoadResource(DataResNo, Res)) goto BadResource;
	if(Res.PacketType!=8) {BadResource(ResourceNo);goto BadResource;}

	fseek(wpd, Res.ResourceFilePos, SEEK_SET);
	Rd_word(wpd, &TextBlocks);	// Load # of text blocks
	if(TextBlocks<1) {BadResource(ResourceNo);goto BadResource;}

	Rd_dword(wpd, &BlockOffset);
	Rd_dword(wpd, &BlockSize);
	if(BlockOffset + BlockSize > Res.PacketSize) {BadResource(ResourceNo);goto BadResource;}

	fseek(wpd, Res.ResourceFilePos+BlockOffset, SEEK_SET);
	end_of_code = Res.ResourceFilePos+BlockOffset+BlockSize;


	if(char_on_line == LEAVE_ONE_EMPTY_LINE)  // Left one enpty line for new enviroment.
	       {
	       fputc('%', table);
	       fputc('%', strip);
	       NewLine(this);
	       char_on_line = true;
	       }
	if(char_on_line==CHAR_PRESENT)     /* make new line for leader of minipage */
	       {
	       NewLine(this);
	       }

	if(!BoxTexHeader(this,Box)) CaptionResNo=0; //caption is disabled
	envir='!';			//Ignore enviroments Before
	NewLine(this);

	char_on_line = FIRST_CHAR_MINIPAGE;
	envir = ' ';
	ActualPos = ftell(wpd);
	recursion++;
	while (ActualPos < end_of_code)
		 {
		 fread(&by, 1, 1, wpd);

		 ProcessKey60();
		 }
	recursion--;

	Close_All_Attr(attr,strip);

	envir=' ';
	if (char_on_line==CHAR_PRESENT)
	     {
	     NewLine(this);
	     }
	if(CaptionResNo>0) //process caption
		{
		if(LoadResource(CaptionResNo, Res)) goto NoCaption;
		if(Res.PacketType!=8) {BadResource(CaptionResNo);goto NoCaption;}

		fseek(wpd, Res.ResourceFilePos, SEEK_SET);
		Rd_word(wpd, &TextBlocks);	// Load # of text blocks
		if(TextBlocks<1) {BadResource(CaptionResNo);goto NoCaption;}

		Rd_dword(wpd, &BlockOffset);
		Rd_dword(wpd, &BlockSize);
		if(BlockOffset + BlockSize > Res.PacketSize) {BadResource(CaptionResNo);goto NoCaption;}

		Box.CaptionPos=Res.ResourceFilePos+BlockOffset;
		fseek(wpd, Box.CaptionPos, SEEK_SET);
		DoCaption6(BlockSize);
		}
NoCaption:
	BoxTexFoot(this, Box);

	envir='^';		//Ignore enviroments after minipage
	NewLine(this);
	}


  if(Box.Contents==3 && Box.Type==5 && DataResNo>0 && OleSize>0) //new WP12 OLE equation
    {
    string temp_filename;
    TconvertedPass1 *cq1_new;
    FILE *SrcOLE;

    temp_filename = OutputDir+GetSomeImgName(".OLE");
    if( (SrcOLE=OpenWrChk(temp_filename(),"wb",err)) != NULL )
	{
	fseek(wpd,OlePos,SEEK_SET);

	i=44+4+2+2+2+2+4+4;
	fseek(wpd,i,SEEK_CUR);
	OleSize-=i;

		//OLE stream is starting here
	fseek(wpd,39,SEEK_CUR); //Why 39??? Don't know.
	OleSize-=39;

        i=fgetc(wpd);
        if(i!=0xD0)
          {
          if(err != NULL)
	    {
	    perc.Hide();
	    fprintf(err, _("\nWarning: Incorrect guess of OLE offset. Please send me this file for analysis."));
	    }
          }
	fputc(i,SrcOLE); OleSize--;

	while (OleSize-->0)
	  fputc(fgetc(wpd), SrcOLE); /*Copy all OLE contents*/
	fclose(SrcOLE);

	SrcOLE = fopen(temp_filename(),"rb");
        if(SrcOLE)
          {
	  CheckFileFormat(SrcOLE,FilForD);
	  cq1_new = GetConverter(FilForD.Converter);
          if(cq1_new!=NULL)
	    {
	    //cq.perc.Hide();
	    if(Verbosing >= 1) printf(_("[nested \"%s\" %s] "), temp_filename(),FilForD.Converter);
	    cq1_new->InitMe(SrcOLE,table,strip,log,err);
	    cq1_new->Convert_first_pass(); //>=1) RetVal=1;
	    if(Verbosing >= 1) printf(_("\n[continuing] "));
	    if(log!=NULL) fputs(_("\n--End or nested file.--\n"),log);
	    //cq.perc.Show();
	    delete cq1_new;
	    }
	  fclose(SrcOLE);
          }	
	}
    }

  if(Box.Contents==3)           	//graphics
	{
        if(Box.Type==100) Box.Type=0;
	Box.CaptionSize=0;
	if(CaptionResNo>0) //process caption
		{
		if(LoadResource(CaptionResNo, Res)) goto NoCaptionG;
		if(Res.PacketType!=8) goto NoCaptionG;

		fseek(wpd, Res.ResourceFilePos, SEEK_SET);
		Rd_word(wpd, &TextBlocks);	// Load # of text blocks
		if(TextBlocks<1) goto NoCaptionG;

		Rd_dword(wpd, &BlockOffset);
		Rd_dword(wpd, &BlockSize);
		if(BlockOffset + BlockSize > Res.PacketSize) goto NoCaptionG;

		Box.CaptionPos = Res.ResourceFilePos+BlockOffset;
		Box.CaptionSize = BlockSize;
		}
NoCaptionG:
        recursion++;
	ImageWP(this,ImageName,Box);
	recursion--;
	}

  if(Box.Contents==4 && DataResNo>0)	//equation
	{
        if(Box.Type==100) Box.Type=4;
	FormulaNo++;
	Box.CaptionSize=0;
	if(CaptionResNo>0) //process caption
		{
		if(LoadResource(CaptionResNo, Res)) goto NoCaptionEq;
		if(Res.PacketType!=8) goto NoCaptionEq;

		fseek(wpd, Res.ResourceFilePos, SEEK_SET);
		Rd_word(wpd, &TextBlocks);	// Load # of text blocks
		if(TextBlocks<1) goto NoCaptionEq;

		Rd_dword(wpd, &BlockOffset);
		Rd_dword(wpd, &BlockSize);
		if(BlockOffset + BlockSize > Res.PacketSize) goto NoCaptionEq;

		Box.CaptionPos = Res.ResourceFilePos+BlockOffset;
		Box.CaptionSize = BlockSize;
		}
NoCaptionEq:
	if(LoadResource(DataResNo, Res)) goto BadResource;
	if(Res.PacketType!=8) {BadResource(ResourceNo);goto BadResource;}

	fseek(wpd, Res.ResourceFilePos, SEEK_SET);
	Rd_word(wpd, &TextBlocks);	// Load # of text blocks
	if(TextBlocks<1) {BadResource(ResourceNo);goto BadResource;}

	Rd_dword(wpd, &BlockOffset);
	Rd_dword(wpd, &BlockSize);
	if(BlockOffset + BlockSize > Res.PacketSize) {BadResource(ResourceNo);goto BadResource;}

	fseek(wpd, Res.ResourceFilePos+BlockOffset, SEEK_SET);

	end_of_code = Res.ResourceFilePos+BlockOffset+BlockSize;
	StrBeg.erase();
	StrEnd.erase();

	flag = Nothing;
	attr.InitAttr();
	recursion++;

	ActualPos = ftell(wpd);
	while(ActualPos < end_of_code)
	     {
	     fread(&by, 1, 1, wpd);
	     if(by<=0) break;
	     if(by>=0x01 && by<=0x20)
		      {
		      StrEnd = Ext_chr_str(0x100|CharsWP6_1_32[by],this,ConvertCpg);
		      StrBeg += FixFormulaStrFromTeX(StrEnd);  //unwanted accents must be fixed here.
		      }
	     if(by == '$')
		      {
		      StrBeg += "\\$ ";
		      ActualPos++;
		      continue;
		      }
	     if(by == '%')
		      {
		      StrBeg += "\\% ";
		      ActualPos++;
		      continue;
		      }
	     if(by == '\\')
		      {
		      StrBeg += (char)1;
		      ActualPos++;
		      continue;
		      }
	     if(by>' ' && by<0x80)
		      {
		      StrBeg += (char)by;
		      ActualPos++;
		      continue;
		      }
	     if(by==0xCC || by==0xCF || by==0xD0)   //New line
		      {
		      StrBeg += ' ';
		      }
	     if(by==0x80) StrBeg += ' ';
	     if(by==0x81) StrBeg += '~';
	     if(by==0x82 || by==0x83 || by==0x85)
			      StrBeg += "\\-";
	     if(by==0x84) StrBeg += '-';
	     if(by==0x86) StrBeg += "{\\penalty0}";
	     if(by==0x87) StrBeg += ' '; 	//!!! Terminate Line

	     if(by == 0xF0)       /*extended character*/
		  {			/*why special wp characters are in equations?*/
		  Rd_word(wpd, &Wchar);
		  StrEnd = Ext_chr_str(Wchar, this, ConvertCpg);
		  StrBeg += FixFormulaStrFromTeX(StrEnd,Wchar>>8);
		  StrEnd.erase();
		  }

	     ProcessKey60();
	     }
	recursion--;

	i = OptimizeFormulaStr(this,StrBeg);
	if(StrBeg.isEmpty()) goto LEqEmpty;
	if(i!=0 && Box.AnchorType==2) StrBeg+='\n';

	while(attr.Opened_Depth>0)  //discard temporarily created attributes
		{
		_AttrOff(attr, attr.stack[attr.Opened_Depth],StrEnd);
		StrBeg+=StrEnd;
		}

	attr = OldAttr;	//Return saved attributes before placing a formula

	if(char_on_line == LEAVE_ONE_EMPTY_LINE) // Left one enpty line for new enviroment.
	  {
	  fputc('%', table);
	  fputc('%', strip);
	  NewLine(this);
	  char_on_line = CHAR_PRESENT;
	  }
	if(char_on_line==CHAR_PRESENT)     /* make new line for leader of minipage */
	  {
	  NewLine(this);
	  }


	PutFormula(this,StrBeg(),Box);

        if(StrBeg.length()>0)
        {
          if(OldEnvir=='B' && char_on_line==false) 
	      char_on_line = -1;		// This will force newline in tabbing environment.

          if(BoxDescription==NULL || *BoxDescription=='!')
              BoxDescription = "Box:Formula";
        }
      /*     if(CaptionLen>0) then   // captions are currently loosed
		begin
		seek(cq.wpd^,CaptionPos);
		DoCaption(cq,CaptionLen);
		end;*/

	goto AttrsRestored;
	}

LEqEmpty:
  attr = OldAttr;
AttrsRestored:
  if(envir=='^') char_on_line = FIRST_CHAR_MINIPAGE;	// stronger false;
  flag = OldFlag;
  envir = OldEnvir;

BadResource:
  strcpy(ObjType, BoxDescription);
}


static void Column6(TconvertedPass1 *cq)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#Column6() ");fflush(cq->log);
#endif
uint8_t ColType, NoColumns;

if(Columns<0)
	{
	strcpy(cq->ObjType, "!Col");
	return;
	}

fseek(cq->wpd, 3L, SEEK_CUR);	//skip <flags>,[non del size]
ColType=getc(cq->wpd);
fseek(cq->wpd, 4L, SEEK_CUR);	//skip {spacing}
NoColumns=getc(cq->wpd);

Column(cq,NoColumns);

sprintf(cq->ObjType, "Col Def:%d",(int)NoColumns);
}


void TconvertedPass1_WP6::Comment6(int CommentLevel)
{
#ifdef DEBUG
  fprintf(log,"\n#Comment6() ");fflush(log);
#endif
  unsigned char OldFlag;
  signed char OldCharOnLine;
  attribute OldAttr;
  uint32_t end_of_code,SavedPos;
  uint16_t ResourceNo;
  Resource Res;

  OldFlag = flag;
  OldAttr = attr;
  OldCharOnLine = char_on_line;

//CrackObject(cq, NewPos);

  fseek(wpd, 2L, SEEK_CUR);
  Rd_word(wpd, &ResourceNo);


  if(LoadResource(ResourceNo, Res)) goto BadResource;
  fseek(wpd, Res.ResourceFilePos, SEEK_SET);
  fread(&by, 1, 1, wpd);
  if(by!=1) {BadResource(ResourceNo);goto BadResource;}
  fseek(wpd, 1L, SEEK_CUR);
  Rd_word(wpd, &ResourceNo);	// Load 2nd indexed resource


  if(LoadResource(ResourceNo, Res)) goto BadResource;
  fseek(wpd, Res.ResourceFilePos, SEEK_SET);
  fread(&by, 1, 1, wpd);
  if(by!=1) {BadResource(ResourceNo);goto BadResource;}
  fseek(wpd, 9, SEEK_CUR);


  flag = CharsOnly;
  recursion++;
  attr.InitAttr();		//Turn all attributes in the comment off
  end_of_code = Res.ResourceFilePos+Res.PacketSize;

  fprintf(strip,"%.*s",CommentLevel,"%%%%%%%%%%");
  ActualPos = ftell(wpd);
  while (ActualPos < end_of_code)
	{
	SavedPos=ActualPos;
	fread(&by, 1, 1, wpd);
	if(by<=0x01) break;
	ProcessKey60();


	if(by==0xD4 && subby==0x1D)   //Nested Comments
		{
		fseek(wpd,SavedPos+4,SEEK_SET);
		SavedPos=ActualPos;

		Comment6(CommentLevel+1);
		fprintf(strip,"%.*s",CommentLevel,"%%%%%%%%%%");

		ActualPos=SavedPos;
		fseek(wpd,SavedPos,SEEK_SET);
		continue;
		}

	if(by==0xCC || by==0xCF || by==0xD0)   //New comment line
       		{
                line_term = 's';    	//Soft return
		Make_tableentry_envir_extra_end(this);
		fprintf(strip, "\n");
		rownum++;
		Make_tableentry_attr(this);

		fprintf(strip,"%.*s",CommentLevel,"%%%%%%%%%%");
		}
       }

  line_term = 's';    	//Soft return
  Make_tableentry_envir_extra_end(this);
  fprintf(strip, "\n");
  rownum++;
  Make_tableentry_attr(this);

  recursion--;
  attr = OldAttr;
  flag = OldFlag;
  if(OldCharOnLine==CHAR_PRESENT || OldCharOnLine==JUNK_CHARS) char_on_line = JUNK_CHARS;
	else char_on_line = NO_CHAR;
BadResource:
  strcpy(ObjType, "Comment");
}


void TconvertedPass1_WP6::Endnote6(uint32_t & NewPos)
{
#ifdef DEBUG
  fprintf(log,"\n#Endnote6() ");fflush(log);
#endif
  unsigned char OldFlag;
  char BkEnvir;
  attribute OldAttr;
  uint32_t end_of_code,BlockOffset,BlockSize;
  uint16_t ResourceNo,TextBlocks;
  Resource Res;
  int ignored;
  bool FirstLine;

  OldFlag = flag;

//CrackObject(cq, NewPos);

  fseek(wpd, 2L, SEEK_CUR);
  Rd_word(wpd, &ResourceNo);


  if(LoadResource(ResourceNo, Res)) goto BadResource;
  if(Res.PacketType!=8) {BadResource(ResourceNo);goto BadResource;}

  fseek(wpd, Res.ResourceFilePos, SEEK_SET);
  Rd_word(wpd, &TextBlocks);	// Load # of text blocks
  if(TextBlocks<1) {BadResource(ResourceNo);goto BadResource;}

  Rd_dword(wpd, &BlockOffset);
  Rd_dword(wpd, &BlockSize);

  fseek(wpd, Res.ResourceFilePos+BlockOffset, SEEK_SET);

  end_of_code = Res.ResourceFilePos+BlockOffset+BlockSize;
  if(BlockOffset + BlockSize > Res.PacketSize)
		end_of_code = Res.ResourceFilePos+Res.PacketSize; //resource seems to be bad - try anyway


  flag = CharsOnly;
  recursion++;

  Close_All_Attr(attr,strip);
  OldAttr = attr;
  attr.InitAttr();		//Turn all attributes in the endnote off

  BkEnvir = envir;
  if(BkEnvir=='L' || BkEnvir=='B') // || BkEnvir=='i')
  {
    envir = '!';  		//Ignore enviroments Before
    NewLine(this);
    envir = ' ';
  }

  FirstLine = true;

  if(!EndNotes) EndNotes=true;		/* set up endnotes */
  if(EndNotes==-1) EndNotes=-2;
  fprintf(strip, "\\endnote{");

  ActualPos = ftell(wpd);
  while(ActualPos < end_of_code)
	{
	fread(&by, 1, 1, wpd);

	switch(by)
	     {
	     case 0xC7:
	     case 0xCC:fprintf(strip, " \\\\ ");
		       ActualPos++;
		       break;
	     case 0xCF:putc(' ', strip);
		       ActualPos++;
		       break;
	     case 0xD0:flag = CharsOnly;
		       ProcessKey60();
		       flag = HeaderText;
		       switch (subby)
			  {
			  case 4:                               //HRt
			  case 6:			        //Spg-HRt
			  case 9:fprintf(strip, " \\\\ ");  //Hpg
				 break;
			  case 1:                               //SRt
			  case 3:putc(' ', strip);          //SRt-Spg
				 break;
			  }
		       break;
	     case 0xDD:ProcessKey60();
		       switch (subby)
			  {
			  case 0xA:flag = Nothing;    break; //Global On
			  case 0xB:flag = HeaderText; break; //Global Off
			  }
		       break;

             case 0xE0:fread(&subby, 1, 1, wpd);
		      fseek(wpd,-1,SEEK_CUR);
                      if(subby==0x11 && FirstLine)
		      {
                        NewLine(this);
		        FirstLine = false;
		      }
		      ProcessKey60();
                      break;

	     default: ProcessKey60();
		      break;
	     }
	}

  Close_All_Attr(attr,strip);   /* Echt nodig ? */

  if(envir != ' ') NewLine(this);

  putc('}', strip);

  if(envir != ' ')	// Finish all environments started in endnote.
    {
    envir = ' ';
    NewLine(this);
    }

  if(BkEnvir=='L' || BkEnvir=='B') // || BkEnvir=='i')
    {
    envir = '^';		//Ignore enviroments Before
    NewLine(this);
    char_on_line = -1;
    }
  envir = BkEnvir;

  recursion--;

	// Cut Useless Bookmarks and endnote index from main document
  ignored = 0;
  flag = Nothing;

  fseek(wpd, NewPos, SEEK_SET);
  ActualPos=NewPos;

  while(!feof(wpd) && ignored<20)
	{
	fread(&by, 1, 1, wpd);

	if(by==0xD7)
		{
		NewPos=ActualPos;
		break;			//Everything is OK, useless section successfully ignored.
		}

	ProcessKey60();
	ignored++;
	}

  if(ignored>=20)
     if (err != NULL)
	{
	perc.Hide();
	fprintf(err, _("\nWarning: Cannot remove strange Endnote index!"));
	}

  attr = OldAttr;
  flag = OldFlag;
BadResource:
  strcpy(ObjType, "Endnote");
}


static void Filename(TconvertedPass1 *cq, uint32_t & NewPos)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#Filename() ");fflush(cq->log);
#endif
int i;
unsigned char by;

  fprintf(cq->strip, "\\jobname.tex"); /*the full filename is not distinguished now*/
  fseek(cq->wpd, NewPos, SEEK_SET);

  i=0;                  // maximal allowed filename length is 80 characters
  while(i<80)		// Read the page number text
	{
	fread(&by, 1, 1, cq->wpd);
	if(by==0) break;
	if(by>0x80) break;
	i++;
	}

  if(by==0xD4 && i<80)	// Skip the page number text after object
	{
	NewPos+=i;
	}

  strcpy(cq->ObjType, "Filename");
  cq->char_on_line = true;
}


void TconvertedPass1_WP6::Footnote6(uint32_t & NewPos)
{
#ifdef DEBUG
  fprintf(log,"\n#Footnote6() ");fflush(log);
#endif
  unsigned char OldFlag;
  char BkEnvir;
  attribute OldAttr;
  uint32_t end_of_code,BlockOffset,BlockSize;
  uint16_t ResourceNo,TextBlocks;
  Resource Res;
  int ignored;

  OldFlag = flag;

//CrackObject(cq, NewPos);

  fseek(wpd, 2L, SEEK_CUR);
  Rd_word(wpd, &ResourceNo);


  if(LoadResource(ResourceNo, Res)) goto BadResource;
  if(Res.PacketType!=8) {BadResource(ResourceNo);goto BadResource;}

  fseek(wpd, Res.ResourceFilePos, SEEK_SET);
  Rd_word(wpd, &TextBlocks);	// Load # of text blocks
  if(TextBlocks<1) {BadResource(ResourceNo);goto BadResource;}

  Rd_dword(wpd, &BlockOffset);
  Rd_dword(wpd, &BlockSize);

  fseek(wpd, Res.ResourceFilePos+BlockOffset, SEEK_SET);

  end_of_code = Res.ResourceFilePos+BlockOffset+BlockSize;
  if(BlockOffset + BlockSize > Res.PacketSize)
		end_of_code = Res.ResourceFilePos+Res.PacketSize; //resource seems to be bad - try anyway


  flag = HeaderText;
  recursion++;

  Close_All_Attr(attr,strip);
  OldAttr = attr;
  attr.InitAttr();		//Turn all attributes in the footnotet off

  BkEnvir = envir;
  if(BkEnvir=='L' || BkEnvir=='B') // || BkEnvir=='i')
  {
    envir = '!';  		//Ignore enviroments Before
    NewLine(this);
    envir = ' ';
  }

  fprintf(strip, "\\footnote{");

  ActualPos = ftell(wpd);
  while (ActualPos < end_of_code)
	{
	fread(&by, 1, 1, wpd);

	switch (by)
	     {
	     case 0xC7:
	     case 0xCC:fprintf(strip, " \\\\ ");
		       ActualPos++;
		       break;
	     case 0xCF:putc(' ', strip);
		       ActualPos++;
		       break;
	     case 0xD0:flag = CharsOnly;
		       ProcessKey60();
		       flag = HeaderText;
		       switch (subby)
			  {
			  case 4:                               //HRt
			  case 6:			        //Spg-HRt
			  case 9:fprintf(strip, " \\\\ ");  //Hpg
				 break;
			  case 1:                               //SRt
			  case 3:putc(' ', strip);          //SRt-Spg
				 break;
			  }
		       break;
	     case 0xDD:ProcessKey60();
		       switch (subby)
			  {
			  case 0xA:flag = Nothing;    break; //Global On
			  case 0xB:flag = HeaderText; break; //Global Off
			  }
		       break;


	     default: ProcessKey60();
		      break;
	     }
	}

  Close_All_Attr(attr,strip);   /* Echt nodig ? */
  if(envir != ' ') NewLine(this);
  putc('}', strip);

  if(envir != ' ')	// Finish all environments started in footnote.
    {
    envir = ' ';
    NewLine(this);
    }

  if(BkEnvir=='L' || BkEnvir=='B') // || BkEnvir=='i')
    {
    envir = '^';		//Ignore enviroments Before
    NewLine(this);
    char_on_line = -1;
    }
  envir = BkEnvir;

  recursion--;

// Cut Useless Bookmarks and endnote index from main document
  ignored=0;
  flag = Nothing;

  fseek(wpd, NewPos, SEEK_SET);
  ActualPos=NewPos;

  while(!feof(wpd) && ignored<20)
	{
	fread(&by, 1, 1, wpd);

	if(by==0xD7)
		{
		NewPos=ActualPos;
		break;			//Everything is OK, useless section successfully ignored.
		}

	ProcessKey60();
	ignored++;
	}

  if(ignored>=20)
     if (err != NULL)
	{
	perc.Hide();
	fprintf(err, _("\nWarning: Cannot remove strange Endnote index!"));
	}

  attr = OldAttr;
  flag = OldFlag;
BadResource:
  strcpy(ObjType, "Footnote");
}


/** This function prints the current number of the footnote. */
void TconvertedPass1_WP6::FootnoteNumber6(uint32_t & NewPos)
{
#ifdef DEBUG
  fprintf(log,"\n#FootnoteNumber6() ");fflush(log);
#endif

  fprintf(strip, "\\thefootnote ");

  SkipNumber6(this,NewPos);

  strcpy(ObjType, "Formatted Footnote Num");
  char_on_line = true;
}


void TconvertedPass1_WP6::Header_Footer6(void)
{
#ifdef DEBUG
  fprintf(log,"\n#Header_Footer6() ");fflush(log);
#endif
 uint8_t occurance,flags,PIDS;
 attribute OldAttr;
 unsigned char OldFlag,OldEnvir;
 uint32_t BlockOffset,BlockSize,end_of_code;
 uint16_t ResourceNo,TextBlocks;
 Resource Res;
 const char *ObjectName;
 static const char Occurance6to5[4] = {0,2,4,1};


  switch (subby)
	{
	case 0:ObjectName="Header A";	 break;
	case 1:ObjectName="Header B";	 break;
	case 2:ObjectName="Footer A";	 break;
	case 3:ObjectName="Footer B";	 break;
	case 4:ObjectName="!Watermark A";goto BadResource;
	case 5:ObjectName="!Watermark B";goto BadResource;
	default:ObjectName="!Unknown";	 goto BadResource;
	}

  flags = getc(wpd);
  PIDS = getc(wpd);
  if(PIDS<=0) goto BadResource;

  Rd_word(wpd, &ResourceNo);
  fseek(wpd, 2L*(PIDS-1) + 2L, SEEK_CUR);  //skip other resources + size of non del data
  occurance=getc(wpd);


  if(LoadResource(ResourceNo, Res)) goto BadResource;
  if(Res.PacketType!=8) {BadResource(ResourceNo);goto BadResource;}

  fseek(wpd, Res.ResourceFilePos, SEEK_SET);
  Rd_word(wpd, &TextBlocks);	// Load # of text blocks
  if(TextBlocks<1) {BadResource(ResourceNo);goto BadResource;}

  Rd_dword(wpd, &BlockOffset);
  Rd_dword(wpd, &BlockSize);

  fseek(wpd, Res.ResourceFilePos+BlockOffset, SEEK_SET); // seek to the beginning of the text

  end_of_code = Res.ResourceFilePos+BlockOffset+BlockSize;
  if(BlockOffset + BlockSize > Res.PacketSize)
		end_of_code = Res.ResourceFilePos+Res.PacketSize; //resource seems to be bad - try anyway


  OldFlag = flag;
  OldEnvir= envir;

  Close_All_Attr(attr,strip);
  OldAttr=attr;			/* Backup all attributes */
  if(Font==FONT_HEBREW || Font==FONT_CYRILLIC || Font==FONT_GEORGIA)
      {
      Font = FONT_NORMAL;
      }

  line_term = 's';    	//Soft return
  if(char_on_line == LEAVE_ONE_EMPTY_LINE)  // Left one enpty line for new enviroment.
      {
      fputc('%', table);
      fputc('%', strip);
      NewLine(this);
      }
  if(char_on_line==CHAR_PRESENT)
      {
      NewLine(this);
      }

  recursion++;
  attr.InitAttr();
			// bit 0 - occurance on odd pages
			// bit 1 - occurance on even pages
  InitHeaderFooter(this, subby, Occurance6to5[occurance & 3]);

  envir='!';		//Ignore enviroments after header/footer
  NewLine(this);

  attr.InitAttr();		//Turn all attributes in the header/footer off

  flag = HeaderText;
  envir = ' ';
  ActualPos = ftell(wpd);
  char_on_line = FIRST_CHAR_MINIPAGE;
  while (ActualPos < end_of_code)
        {
        fread(&by, 1, 1, wpd);

	ProcessKey60();
        }

  Close_All_Attr(attr,strip);
  if(char_on_line==CHAR_PRESENT)
     {
     line_term = 's';    	//Soft return
     NewLine(this);
     }
  putc('}', strip);

  line_term = 's';    	//Soft return
  envir = '^';		//Ignore enviroments after header/footer
  NewLine(this);

  attr = OldAttr;	// Restore backuped attributes
  flag = OldFlag;
  envir = OldEnvir;
  char_on_line = FIRST_CHAR_MINIPAGE;	// stronger false;
  recursion--;

BadResource:
  strcpy(ObjType,ObjectName);
}


static void Hyphenation6(TconvertedPass1 *cq)
{
uint8_t b;

 fseek(cq->wpd, 3L, SEEK_CUR);
 fread(&b, 1, 1, cq->wpd);    /*0- hyphenation off; 1- hyphenation on*/

 Hyphenation(cq,b);
}


static void Label16Inside(TconvertedPass1_WP6 *cq, uint32_t end_of_code, uint16_t Wchar = 0)
{
const char *CharStr;

  if(Wchar==0) Rd_word(cq->wpd, &Wchar);
  cq->ActualPos=ftell(cq->wpd)-2;
  while(Wchar!=0 && cq->ActualPos<=end_of_code)
	{
	CharStr = Ext_chr_str(Wchar, cq, cq->ConvertCpg);
	FixLabelText(CharStr,cq->strip);

	Rd_word(cq->wpd, &Wchar);
        cq->ActualPos+=2;

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

if(feof(cq->wpd)) fseek(cq->wpd, cq->DocumentStart, SEEK_SET);
}


static void LineSpacing6(TconvertedPass1 *cq)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#LineSpacing6() ");fflush(cq->log);
#endif
uint32_t CurrentSpacing;
uint16_t  WordSpacing;
char b;

  fseek(cq->wpd, 3l, SEEK_CUR);
  Rd_dword(cq->wpd,&CurrentSpacing);

  WordSpacing=(uint16_t)(CurrentSpacing*128l / 0x10000);

  b = 'l';
  fwrite(&b, 1, 1, cq->table);
  Wr_word(cq->table,WordSpacing);

  sprintf(cq->ObjType, "Line Spacing %2.2f",float(CurrentSpacing)/0x10000);
}


/*This procedure converts a sequence of overstriked characters*/
static void Overstrike6(TconvertedPass1_WP6 *cq, uint32_t end_of_code)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#Ovestrike6() ");fflush(cq->log);
#endif
int CharCount=0;
uint16_t Wchar;
attribute OldAttr;
string s;

  fseek(cq->wpd, 3L, SEEK_CUR);
  Rd_word(cq->wpd, &Wchar);
  cq->ActualPos=ftell(cq->wpd)-2;

  cq->recursion++;
  end_of_code-=4;
  OldAttr = cq->attr;
  *cq->ObjType=0;
  while(Wchar!=0 && cq->ActualPos<=end_of_code)
	{
	switch(Wchar)
	  {
	  case 0xFC66:Attr_ON(cq,0);	break;
	  case 0xFC67:Attr_ON(cq,1);	break;
	  case 0xFC68:Attr_ON(cq,2);	break;
	  case 0xFC69:Attr_ON(cq,3);	break;
	  case 0xFC6A:Attr_ON(cq,4);	break;
	  case 0xFC6B:Attr_ON(cq,5);	break;
	  case 0xFC6C:Attr_ON(cq,6);	break;
	  case 0xFC6D:Attr_ON(cq,7);	break;
	  case 0xFC6E:Attr_ON(cq,8);	break;
	  case 0xFC6F:Attr_ON(cq,9);	break;
	  case 0xFC70:Attr_ON(cq,10);	break;
	  case 0xFC71:Attr_ON(cq,11);	break;
	  case 0xFC72:Attr_ON(cq,12);	break;
	  case 0xFC73:Attr_ON(cq,13);	break;
	  case 0xFC74:Attr_ON(cq,14);	break;
	  case 0xFC75:Attr_ON(cq,15);	break;

	  case 0xFC76:Attr_OFF(cq,0);	break;
	  case 0xFC77:Attr_OFF(cq,1);	break;
	  case 0xFC78:Attr_OFF(cq,2);	break;
	  case 0xFC79:Attr_OFF(cq,3);	break;
	  case 0xFC7A:Attr_OFF(cq,4);	break;
	  case 0xFC7B:Attr_OFF(cq,5);	break;
	  case 0xFC7C:Attr_OFF(cq,6);	break;
	  case 0xFC7D:Attr_OFF(cq,7);	break;
	  case 0xFC7E:Attr_OFF(cq,8);	break;
	  case 0xFC7F:Attr_OFF(cq,9);	break;
	  case 0xFC80:Attr_OFF(cq,10);	break;
	  case 0xFC81:Attr_OFF(cq,11);	break;
	  case 0xFC82:Attr_OFF(cq,12);	break;
	  case 0xFC83:Attr_OFF(cq,13);	break;
	  case 0xFC84:Attr_OFF(cq,14);	break;
	  case 0xFC85:Attr_OFF(cq,15);	break;

	  default:Open_All_Attr(cq->attr, cq->strip);
		  if(CharCount>0)
		    {
		    if(cq->attr.Math_Depth>0) cq->attr.Math_Depth=0;//Math might be nested inside \llap
		    fputs("\\llap{",cq->strip);
		    }
		  CharacterStr(cq,Ext_chr_str(Wchar, cq, cq->ConvertCpg));
		  if(CharCount>0)  fputs("}",cq->strip);
		  CharCount++;
	  }

	if (cq->log != NULL)
	     {   /**/
	     if (*cq->ObjType != '\0')
		  {
		  fprintf(cq->log, "\n%*s [%s] ",cq->recursion * 2,"",
			 cq->ObjType);
		  *cq->ObjType=0;
		  }
	     else fprintf(cq->log, " [%u] ", Wchar);
	     }


	Rd_word(cq->wpd, &Wchar);
	cq->ActualPos+=2;
	}

  AttrFit(cq->attr,OldAttr,s);
  if(!s.isEmpty()) fputs(s(),cq->strip);

  cq->recursion--;
  if(CharCount>0) cq->char_on_line = true;

  strcpy(cq->ObjType, "Overstrike");
}


void TconvertedPass1_WP6::SetFontShape(void)
{
#ifdef DEBUG
  fprintf(log,"\n#SetFontShape() ");fflush(log);
#endif
uint16_t  ResourceNo, FontNameSize, Wchar;
string FontName;
const char *ig="!";
Resource Res;

  fseek(wpd, 2L, SEEK_CUR);
  Rd_word(wpd, &ResourceNo);
  if(LoadResource(ResourceNo, Res)) goto BadResource;
  if(Res.PacketType!=0x55) goto BadResource;

  fseek(wpd, Res.ResourceFilePos+22, SEEK_SET);
  Rd_word(wpd, &FontNameSize);
  while(FontNameSize>0)
	{
	Rd_word(wpd, &Wchar);
	if(Wchar==0) break;
	FontName += Ext_chr_str(Wchar, this, ConvertCpg);
	FontNameSize--;
	}

  SetFont(this,0,FontName());
  if(NFSS && !FontName.isEmpty()) ig="";

BadResource:
  if(length(FontName)>(int)sizeof(ObjType)-7)
	FontName=copy(FontName,0,sizeof(ObjType)-7);
  sprintf(ObjType, "%sFont %s", ig, chk(FontName()));
}




//---------------------------

/*This procedure increments the number of current endnote*/
static void IncCounterNum(TconvertedPass1 *cq,const char *CounterName)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#IncCounterNum() ");fflush(cq->log);
#endif

  fprintf(cq->strip, "\\stepcounter{%s}",CounterName);
  sprintf(cq->ObjType, "Inc %s Num",CounterName);
}


/**This procedure increments the number of the user counter*/
void TconvertedPass1_WP6::IncUserCounter(void)
{
#ifdef DEBUG
  fprintf(log,"\n#IncUserCounter() ");fflush(log);
#endif
  uint8_t Flag,NumID;
  uint16_t ResourceNo,Wchr;
  Resource Res;
  string CounterName;

  Flag = getc(wpd);
  if(!(Flag & 0x80)) goto BadResource;
  NumID = getc(wpd);

  while(NumID>0)
	{
	Rd_word(wpd,&ResourceNo);
	if(LoadResource(ResourceNo, Res)) goto BadResource;
	if(Res.PacketType==0x11)
		{
		fseek(wpd,Res.ResourceFilePos,SEEK_SET);

		Rd_word(wpd,&Wchr);
		while(Wchr!=0)
		  {
		  CounterName+=Ext_chr_str(Wchr, this, ConvertCpg);
		  Rd_word(wpd,&Wchr);
		  }

		break;
		}

	NumID--;
	}
  if(CounterName.isEmpty()) goto BadResource;

  FixCounterName(CounterName);
  Counters|=CounterName;
  fprintf(strip, "\\stepcounter{%s}",CounterName());

BadResource:
  if(length(CounterName)>(int)sizeof(ObjType)-13)
	{
	CounterName[sizeof(ObjType)-13]=0;
	}
  sprintf(ObjType, "Inc %s Counter",chk(CounterName()));
}


/** This procedure decrements the number of the user counter. */
void TconvertedPass1_WP6::DecUserCounter(void)
{
#ifdef DEBUG
  fprintf(log,"\n#DecUserCounter() ");fflush(log);
#endif
  uint8_t Flag,NumID;
  uint16_t ResourceNo,Wchr;
  Resource Res;
  string CounterName;

  Flag=getc(wpd);
  if(!(Flag & 0x80)) goto BadResource;
  NumID=getc(wpd);

  while(NumID>0)
	{
	Rd_word(wpd,&ResourceNo);
	if(LoadResource(ResourceNo, Res)) goto BadResource;
	if(Res.PacketType==0x11)
		{
		fseek(wpd,Res.ResourceFilePos,SEEK_SET);

		Rd_word(wpd,&Wchr);
		while(Wchr!=0)
		  {
		  CounterName+=Ext_chr_str(Wchr, this, ConvertCpg);
		  Rd_word(wpd,&Wchr);
		  }

		break;
		}

	NumID--;
	}
  if(CounterName.isEmpty()) goto BadResource;

  FixCounterName(CounterName);
  Counters|=CounterName;
  fprintf(strip, "\\addtocounter{%s}{-1}",CounterName());

BadResource:
  if(length(CounterName)>(int)sizeof(ObjType)-13)
	{
	CounterName[sizeof(ObjType)-13]=0;
	}
  sprintf(ObjType, "Dec %s Counter",chk(CounterName()));
}


void TconvertedPass1_WP6::UserCounter(uint32_t & NewPos)
{
#ifdef DEBUG
  fprintf(log,"\n#PageNumber6() ");fflush(log);
#endif
  int i;
  unsigned char by;
  uint8_t Flag,NumID;
  uint16_t ResourceNo,Wchr;
  Resource Res;
  string CounterName;

  Flag=getc(wpd);
  if(!(Flag & 0x80)) goto BadResource;
  NumID=getc(wpd);

  while(NumID>0)
    {
    Rd_word(wpd,&ResourceNo);
    if(LoadResource(ResourceNo, Res)) goto BadResource;
    if(Res.PacketType==0x11)
	{
	fseek(wpd,Res.ResourceFilePos,SEEK_SET);

	Rd_word(wpd,&Wchr);
	while(Wchr!=0)
	  {
          const char *Conv = Ext_chr_str(Wchr, this, ConvertCpg);
	  if(!strcmp(Conv," -?- "))
            CounterName.cat_printf("W%u",Wchr);
          else	
	    CounterName += Conv;
	  Rd_word(wpd,&Wchr);
	  }

	break;
        }
    NumID--;
    }
  if(CounterName.isEmpty()) goto BadResource;

  FixCounterName(CounterName);
  Counters|=CounterName;
  fprintf(strip, "\\the%s ",CounterName());

  fseek(wpd, NewPos, 0);
  i=0;
  while(i<20)		// Read the page number text
	{
	fread(&by, 1, 1, wpd);
	if(!isalnum(by)) break;
	i++;
	}

  if(by==0xDA && i<20)	// Skip the page number text after object
	{
	NewPos+=i;
	}

  char_on_line = true;
BadResource:
  if(length(CounterName)>(int)sizeof(ObjType)-9)
	{
	CounterName[sizeof(ObjType)-9]=0;
	}
  sprintf(ObjType, "Counter %s", chk(CounterName()));
}


/*This procedure increments the number of current endnote*/
static void DecCounterNum(TconvertedPass1 *cq,const char *CounterName)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#DecCounterNum() ");fflush(cq->log);
#endif

  fprintf(cq->strip, "\\addtocounter{%s}{-1}",CounterName);
  sprintf(cq->ObjType, "Inc %s Num",CounterName);
}


static void EndnoteNumber6(TconvertedPass1 *cq, uint32_t & NewPos)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#EndnoteNumber6() ");fflush(cq->log);
#endif

  if(!EndNotes) EndNotes=true;		/* set up endnotes */
  if(EndNotes<0)
	{
	strcpy(cq->ObjType, "!Endnote Num");
	return;
	}

  fprintf(cq->strip, "\\theendnote ");

  SkipNumber6(cq,NewPos);

  strcpy(cq->ObjType, "Formatted Endnote Num");
  cq->char_on_line = true;
}


/** This procedure converts WP6.x Line numbering. */
static void LineNumbering6(TconvertedPass1_WP6 *cq)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#LineNumbering6() ");fflush(cq->log);
#endif
 uint8_t PIDs, LineNumFlag;

  fseek(cq->wpd, 1L, SEEK_CUR);		// skip Flag
  PIDs = fgetc(cq->wpd);
  fseek(cq->wpd, 2*PIDs+2+2+1+2+2, SEEK_CUR);
  LineNumFlag = fgetc(cq->wpd);

  LineNumbering(cq, LineNumFlag&1);
}


void TconvertedPass1_WP6::MakeIndex60(void)
{
#ifdef DEBUG
  fprintf(log,"\n#MakeIndex60() ");fflush(log);
#endif
  unsigned char OldFlag;
  uint16_t ResourceNo,Wchar;
  Resource Res;

  OldFlag = flag;

  fseek(wpd, 2L, SEEK_CUR);
  Rd_word(wpd, &ResourceNo);
  if(LoadResource(ResourceNo, Res)) goto BadResource;


  fseek(wpd, Res.ResourceFilePos, SEEK_SET);
  Rd_word(wpd, &Wchar);	// Load first resource char
  if(feof(wpd)) {fseek(wpd, 0l, SEEK_CUR);{BadResource(ResourceNo);goto BadResource;}};
  if(Wchar!=0) {BadResource(ResourceNo);goto BadResource;}


  fprintf(strip, " \\index{");

  flag = HeaderText;
  Label16Inside(this, DocumentStart, Wchar);

  putc('}', strip);
  Index=true;

  flag = OldFlag;
  char_on_line = true;

BadResource:
  strcpy(ObjType, "Index");
}


void TconvertedPass1_WP6::MakeLabel6(void)
{
#ifdef DEBUG
  fprintf(log,"\n#MakeLabel6() ");fflush(log);
#endif
  unsigned char OldFlag;
  uint16_t Wchar, ResourceNo;
  Resource Res;
  uint8_t PIDs;

  OldFlag = flag;

  fseek(wpd, 1L, SEEK_CUR);
  PIDs=fgetc(wpd);
  if(PIDs!=1)
    {
    if(err!=NULL)
       fprintf(err, _("\nWarning: Label contains unexpected amount of resources %d!"),(int)PIDs);
	goto BadResource;
    }
  Rd_word(wpd, &ResourceNo);
  if(LoadResource(ResourceNo, Res)) goto BadResource;


  if(Res.PacketType!=0xF) {BadResource(ResourceNo);goto BadResource;}
  fseek(wpd, Res.ResourceFilePos, SEEK_SET);
  Rd_word(wpd, &Wchar);	// Load first resource char
  if(feof(wpd)) {fseek(wpd, 0l, SEEK_SET);{BadResource(ResourceNo);goto BadResource;}};
  if(Wchar==0) {BadResource(ResourceNo);goto BadResource;}


  fprintf(strip, "%s\\label{",char_on_line>0?" ":"");

  flag = HeaderText;
  Label16Inside(this, DocumentStart, Wchar);

  putc('}', strip);

  flag = OldFlag;
  if(char_on_line == false)
  	char_on_line = -1;
BadResource:
  strcpy(ObjType, "Label");
}


static void MakeRef6(TconvertedPass1_WP6 *cq, uint32_t & NewPos, char TypeRef)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#MakeRef6(NewPos=%u) ",NewPos); fflush(cq->log);
#endif
  unsigned char OldFlag;
  uint32_t end_of_code;
  int i;
  unsigned char ch,SubRefType;


  end_of_code=NewPos;
  OldFlag = cq->flag;
  end_of_code -= 4;

  fread(&SubRefType, 1, 1, cq->wpd);
  fseek(cq->wpd,SubRefType<0x80? 2l : 7l , SEEK_CUR);
  cq->ActualPos = ftell(cq->wpd);

  if(TypeRef>9) TypeRef=9;
  if(TypeRef==0) fprintf(cq->strip, " \\pageref{");
  	    else fprintf(cq->strip, " \\ref{");

  cq->flag = HeaderText;
  Label16Inside(cq, end_of_code);

  putc('}', cq->strip);

//The referred number must be removed
  if(SubRefType>=0x80)
    {
    fseek(cq->wpd, NewPos, 0);
    i=0;
    while(i<20)		// Read the page number text
  	  {
          fread(&ch, 1, 1, cq->wpd);
          if(!isalnum(ch)) break;
          i++;
	  }

    if(ch==0xD5 && i<20)	// Skip the page number text after object
  	  {
          NewPos+=i;
          }
    }

  cq->flag = OldFlag;
  cq->char_on_line = true;
  sprintf(cq->ObjType, "Ref:%s",RefTypes[TypeRef]);
}


static void PageNumber6(TconvertedPass1 *cq, uint32_t & NewPos)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#PageNumber6() ");fflush(cq->log);
#endif
int i;
unsigned char by;

  fprintf(cq->strip, "\\thepage ");
  fseek(cq->wpd, NewPos, 0);

  i=0;
  while(i<20)		// Read the page number text
	{
	fread(&by, 1, 1, cq->wpd);
	if(!isalnum(by)) break;
	i++;
	}

  if(by==0xDA && i<20)	// Skip the page number text after object
	{
	NewPos+=i;
	}

  strcpy(cq->ObjType, "Formatted Pg Num");
  cq->char_on_line = true;
}


/** This procedure sets the user counter to a given number. */
void TconvertedPass1_WP6::SetUserCounter(void)
{
#ifdef DEBUG
  fprintf(log,"\n#SetUserCounter() ");fflush(log);
#endif
  uint8_t Flag,NumID;
  uint16_t ResourceNo,Wchr;
  Resource Res;
  string CounterName;
  uint32_t SavePos;

  Flag=getc(wpd);
  if(!(Flag & 0x80)) goto BadResource;
  NumID=getc(wpd);

  while(NumID>0)
	{
	Rd_word(wpd,&ResourceNo);
	SavePos= ftell(wpd);
	if(LoadResource(ResourceNo, Res)) goto BadResource;
	if(Res.PacketType==0x11)
		{
		fseek(wpd,Res.ResourceFilePos,SEEK_SET);

		Rd_word(wpd,&Wchr);
		while(Wchr!=0)
		  {
		  CounterName += Ext_chr_str(Wchr, this, ConvertCpg);
		  Rd_word(wpd,&Wchr);
		  }
		}

	fseek(wpd,SavePos,SEEK_SET);
	NumID--;
	}
  if(CounterName.isEmpty()) goto BadResource;

  fseek(wpd,4l,SEEK_CUR);
  Rd_word(wpd, &Wchr);

  FixCounterName(CounterName);
  Counters|=CounterName;
  fprintf(strip, "\\setcounter{%s}{%u}",CounterName(),(unsigned int)Wchr);

BadResource:
  if(length(CounterName)>(int)sizeof(ObjType)-13)
	{
	CounterName[sizeof(ObjType)-13]=0;
	}
  sprintf(ObjType, "Set Counter %s=%u",chk(CounterName()),(unsigned int)Wchr);
}


void TconvertedPass1_WP6::TableOfContents6(void)
{
#ifdef DEBUG
  fprintf(log,"\n#TableOfContents6() ");fflush(log);
#endif
  char ListType;

  if ((char_on_line==CHAR_PRESENT)||(attr.Opened_Depth>0))
    {
    Close_All_Attr(attr,strip);

    NewLine(this);
    }

  fseek(wpd, 6L, SEEK_CUR);
  fread(&ListType, 1, 1, wpd);

  switch(ListType)
  	{
	case  0:fprintf(strip, "\\tableofcontents");
		line_term = 's';   /* Soft return */
		NewLine(this);
        	strcpy(ObjType, "Def Mark:ToC");
                break;
	case  1:sprintf(ObjType, "!Def Mark:List");
// !!!!!!!!! The lists are not converted yet
		break;
	case  2:PlaceIndex(this);
		strcpy(ObjType, "Def Mark:Index");
		break;
	case  3:sprintf(ObjType, "!Def Mark:ToA");
// !!!!!!!!! The tables of autorities are not converted yet
	        break;

	default: strcpy(ObjType, "!Def Mark:?Unknown");
	}
}


static void TabSet6(TconvertedPass1 *cq)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#TabSet6() ");fflush(cq->log);
#endif
 int j,SideMargin;
 uint16_t oldw,w,difw,Adjust;
 uint8_t Definition,TabsNum,TabType,TabRepeater;

  fseek(cq->wpd, 3L, SEEK_CUR);

  Definition = fgetc(cq->wpd);
  Rd_word(cq->wpd, &Adjust);
  TabsNum = fgetc(cq->wpd);

  if((Definition & 1) == 1)
	{
	SideMargin=Adjust+cq->WP_sidemargin-cq->Lmar;//Relative Tab
	}
	else SideMargin=cq->WP_sidemargin;	//Absolute Tab

  cq->num_of_tabs = 0;
  oldw=0;
  TabRepeater=TabType=0;
  for (j = 1; j <= TabsNum; j++)
      {
      if(TabRepeater<1)
	 {
	 TabRepeater = fgetc(cq->wpd);
	 if(TabRepeater>=0x80)
		     {
		     TabRepeater &= 0x7F;
		     j-= TabRepeater-1;
		     Rd_word(cq->wpd, &difw);
		     }
		else {
		     TabType=TabRepeater;
		     TabRepeater=0;
		     Rd_word(cq->wpd, &w);
		     }
	 }

      if(TabRepeater>0)
	   {
	   TabRepeater--;
	   w=oldw+difw;
	   }

      if (w > cq->WP_sidemargin && w != 0xffffL)
	    {
	    cq->num_of_tabs++;
	    cq->tabpos[cq->num_of_tabs - 1] = w - SideMargin;
	    }
      oldw=w;
      }

  Make_tableentry_tabset(cq);
  sprintf(cq->ObjType, "TabSet:%s", (Definition & 1)?"Rel":"Abs");
}


/** This procedure converts beginning of the table and reads alignment of columns. */
void TconvertedPass1_WP6::TableStart6(uint32_t & NewPos)
{
#ifdef DEBUG
  fprintf(log,"\n#TableStart6() ");fflush(log);
#endif
int columns;
uint16_t w;
uint32_t attributes;
unsigned char align;
string TexAttrib;
bool bookmark=false;
unsigned char OldFlag;
char OldEnvir;
uint8_t Flag, NumID;
attribute OldAttr;

  Flag = getc(wpd);
  if(!(Flag & 0x80)) {Flag=0;goto BadResource;}
  NumID = getc(wpd);
  fseek(wpd, 2*NumID + 2 + 1, SEEK_CUR);

  Flag = getc(wpd);		//table flags

BadResource:
  fseek(wpd, NewPos, SEEK_SET);
  OldFlag = flag;
  OldEnvir= envir;
  OldAttr = attr;

  columns=0;            // a counter of columns
  while(columns<80)		// Read next text
	{
        unsigned char by,subby;
	fread(&by, 1, 1, wpd);
	fread(&subby, 1, 1, wpd);
	if(!bookmark)
		{
		if(by==0xF1 && subby==0x0)  //remove useless bookmark
			{
			bookmark=true;
			NewPos+=5;
			fseek(wpd, NewPos, SEEK_SET);
			continue;
			}
		}

	if(subby!=0x2C) break;
	if(by!=0xD4) break;
	Rd_word(wpd, &w);

	fseek(wpd, 10l, SEEK_CUR);
	Rd_dword(wpd, &attributes);
	fread(&align, 1, 1, wpd);

	if(columns==0)
		{
		line_term = 's';   /* Soft return */
		recursion++;

		if(char_on_line == LEAVE_ONE_EMPTY_LINE)  // Left one enpty line for new enviroment.
		    {
		    fputc('%', table);fputc('%', strip);
		    NewLine(this);
		    }
		if(char_on_line>=CHAR_PRESENT) //  if(char_on_line>=-1)
		    {
		    NewLine(this);
		    }		
			
		switch(Flag & 3)	// Apply table position flag
		{
		  case 1:if(OldEnvir!='R')
		 	   {fprintf(strip, "\\begin{flushright}"); NewLine(this);}
			 break;
		  case 2:if(OldEnvir!='C')
		 	   {fprintf(strip, "\\begin{center}"); NewLine(this);}
			 break;
		}
                
                attr.InitAttr();	// OldAttr is saved before loop.

		envir='!';
		fputc('%', table);fputc('%', strip);
		NewLine(this);

		envir = 'B';
		fprintf(strip, "{|");
		}

	TexAttrib = Attributes2String(attributes); //Solve attributes for columns
	if(!TexAttrib.isEmpty())
	  {
	  fprintf(strip,"@{%s}",TexAttrib());
	  }
	switch(align & 0x7) /* bits 0-2 align; bit 3 - absolute position; 4-7 num of chars */
		{
		case 0x0:fprintf(strip, "l|"); break;  //left
		case 0x1:fprintf(strip, "c|"); break;  //full
		case 0x2:fprintf(strip, "c|"); break;  //center
		case 0x3:fprintf(strip, "r|"); break;  //right
		case 0x4:		//full all lines
		case 0x5:		//decimal align
		default:fprintf(strip, "c|");
		}

	NewPos+=w;
//	CrackObject(cq, NewPos);
	fseek(wpd, NewPos, SEEK_SET);
	columns++;
	}

  if(columns>0) putc('}', strip);
  char_on_line = false;
  nomore_valid_tabs = false;
  rownum++;
  Make_tableentry_attr(this);
  latex_tabpos = 0;
  if(columns<=0) goto NoTable;

	/* Process all content of the table */
  fseek(wpd,ActualPos=NewPos,SEEK_SET);
  this->by = fgetc(wpd);
  while(!feof(wpd))
	{
	if(this->by==0xD4 && envir!='B')
		{
		envir='B';
		}
	ProcessKey60();
	NewPos = ActualPos;
	if(this->by==0xD0 && this->subby>=17 && this->subby<=19) break; /*End of table*/
	if(this->by>=0xBD && this->by<=0xBF) break;

	this->by = fgetc(wpd);
	}
  if(char_on_line <= FIRST_CHAR_MINIPAGE)   // Left one empty line for ending enviroment.
	{
	fputc('%', table);fputc('%', strip);
	NewLine(this);
	}

  switch(Flag & 3)
  {
    case 1:if(OldEnvir!='R')
	     {fprintf(strip, "\\end{flushright}"); NewLine(this);}
	   break;
    case 2:if(OldEnvir!='C')
	     {fprintf(strip, "\\end{center}"); NewLine(this);}
	   break;
  }

  envir = '^';		//Ignore enviroments after table
  fputc('%', table);
  NewLine(this);
  char_on_line = FIRST_CHAR_MINIPAGE;	// stronger false;

  recursion--;

NoTable:
  flag = OldFlag;
  envir = OldEnvir;
  attr = OldAttr;
  strcpy(ObjType, "!Table Start"+((columns!=0)?1:0));
}


void TconvertedPass1_WP6::Undo(uint32_t & NewPos)
{
#ifdef DEBUG
  fprintf(log,"\n#Undo() ");fflush(log);
#endif
unsigned char OldFlag;
attribute OldAttr;
uint8_t Type;
uint16_t Level;
int16_t SubLevel;
const char *UndoType;

  Type=fgetc(wpd);
  Rd_word(wpd, &Level);
  if(!::UndoRedo) goto SkipUndoStuff;

  fseek(wpd, NewPos, SEEK_SET);

  if(Type==0 && EmptyCheck(UndoRedo))
    {
    UndoRedo.push(-(int)Level);
    if(log)
      fprintf(log,_("\n%*sIgnored from undo %d:"), recursion*2, "", Level);

    OldFlag = flag;
    OldAttr = attr;

    flag = Nothing;

    fseek(wpd, NewPos, SEEK_SET);
    ActualPos=NewPos;

    recursion++;
    while(!feof(wpd))
	{
	if(fread(&by, 1, 1, wpd)<1) break;

	if(by==0xF1) //next Undo command
		{
		NewPos=ActualPos; //Everything is OK
		Type=fgetc(wpd);
		Rd_word(wpd, (uint16_t *)&SubLevel);
		fseek(wpd,ActualPos+1,SEEK_SET);

		switch(Type)
                  {
		  case 0:UndoRedo.push(-(int)SubLevel); break;
		  case 2:UndoRedo.push((int)SubLevel);  break;

		  case 1:SubLevel=-SubLevel;  	//continuing on label 3:
                  case 3:while(UndoRedo.pop()!=(int)SubLevel && !EmptyCheck(UndoRedo))
			   {
			   if(err!=NULL)
	 		     {
	 		     perc.Hide();
	 		     fprintf(err,
			       _("\nError: Undo/Redo stack is corrupted, Type=%d!"),Type);
	 		     }
                           }
                  }
		if(EmptyCheck(UndoRedo))
                  {
                  ProcessKey60();
		  NewPos = ActualPos; //Everything is OK
                  break;}
		}
	ProcessKey60();
	}

     recursion--;
     attr = OldAttr;
     flag = OldFlag;

     Type=0;
     }

SkipUndoStuff:
 switch(Type)
   {
   case 0:UndoType="Invalid Start";	break;
   case 1:UndoType="Invalid End";	break;
   case 2:UndoType="Valid Start";	break;
   case 3:UndoType="Valid End";		break;
   default:if (err != NULL)
		{
		perc.Hide();
		fprintf(err, _("\nWarning: Strange Undo type:%d!"),(int)Type);
		}
	   sprintf(ObjType, "!Undo (?%d:%d)"+(::UndoRedo?1:0),Type,(int)Level);
	   return;
   }

  sprintf(ObjType, "!Undo (%s:%d)"+(::UndoRedo?1:0), UndoType, (int)Level);
}

//-------------------------------------------------


static bool CheckConzistency60(TconvertedPass1 *cq, long NewPos)
{
#ifdef DEBUG
  fprintf(cq->log,"\n#CheckConzistency60() ");fflush(cq->log);
#endif

  bool Result = true;
  unsigned char TestedBy;
  long Pos;

  Pos = ftell(cq->wpd);

  fseek(cq->wpd, NewPos-1 , 0);
  fread(&TestedBy, 1, 1, cq->wpd);

  if(TestedBy != cq->by)
  	{
	if (cq->err != NULL)
	 {
	 cq->perc.Hide();
	 fprintf(cq->err,
	      _("\nError: Object %lX:%X consistency check failed. Trying to ignore."),Pos,(int)cq->by);
	 }
        CorruptedObjects++;
        Result = false;
	/* asm int 3; end;*/
	}

  fseek(cq->wpd, Pos, 0);
  return Result;
}


/** This is main procedure for processing one key. It is recursivelly called. */
void TconvertedPass1_WP6::ProcessKey60(void)
{
#ifdef DEBUG
  fprintf(log,"\n#ProcessKey60() ");fflush(log);
#endif
uint16_t w;
uint32_t NewPos = 0;
unsigned char by, subby;
uint16_t Wchar;

  if(this->by == 0)
    fread(&this->by, 1, 1, wpd);

#ifdef DEBUG
  if(ActualPos+1 != ftell(wpd))
	fprintf(err,
	      _("\nInternal Error: Position skew was detected at 0x%X != 0x%lX!"), ActualPos, ftell(wpd)-1);
#endif //DEBUG

  *ObjType = '\0';
  w = 1;
  this->subby = 0;

	/* Computing end position of the object */
  if (this->by >= 0x7F)
    {
    if((this->by & 0xF0) == 0xF0 )
	{
	w = ObjWP6SizesF0[this->by - 0xF0];
	if (w > 0) NewPos = ActualPos + w;
	this->subby = 0xFF;   /*ignored subcommand*/
	}
    else if(this->by >= 0xD0 && this->by <= 0xEF)
	{
	fread(&this->subby, 1, 1, wpd);
	Rd_word(wpd, &w);
	Linebegin = false;
        if(w<=0)  // We are in big problem now, object is probably, it reports bad size.
          {
          w = 1;
          }
	NewPos = ActualPos + w;
	}
    }

  by = this->by;
  subby = this->subby;

  if(ExtendedCheck && NewPos != 0)
    if(!CheckConzistency60(this, NewPos))
      {
      NewPos = ActualPos+1;
      strcpy(ObjType, "Corrupted!!");
      goto _LObjectError;
      }


  if(filter[flag][by])
     {
     switch(by)
	{
	case 0x01:	//Default extended international characters
	case 0x02:
	case 0x03:
	case 0x04:
	case 0x05:
	case 0x06:
	case 0x07:
	case 0x08:
	case 0x09:
	case 0x0A:
	case 0x0B:
	case 0x0C:
	case 0x0D:
	case 0x0E:
	case 0x0F:
	case 0x10:
	case 0x11:
	case 0x12:
	case 0x13:
	case 0x14:
	case 0x15:
	case 0x16:
	case 0x17:
	case 0x18:
	case 0x19:
	case 0x1A:
	case 0x1B:
	case 0x1C:
	case 0x1D:
	case 0x1E:
	case 0x1F:
	case 0x20:CharacterStr(this,Ext_chr_str(0x100 | CharsWP6_1_32[by],this,ConvertCpg));
		  break;

	case 0x80:putc(' ', strip);   /*soft space*/
		  break;
	case 0x81:fputc('~', strip);strcpy(ObjType, " ");
		  break;
	case 0x82:
	case 0x83:SoftHyphen(this); break;
	case 0x84:HardHyphen(this); break;		/*Hyphen*/
	case 0x85:fputs("\\-", strip);strcpy(ObjType, "- Auto Hyphen");
		  break;
	case 0x86:InvisibleSoftReturn(this);		break;
	case 0x87:Terminate_Line(this, 'h');	/* Dormant Hard Return */
		  strcpy(ObjType, "Dorm HRt");
		  break;

	case 0x90:CancelHyph(this);			break;

	case 0xB8:if(char_on_line>NO_CHAR)	    /*Deleteble Hard EOC/EOP*/
			Terminate_Line(this, 'h'); /*[THRt]  Hard return */
		  char_on_line = -1;
		  strcpy(ObjType, "TH_EOC/EOP");
		  break;
	case 0xB9:if(char_on_line>NO_CHAR)
			Terminate_Line(this, 'h'); /*[THRt]  Hard return */
		  char_on_line = -1;
		  strcpy(ObjType, "THRt");
		  break;

	case 0xBD:				/*Table Off/EOC/EOP*/
	case 0xBE:				/*Table Off/EOC*/
	case 0xBF:EndTable(this);  break;		/*Table Off*/
	case 0xC0:				/*Table Row/Hard EOP*/
	case 0xC1:				/*Table Row/Hard EOC/EOP*/
	case 0xC2:				/*Table Row/Hard EOC*/
	case 0xC3:				/*Table Row/EOC/EOP*/
	case 0xC4:				/*Table Row/EOC*/
	case 0xC5:RowTable(this);  break;		/*Table Row*/
	case 0xC6:if(char_on_line==0) char_on_line=-1;
		  CellTable(this); break;		/*Table Cell*/
	case 0xC7:HardPage(this);  break;		/* Hard page */

	case 0xCC:HardReturn(this);break;		/*[HRt]  Hard return */

	case 0xCF:SoftReturn(this);	break;		/* soft return */
	case 0xD0:switch (subby)
		    {
		    case  1:SoftReturn(this); break;      /* Soft Return */
		    case  3:SoftReturn(this); strcpy(ObjType, "SRt-SPg");
			    break;      		/* Soft Return - Soft Page */
		    case  4:HardReturn(this); break;	/* Hard Return (within TAB) */
		    case  6:Terminate_Line(this, 'h');	/* Prefer Hard return - Soft page */
			    strcpy(ObjType, "HRt-SPg");
			    break;
		    case  9:HardPage(this);   break;	 /* Hard page */
		    case 10:if(char_on_line==0) char_on_line=-1;
			    CellTable(this);  break;
		    case 11:RowTable(this);   break;
		    case 13:RowTable(this);   break;	/* in the case of page break */
		    case 17:			/*Table Off*/
		    case 18:                    /*     at EOC*/
		    case 19:EndTable(this);break; /*     at EOC/EOP*/
		    case 0x1A:if(char_on_line) Terminate_Line(this, 's');
			   strcpy(ObjType, "THCol");
			   break;
		    }
		  break;
	case 0xD1:switch (subby)
		    {
		    case    0:strcpy(ObjType,"!Top Margin");break;
		    case    1:strcpy(ObjType,"!Bottom Margin");break;
		    case    2:Suppress(this,6);			break;
		    case    3:Page_number_position(this,6);	break;
		    case    4:CenterPage(this);			break;
		    case    5:strcpy(ObjType,"!Center Page Top Bottom"); break;
		    case    6:WidowOrphan(this,6);		break;
		    case    7:strcpy(ObjType,"!Set Footnote spaces");break;
		    case    8:strcpy(ObjType,"!Set Endnote spaces");break;

                    case 0x0D:strcpy(ObjType,"!Endnote pos");	break;
                    case 0x0E:strcpy(ObjType,"!Footnote sep line"); break;
                    case 0x0F:strcpy(ObjType,"!Bind Width");	break;
                    case 0x10:strcpy(ObjType,"!Page border"); break;
                    case 0x11:strcpy(ObjType,"!Form");	break;
		    case 0x12:strcpy(ObjType,"!Form Labels");break;
		    case 0x13:strcpy(ObjType,"!Double Sided Printing");break;
		    case 0x14:strcpy(ObjType,"!Logical Pages");break;
		    case 0x15:strcpy(ObjType,"!Delayed Codes");break;
		    case 0x16:strcpy(ObjType,"!Delay on");	break;
		    case 0x17:strcpy(ObjType,"!~Delay on");	break;
		    }
		  break;
	case 0xD2:switch (subby)
		    {
		    case 0: strcpy(ObjType,"!Left Margin");break;
		    case 1: strcpy(ObjType,"!Right Margin");break;
		    case 2: Column6(this);		break;
		    }
		  break;
	case 0xD3:switch (subby)
		    {
		    case  1:LineSpacing6(this);		break;
		    case  4:TabSet6(this);		break;
		    case  5:Justification(this,6); 	break;
		    case  6:Hyphenation6(this); 		break;
		    case  8:strcpy(ObjType,"!Begin Generated Text");break;
		    case  9:strcpy(ObjType,"!End Generated Text");break;
                    case 0xA:strcpy(ObjType,"!Spacing after par");break;
                    case 0xB:strcpy(ObjType,"!Indent 1st line");break;
                    case 0xC:strcpy(ObjType,"!Left Margin Adjust");break;
		    case 0xD:strcpy(ObjType,"!Right Margin Adjust");break;
		    case 0xE:strcpy(ObjType,"!Outline Define");break;
                    case 0xF:strcpy(ObjType,"!Par border");break;
                    case 0x10:strcpy(ObjType,"!Math cols");break;
                    case 0x11:strcpy(ObjType,"!Math on/off");break;
                    case 0x12:LineNumbering6(this);	break;
                    case 0x13:strcpy(ObjType,"!Force odd/even/new");break;
		    case 0x14:PlaceEndnotes(this);	break;
                    case 0x15:strcpy(ObjType,"!Endnotes here");break;
		    case 0x16:TableOfContents6();	break;
                    case 0x17:strcpy(ObjType,"!Def drom cap");break;
		    }
		  break;
	case 0xD4:switch (subby)
		    {
                    case 0x00:strcpy(ObjType,"!Align char");break;
                    case 0x01:strcpy(ObjType,"!Thousand sep");break;
                    case 0x02:strcpy(ObjType,"!Und space mode");break;
                    case 0x03:strcpy(ObjType,"!Und TAB mode");break;
		    case 0x06:MakeIndex60();		break;
		    case 0x08:MakeLabel6();		break;
		    case 0x0A:StartSection(this,6);	break;
		    case 0x0B:EndSection(this,6);		break;
		    case 0x18:Color(this,6);		break;
		    case 0x1C:if(w>=0xE)
				{
				char flags=getc(wpd);
				uint16_t NdelData;
				Rd_word(wpd, &NdelData);
				Language(this, 6);
				}
			      break;
		    case 0x1A:SetFontShape();		break;
		    case 0x1B:SetFontSize(this,6);	break;

		    case 0x1D:Comment6();		break;

                    case 0x23:strcpy(ObjType,"!Char Space/Width");break;
		    case 0x24:strcpy(ObjType,"!Space expansion");break;
		    case 0x25:strcpy(ObjType,"!Bookmark");break;
                    case 0x26:strcpy(ObjType,"!Protect blk on");break;
                    case 0x27:strcpy(ObjType,"!Protect blk off");break;
                    case 0x28:strcpy(ObjType,"!Printer pause");break;
		    case 0x29:Overstrike6(this,NewPos);	break;
		    case 0x2A:TableStart6(NewPos);	break;

		    case 0x2C:strcpy(ObjType,"!Table Hdr");break;

                    case 0x2E:Filename(this,NewPos);	break;
                    case 0x2F:strcpy(ObjType,"~Filename"); break;

		    case 0x32:strcpy(ObjType,"!Par Num On"); break;
		    case 0x33:strcpy(ObjType,"!Par Num Off"); break;
                    }
        	  break;
        case 0xD5:switch (subby)
                    {
                    case  0:MakeRef6(this, NewPos, 1);	break;
                    case  2:MakeRef6(this, NewPos, 2);	break;
		    case  4:MakeRef6(this, NewPos, 0);	break;
                    case  6:MakeRef6(this, NewPos, 3);	break;
                    case  8:MakeRef6(this, NewPos, 4);	break;
                    case 10:MakeRef6(this, NewPos, 5);	break;
                    case 12:MakeRef6(this, NewPos, 6);	break;
                    case 14:MakeRef6(this, NewPos, 7);	break;
                    case 16:MakeRef6(this, NewPos, 8);	break;
                    case  1:
                    case  3:
                    case  5:
                    case  7:
		    case  9:
                    case 11:
                    case 13:
                    case 15:
		    case 17:strcpy(ObjType,"~Ref"); break;
		    }
		  break;
	case 0xD6:if(subby<=5) Header_Footer6();
		  break;
	case 0xD7:switch (subby)
		    {
		    case 0: Footnote6(NewPos);		break;
		    case 1: strcpy(ObjType,"~Footnote");	break;
		    case 2: Endnote6(NewPos);		break;
		    case 3: strcpy(ObjType,"~EndNote");	break;
		    }
		  break;
	case 0xD8:switch (subby)
		    {
		    case  0:SetUserCounter();			break;
		    case  2:SetPgNum(this,6);			break;
		    case  7:SetFootnoteNum(this,6);		break;
		    case  8:SetEndnoteNum(this,6);		break;
		    }
		  break;

	case 0xDA:switch (subby)
		    {
		    case    0:UserCounter(NewPos);		break;
		    case    1:strcpy(ObjType,"~User Counter");break;

		    case    4:PageNumber6(this, NewPos);	break;
		    case    5:strcpy(ObjType, "~Pg Num");	break;

		    case  0xC:SkipNumber6(this,NewPos);
			      strcpy(ObjType,"!Par Num Disp");	break;
		    case  0xD:strcpy(ObjType,"!~Par Num Disp");	break;
		    case  0xE:FootnoteNumber6(NewPos);		break;
		    case  0xF:strcpy(ObjType,"~Footnote Num");	break;
		    case 0x10:EndnoteNumber6(this, NewPos);	break;
		    case 0x11:strcpy(ObjType,"~Endnote Num");	break;
		    }
		  break;
	case 0xDB:switch (subby)
		    {
		    case  0:IncUserCounter();			break;

		    case  2:IncCounterNum(this,"page");		break;
		    case  7:IncCounterNum(this,"footnote");	break;
		    case  8:IncCounterNum(this,"endnote");
			    if(!EndNotes) EndNotes=true; 	break;
		    }
		  break;
	case 0xDC:switch (subby)
		    {
		    case  0:DecUserCounter();			break;

		    case  2:DecCounterNum(this,"page");		break;
		    case  7:DecCounterNum(this,"footnote");	break;
		    case  8:DecCounterNum(this,"endnote");
			    if(!EndNotes) EndNotes=true;	break;
		    }
		  break;
	case 0xDD:switch (subby)
		    {
		    case 0x0:strcpy(ObjType,"!Style Begin On"); break;
		    case 0x1:strcpy(ObjType,"!Style Begin Off"); break;
	            case 0x2:strcpy(ObjType,"!Style End On"); break;
		    case 0x3:strcpy(ObjType,"!Style End Off"); break;
		    case 0x4:strcpy(ObjType,"!Par Style 1 Beg On"); break;
		    case 0x5:strcpy(ObjType,"!Par Style 1 Beg Off"); break;
		    case 0x6:strcpy(ObjType,"!Par Style 2 Beg On"); break;
		    case 0x7:strcpy(ObjType,"!Par Style 2 Beg Off"); break;
		    case 0x8:strcpy(ObjType,"!Par Style End On"); break;
		    case 0x9:strcpy(ObjType,"!Par Style End Off"); break;
		    case 0xA:strcpy(ObjType,"!Global on"); break;
		    case 0xB:strcpy(ObjType,"!Global off");break;
                    }
		  break;
	case 0xDF:if (subby<=2) Box6();
		  if (subby==0x3) HLine(this,6);
		  break;
	case 0xE0:switch (subby)
		    {
		    case 0x00:BackTab(this);		break;
		    case 0x11:Tab(this,6);		break;
		    case 0x30:Indent(this,6);		break;
		    case 0x40:Center(this);		break;
		    case 0x80:Flush_right(this,0);	break;
		    case 0x82:Flush_right(this,1);	break;
		    case 0xD1:strcpy(ObjType, "!Dec Tab");
			      putc(' ', strip);	break;
		    default:sprintf(ObjType,"!TAB %Xh",subby);
			    putc(' ', strip);
			    break;
		    }
		  break;
        case 0xE1:if(subby==0xC)
			{
			fseek(wpd,3,SEEK_CUR); //<flags>[NDelSize]
			Color(this,7);		break;
			}
		  break;
	case 0xF0:char_on_line = true;   /*Some character is placed on line */
		  if(attr.Closed_Depth!=attr.Opened_Depth)
			{
		        Open_All_Attr(attr,strip);
		        }

		  Rd_word(wpd, &Wchar);
		  sprintf(ObjType,"%u,%u", Wchar>>8, Wchar & 0xFF);

		  CharacterStr(this,Ext_chr_str(Wchar, this, ConvertCpg));

		  subby = fgetc(wpd);		// charset again
		  break;
	case 0xF1:Undo(NewPos);				break;
	case 0xF2:Attr_ON(this);			break;
	case 0xF3:Attr_OFF(this);			break;


	default:if(by>0x20 && by<=0x7f)
		 {
		 if(NativeCpg != NULL)
		   {
	           CharacterStr(this,Ext_chr_str(by,this,NativeCpg));
		   }
		 else
		   {	
                   if(RequiredFont==FONT_HEBREW)
                     {
		     if(by=='.')
                         {CharacterStr(this,"\\textrm{.}");break;}
                     if(by==',')
                         {CharacterStr(this,"\\textrm{,}");break;}
		     if(by==':')
                         {CharacterStr(this,"\\textrm{:}");break;}
                     if(by==';')
                         {CharacterStr(this,"\\textrm{;}");break;}
                     }
		   RequiredFont = FONT_NORMAL;
		   CharacterStr(this,Ext_chr_str(this->by,this,ConvertCpg));   /* Normal_char */
	           }
    		 break;
	         }
        }
     }

_LObjectError:
  if (log != NULL)
    {   /**/
    if (by==0xF0) fprintf(log, " [ExtChr %s] ", ObjType);
    else if (by >= ' ' && by <= 'z')
	         putc(by, log);
    else if(by==0x80) putc(' ', log);
    else if((by>0xC0)||(*ObjType != '\0'))
	{
        if(by>=0xF0)
          fprintf(log,_("\n%*sObject type:%3Xh length:%4u"),
		  recursion * 2,"", by, w);
        else
	  fprintf(log,_("\n%*sObject type:%3Xh subtype:%3Xh length:%4u"),
		  recursion * 2,"", by, subby, w);
	if (*ObjType != '\0')
		  fprintf(log, " [%s] ", ObjType);
	     else fprintf(log, "    ");
	if(*ObjType==0) UnknownObjects++;
	}
    }


  if (NewPos == 0)
	{
	if(by<0xD0) ActualPos++;	//Only one byte read - simple guess of new position
	       else ActualPos = ftell(wpd);
	return;
	}
  ActualPos = ftell(wpd);
  if (NewPos == ActualPos) return;
  fseek(wpd, NewPos, SEEK_SET);
  ActualPos = NewPos;
  NewPos = 0;
  /*these functions have fixed size - see table SizesC0*/
}


void TconvertedPass1_WP6::InitFilter60(void)
{
 filter[0] = set(set0_60,sizeof(set0_60)/sizeof(int));
 filter[1] = set(set1_60,sizeof(set1_60)/sizeof(int));
 filter[2] = set(set2_60,sizeof(set2_60)/sizeof(int));
 filter[3] = set(set3_60,sizeof(set3_60)/sizeof(int));
}


int TconvertedPass1_WP6::Dispatch(int FuncNo, const void *arg)
{
#ifdef DEBUG
  fprintf(log,"\n#TconvertedPass1_WP6::Dispatch(%d) ",FuncNo);fflush(log);
#endif

 switch(FuncNo)
   {
   case DISP_PROCESSKEY:
	 ProcessKey60();
	 return 0;

   case DISP_WRAPPER:		// Notification from OLE wrapper is discarded for now.
         return 0;

   case DISP_EXTRACT_LABEL:
         {
         ExtractCaptionLabel6((const TBox*)arg);
         return 0;
         }

   case DISP_DO_CAPTION:
         {
         DoCaption6((arg==NULL)?0:*(unsigned short*)arg);
         return 0;
         }
   }  

 if(err != NULL)
   {
   perc.Hide();
   fprintf(err, _("\nInternal Error: Unknown dispatch %d."),FuncNo);
   }
return(-1);
}


/***************************************/
/* This procedure provides all needed processing for the first pass*/
int TconvertedPass1_WP6::Convert_first_pass(void)
{
#ifdef DEBUG
  fprintf(log,"\n#TconvertedPass1_WP6::Convert_first_pass() ");fflush(log);
#endif
uint32_t fsize;

  InitFilter60();

  ConvertCpg = GetTranslator("wp6TOinternal");

  DocumentStart = ftell(wpd);
  fsize = FileSize(wpd);

  ResourceStart=0;
  if(DocumentStart>0x10)
    {
    fseek(wpd,14,SEEK_SET);
    Rd_word(wpd,&ResourceStart);
    if(ResourceStart==0) ResourceStart=0x10;
    if(ResourceStart<0x10) ResourceStart=0;
    fseek(wpd,DocumentStart,SEEK_SET);
    }

  perc.Init(ftell(wpd),fsize,_("First pass WP 6.x:"));

#ifndef FINAL
  CrackResources();
#endif

  ActualPos = ftell(wpd);
  while (ActualPos < fsize)
      {
      if(Verbosing >= 1)		//actualise a procentage counter
	      perc.Actualise(ActualPos);

      by = 0;
      ProcessKey60();
      }

  Finalise_Conversion(this);
  return(1);
}


#if 0
void Convert_pass1_WP6_encrypted(FILE *FileIn,FILE  *table, FILE *StripOut,FILE *LogFile,FILE *ErrorFile,void *Wrapper);
FFormatTranslator FormatWP6encrypted("WP6.x encrypted",Convert_pass1_WP6_encrypted);

void Convert_pass1_WP6_encrypted(FILE *FileIn,FILE  *table, FILE *StripOut,FILE *LogFile,FILE *ErrorFile,void *Wrapper)
{
 FileIn=FileIn;
 table=table;
 StripOut=StripOut;
 ErrorFile=ErrorFile;
 LogFile=LogFile;

//
// Sorry, I have no Idea how to decrypt WP6.x files!");
//     please help ............
//
RunError(0x203);
}
#endif


/*--------------------End of PASS1_6----------------------*/
