/******************************************************************************
 * program:     wp2latex                                                      *
 * function:    module for conversion HTML files into LaTeX 		      *
 * modul:       pass1htm.cc                                                   *
 * description: This module contains parser for HTML documents. It could be   *
 *		optionally compiled with WP2LaTeX package.		      *
 * licency:     GPL		                                              *
 ******************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#include"stringa.h"
#include"lists.h"
#include"dbllist.h"

#if defined(__UNIX__)||defined(__DJGPP__)
 #include <unistd.h>
#endif

#include"wp2latex.h"
#include"pass1xml.h"
#include "cp_lib/cptran.h"
#include "cp_lib/out_dir/html.trn"


list HTMLChars(Table_html,sizeof(Table_html)/sizeof(char *));

#define HTMLVersion "0.35"


typedef enum
{
    Itemize_NO_NUMBER,
    Itemize_NUMBER,
    Itemize_alpha,
    Itemize_ALPHA,
    Itemize_roman,
    Itemize_ROMAN
} E_ItemizeType;


/** Base class for HTML document conversion. */
class TconvertedPass1_HTML: public TconvertedPass1_XML
{    
public:
    list UnknownChars;

    virtual int Convert_first_pass(void);

    void ProcessKeyHTML(void);

    CpTranslator *ConvertUnicode;

protected:
    void ImageHTML(void);
    void ImageSVG(void);
    void IndentHTML(void);
    void ItemizeHTML(uint8_t ItemStyle);
    void LanguageHTML(const char *LangStr);
    void MetaHTML(void);
    void ScriptXML(void);
    void TableHTML(void);
    void TitleHTML(void);
    void StyleHTML(void);
};


/*Register translators here*/
TconvertedPass1 *Factory_HTML(void) {return new TconvertedPass1_HTML;}
FFormatTranslator FormatHTML("HTML",Factory_HTML);



typedef enum
{
  TAG_ATTR =	129,
  TAG_xATTR =	130,
  TAG_BR =	131,
  TAG_xP =	133,
  TAG_DD =	140,
  TAG_JUST =	134,
  TAG_H =	135,
  TAG_xH =	136,
  TAG_HR =	139,
  TAG_IMG =	142,
  TAG_xINDENT = 141,
  TAG_ITEMIZE =	144,
  TAG_META =	137,
  TAG_P =	132,
  TAG_SCRIPT =  138,
  TAG_TABLE =	143,
  TAG_HTML =	145,
  TAG_TITLE =	147,
  TAG_xTITLE =	148,
  TAG_STYLE =   149,
  TAG_DIRECTION=150,
  TAG_SVG =     151,

  TAG_HSPACE =  200,
  TAG_EXT_CHR = 201,
  TAG_UNKNOWN = 202,
} HTML_TAGS;


typedef struct
{
  const char *String;
  unsigned char Type;
  unsigned char SubType;
} TagStruct;


TagStruct OpenTags[] =
{
  {"B",      TAG_ATTR, 12},	//ATTR on bold
  {"BIG",    TAG_ATTR, 2},	//ATTR on large
  {"BR",     TAG_BR, 0},	//HRt
  {"CENTER", TAG_JUST, 0x82},	//Justification Center
  {"DD",     TAG_DD, 0},	//Indented definition
  {"H1",     TAG_H, 1},		//section level 1
  {"H2",     TAG_H, 2},		//section level 2
  {"H3",     TAG_H, 3},		//section level 3
  {"H4",     TAG_H, 4},		//section level 4
  {"H5",     TAG_H, 5},		//section level 5
  {"H6",     TAG_H, 6},		//section level 6
  {"HR",     TAG_HR, 0},	//horizontal line
  {"HTML",   TAG_HTML, 0},	//markup start
  {"I",      TAG_ATTR, 8},	//ATTR on italic
  {"IMG",    TAG_IMG, 0},	//Image
  {"LI",     TAG_ITEMIZE, 2},	//Start of item
  {"META",   TAG_META, 0},	//meta tag
  {"OL",     TAG_ITEMIZE, 4},	//Start of numbered list; type=1:numbers, A:uppercase letters, a:lowercase letters, I:Roman Numbers; start="50"
  {"P",      TAG_P, 0},		//new paragraph
  {"S",      TAG_ATTR, 13},	//ATTR on strike out
  {"SMALL",  TAG_ATTR, 3},	//ATTR on small
  {"SCRIPT", TAG_SCRIPT, 0},	//start SCRIPT
  {"STRONG", TAG_ATTR, 12},	//ATTR on bold
  {"STRIKE", TAG_ATTR, 13},	//ATTR on strike out variant
  {"STYLE",  TAG_STYLE, 0},	//STYLE
  {"SUB",    TAG_ATTR, 6},	//ATTR on subscript
  {"SUP",    TAG_ATTR, 5},	//ATTR on superscript
  {"SVG",    TAG_SVG, 0},	//SVG Image
  {"TABLE",  TAG_TABLE, 0},	//Start of the table
  {"TD",     TAG_TABLE, 4},	//Start of cell
  {"TH",     TAG_TABLE, 6},	//Start of head cell
  {"TITLE",  TAG_TITLE, 0},	//Start of title
  {"TR",     TAG_TABLE, 2},	//Start of row
  {"TT",     TAG_ATTR, 16},	//ATTR on typewriter
  {"U",      TAG_ATTR, 14},	//ATTR on underline
  {"UL",     TAG_ITEMIZE, 0}	//Start of itemize
};


TagStruct CloseTags[] =
{
  {"B",      TAG_xATTR,  12},	//ATTR off bold
  {"BIG",    TAG_xATTR,  2},	//ATTR off large
  {"CENTER", TAG_JUST,  0x81},	//End of center justification
  {"DD",     TAG_xINDENT, 0},	//End of indented definition
  {"DL",     TAG_xINDENT, 0},	//End of definition list
  {"H1",     TAG_xH,  1},	//section off level 1
  {"H2",     TAG_xH,  2},	//section off level 2
  {"H3",     TAG_xH,  3},	//section off level 3
  {"H4",     TAG_xH,  4},	//section off level 4
  {"H5",     TAG_xH,  5},	//section off level 5
  {"H6",     TAG_xH,  6},	//section off level 6
  {"LI",     TAG_ITEMIZE,  3},	//End of item
  {"OL",     TAG_ITEMIZE,  5},	//End of numbered list
  {"I",      TAG_xATTR,  8},	//ATTR off italic
  {"P",      TAG_xP, 0},	//end paragraph
  {"S",      TAG_xATTR,  13},	//ATTR off strike out
  {"SMALL",  TAG_xATTR,  3},    //ATTR off small
  {"SCRIPT", TAG_SCRIPT,  1},	//end SCRIPT
  {"STRONG", TAG_xATTR,  12},	//ATTR off bold
  {"STRIKE", TAG_ATTR,  13},	//ATTR on strike out variant
  {"STYLE",  TAG_STYLE, 1},	//STYLE
  {"SUB",    TAG_xATTR,  6},	//ATTR off subscript
  {"SUP",    TAG_xATTR,  5},	//ATTR off superscript
  {"SVG",    TAG_SVG,  1},
  {"TABLE",  TAG_TABLE,  1},	//End of Table
  {"TD",     TAG_TABLE,  5},	//End of cell
  {"TH",     TAG_TABLE,  7},	//End of head cell
  {"TITLE",  TAG_xTITLE, 0},	//End of title
  {"TR",     TAG_TABLE,  3},	//End of row
  {"TT",     TAG_xATTR,  16},	//ATTR off typewriter
  {"U",      TAG_xATTR,  14},	//ATTR off underline
  {"UL",     TAG_ITEMIZE,  1},	//End of itemize
};



#define PAPER_SIZE	210.0f
#define PagePixels 800.0f
void TconvertedPass1_HTML::ImageHTML(void)
{
#ifdef DEBUG
  fprintf(log,"\n#ImageHTML() ");fflush(log);
#endif
TBox Box;
int i;
const char *FileName=NULL;
char *str;
unsigned char terminator;
string NewFileName;

  initBox(Box);
  Box.Width = -1; 		// Undefined, use default 100mm
  Box.Image_type=0;		// Image on disk
  Box.AnchorType = 0; 		// 0-Paragraph, 1-Page, 2-Character
  Box.HorizontalPos=2;		// 0-Left, 1-Right, 2-Center, 3-Full

  if((i=TAG_Args IN "src")>=0 || (i=TAG_Args IN "SRC")>=0)
  {
    FileName = TAG_Args.Member(i,1);
    if(FileName!=NULL)
    {
      for(i=0; i<sizeof(MimeList)/sizeof(TMimeItem); i++)
      {
        if(!strncmp(FileName,MimeList[i].MimeType,MimeList[i].TypeLen))
        {
          NewFileName = MergePaths(OutputDir,RelativeFigDir) + GetSomeImgName(MimeList[i].ImageExt);
          FileName += MimeList[i].TypeLen + 1;
          break;
        }
      }

      if(NewFileName.length()>0)
      {      
        FILE *F = fopen(NewFileName(),"wb");
        if(F)
        {
          base64_decode(FileName, F);
          fclose(F);
        }
        else
        {
          if(err != NULL)
          {
            perc.Hide();
	    fprintf(err,_("\nError: Cannot create image file: \"%s\"."),NewFileName());
          }
        }
        FileName = NewFileName();
      }
    }
  }

  if((i=TAG_Args IN "width")>=0 || (i=TAG_Args IN "WIDTH")>=0)
  {
    str=TAG_Args.Member(i,1);
    switch(sscanf(str,"%f%c",&Box.Width,&terminator))
    {
      case 0: terminator=255;break;
      case 1: terminator=0;break;
      case 2: break;
      default:terminator=255;break;
    }
    switch(terminator)
    {
      case 0:Box.Width *= PAPER_SIZE/PagePixels;
		 break;					//normal
      case '%':Box.HorizontalPos=4;
		 if(Box.Width<=0) Box.HorizontalPos=3;
		 break;					//percentage
      default: break;				//nothing
    }
  }
  if(FileName==NULL) FileName="dummy";

  ImageWP(this, FileName, Box);

  if(!NewFileName.isEmpty() && SaveWPG<0)
  {
    unlink(NewFileName());
  }

return;
}


void TconvertedPass1_HTML::ImageSVG(void)
{
#ifdef DEBUG
  fprintf(log,"\n#ImageSVG() ");fflush(log);
#endif
TBox Box;
const char *FileName=NULL;
string NewFileName;
unsigned char OldFlag;
long SVGStart = ActualPos;
long SVGEnd;
char OldEnvir;

  OldFlag = flag;
  OldEnvir = envir;
  flag = Nothing;
  recursion++;

  ReadXMLTag();
  while(!feof(wpd))
  {
/*	if(by==0 && (subby==10 || subby==13))
		{
		subby=' ';	// remove \n from cell text
		} */
    ProcessKeyHTML();
    if(by==TAG_SVG)
    {
      if(subby==1) break; /*End of SVG*/
    }

    ReadXMLTag();
  }
  flag = OldFlag;
  envir = OldEnvir;
  recursion--;
  SVGEnd = ftell(wpd);

  initBox(Box);
  Box.Width = -1; 		// Undefined, use default 100mm
  Box.Image_type=0;		// Image on disk
  Box.AnchorType = 0; 		// 0-Paragraph, 1-Page, 2-Character
  Box.HorizontalPos=2;		// 0-Left, 1-Right, 2-Center, 3-Full

  NewFileName = MergePaths(OutputDir,RelativeFigDir) + GetSomeImgName(".svg");
  if(NewFileName.length()>0)
  {
    FILE *F = fopen(NewFileName(),"wb");
    if(F)
    {
      fseek(wpd,SVGStart,SEEK_SET);
      CopyFile(F, wpd, SVGEnd-SVGStart);

      fclose(F);
    }
    else
    {
      if(err != NULL)
      {
        perc.Hide();
        fprintf(err,_("\nError: Cannot create image file: \"%s\"."),NewFileName());
      }
      NewFileName.erase();
    }
  }

  if(NewFileName.isEmpty()) NewFileName="dummy";

  ImageWP(this, NewFileName(), Box);

  if(NewFileName.length()>0 && SaveWPG<0)
    {
    unlink(NewFileName());
    }
}


void TconvertedPass1_HTML::IndentHTML(void)
{
#ifdef DEBUG
  fprintf(log,"\n#IndentHTML() ");fflush(log);
#endif
  tabpos[0] = 470 + WP_sidemargin;
  Indent(this,0);
}


void TconvertedPass1_HTML::ItemizeHTML(uint8_t ItemStyle)
{
#ifdef DEBUG
  fprintf(log,"\n#ItemizeHTML() ");fflush(log);
#endif
unsigned char OldFlag;
char OldEnvir;
long FilePos;

  FilePos = ftell(wpd);
  OldFlag = flag;
  OldEnvir = envir;
  flag = Nothing;
  AttrOff(Arabic_Font);

  recursion++;

  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) //  if(char_on_line>=-1)
	{
	NewLine(this);
	}
  envir='!';
  fputc('%', table);fputc('%', strip);
  NewLine(this);

  envir = ' ';

  if(OldEnvir=='B') fputs("\\vbox{",strip); //protect itemize inside table

  if(ItemStyle>0)
  {
    if(enumitem<0) ItemStyle=Itemize_NO_NUMBER;		// Cannot turn on "enumitem".
    else 
      if(enumitem==0) enumitem=1;
  }
  if(ItemStyle==0)
    fputs("\\begin{itemize}",strip);
  else
  {
    fputs("\\begin{enumerate}",strip);  //[label=(\roman*)]"); // (\roman*) (a)
    switch(ItemStyle)
    {
      case Itemize_alpha: fputs("[label=(a)]",strip); break;
      case Itemize_ALPHA: fputs("[label=(A)]",strip); break;
      case Itemize_roman: fputs("[i]",strip); break;	// label=(\roman*)
      case Itemize_ROMAN: fputs("[I]",strip); break;	// label=(\Roman*)
    }
  }

  char_on_line = false;
  nomore_valid_tabs = false;
  rownum++;
  Make_tableentry_attr();
  latex_tabpos = 0;

	/*Process all content of the table */
  flag=OldFlag;
  fseek(wpd,FilePos,SEEK_SET);
  ReadXMLTag();
  while(!feof(wpd))
	{
/*	if(by==0 && (subby==10 || subby==13))
		{
		subby=' ';	// remove \n from cell text
		} */
	ProcessKeyHTML();
	if(by==TAG_ITEMIZE)
		{
		if(subby==1 || subby==5) break; /*End of itemize*/
		if(subby==2) fprintf(strip, "\\item ");
		}

	ReadXMLTag();
	}

  AttrOff(Arabic_Font);  
  fprintf(strip, (ItemStyle==0) ? "\\end{itemize}" : "\\end{enumerate}");
  if(OldEnvir=='B') fprintf(strip, "}");
  if(char_on_line <= FIRST_CHAR_MINIPAGE)  // Left one enpty line for ending enviroment.
	{
	fputc('%', table);fputc('%', strip);
	NewLine(this);
	}
  envir = '^';		//Ignore enviroments after table
  fputc('%', table);
  NewLine(this);
  char_on_line = -10;		// stronger false;

  recursion--;

  flag = OldFlag;
  envir = OldEnvir;
  TAG = "ITEMIZE";
strcpy(ObjType, "Itemize Start");
}


void TconvertedPass1_HTML::LanguageHTML(const char *LangStr)
{
 if(LangStr==NULL) return;
 if(*LangStr==0) return;

 if(!strcmp(LangStr,"en-US"))
 { 
   Language(this,'U'+256*'S');
 }
}


/** This function extracts some information from meta HTML tag */
void TconvertedPass1_HTML::MetaHTML(void)
{
#ifdef DEBUG
  fprintf(log,"\n#MetaHTML() ");fflush(log);
#endif
  int i;
  const char *content, *charset;
  string translator;

  strcpy(ObjType, "Meta");

  if((i=TAG_Args IN "content")>=0 || (i=TAG_Args IN "CONTENT")>=0)
  {
    content=TAG_Args.Member(i,1);
    if(content!=NULL)
    {
      charset = strstr(content,"CHARSET");
      if(charset==NULL) charset = strstr(content,"charset");
      if(charset!=NULL)
      {
        charset+=7;
        while(isspace(*charset)) charset++;
        if(*charset++ == '=')
        {
          while(isspace(*charset)) charset++;
          SelectTranslator(charset);
        }
      }
    }
  }

  if((i=TAG_Args IN "charset")>=0 || (i=TAG_Args IN "CHARSET")>=0)
  {
    charset = TAG_Args.Member(i,1);
    if(charset==NULL) return;
    while(isspace(*charset)) charset++;
    SelectTranslator(charset);
  }
}


void TconvertedPass1_HTML::ScriptXML(void)
{
#ifdef DEBUG
  fprintf(log,"\n#ScriptXML() ");fflush(log);
#endif
unsigned char OldFlag;

OldFlag = flag;
flag = Nothing;

do {
   TAG.erase();
   ProcessKeyHTML();
   if(by==TAG_SCRIPT && subby==1) break;
   }while(!feof(wpd));

flag = OldFlag;
}


void TconvertedPass1_HTML::TableHTML(void)
{
#ifdef DEBUG
  fprintf(log,"\n#TableHTML() ");fflush(log);
#endif
unsigned char OldFlag;
char OldEnvir;
long FilePos;
int i, FieldCount=0;
char State=0;
char *Align;
char *FieldPos=NULL,Alignment;

FilePos = ftell(wpd);
OldFlag = flag;
OldEnvir = envir;
flag = Nothing;
recursion++;

do {
   TAG.erase();
   ProcessKeyHTML();
   if(by==TAG_TABLE)
     {
     if(subby == 0) break;			// <TABLE>
     if(subby == 1) break;			// </TABLE>
     if(subby == 2)				// <TR>
	  {
	  if(State==0) {State++;continue;}
	  if(FieldCount==0) continue;
	  break;
	  }
     if(subby == 3) break;			// </TR>
     if(subby == 4 || subby == 6)	// <TD> or <TH>
	  {
	  if(State==0) State++;
	  Alignment='l';
	  if((i=TAG_Args IN "align")>=0 || (i=TAG_Args IN "ALIGN")>=0)
	      {
	      Align=TAG_Args.Member(i,1);
	      if(!StrCmp(Align,"left"))  Alignment='l';
	      if(!StrCmp(Align,"right")) Alignment='r';
	      if(!StrCmp(Align,"center"))Alignment='c';
	      }
	  if(FieldPos==NULL) FieldPos=(char *)malloc(100);
	  if(FieldCount<100 && FieldPos!=NULL)
		{
		FieldPos[FieldCount]=Alignment;
		}
	  FieldCount++;
	  }
     }
   }while(!feof(wpd));


  if(FieldCount>0)
    {
    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) //  if(char_on_line>=-1)
	{
	NewLine(this);
	}
    envir='!';
    fputc('%', table);fputc('%', strip);
    NewLine(this);

    envir = 'B';

    fprintf(strip, "{|");
    for(i = 0; i < FieldCount; i++)
	{
	Alignment='l';
	if(FieldCount<100 && FieldPos!=NULL) Alignment=FieldPos[i];
	fprintf(strip, "%c|",Alignment);
	}
    putc('}', strip);

    char_on_line = false;
    nomore_valid_tabs = false;
    rownum++;
    Make_tableentry_attr();
    latex_tabpos = 0;
    }

	/*Process all content of the table */
  flag=OldFlag;
  fseek(wpd,FilePos,SEEK_SET);
  ReadXMLTag();
  while(!feof(wpd))
	{
	if(by==0 && (subby==10 || subby==13))
		{
		subby=' ';	/* remove \n from cell text */
		}
	ProcessKeyHTML();
	if(by==TAG_TABLE && subby==1) break; /*End of table*/

	ReadXMLTag();
	}
  if(char_on_line <= FIRST_CHAR_MINIPAGE)  // Left one enpty line for ending enviroment.
	{
	fputc('%', table);fputc('%', strip);
	NewLine(this);
	}
  envir='^';		//Ignore enviroments after table
  fputc('%', table);
  NewLine(this);
  char_on_line = FIRST_CHAR_MINIPAGE;	// stronger false;

  recursion--;

  flag = OldFlag;
  envir = OldEnvir;
  TAG = "TABLE";
strcpy(ObjType, "Table Start");
}


void TconvertedPass1_HTML::StyleHTML(void)
{
#ifdef DEBUG
  fprintf(log,"\n#StyleHTML() ");fflush(log);
#endif
unsigned char OldFlag = flag;
 
 flag = Nothing;

 do {
    TAG.erase();
    ProcessKeyHTML();
    if(by==TAG_STYLE && subby==1) break;
    } while(!feof(wpd));

 //if(TotalSummary>0) NewLine(this);
 flag = OldFlag;
 strcpy(ObjType, "Style");
}


void TconvertedPass1_HTML::TitleHTML(void)
{
#ifdef DEBUG
  fprintf(log,"\n#TitleHTML() ");fflush(log);
#endif
unsigned char OldFlag = flag;
 
 flag = HeaderText;

 AttrOff(Arabic_Font);
 fprintf(strip, "\\title{");
 do {
    TAG.erase();
    ProcessKeyHTML();
    if(by==TAG_xTITLE) break;
    } while(!feof(wpd));
 AttrOff(Arabic_Font);
 fprintf(strip, "}");

 //if(TotalSummary>0) NewLine(this);
 flag = OldFlag;
 strcpy(ObjType, "Title Start");
}


void TconvertedPass1_HTML::ProcessKeyHTML(void)
{
#ifdef DEBUG
  fprintf(log,"\n#ProcessKeyHTML() ");fflush(log);
#endif
 string TAG;
 const char *tag = NULL;
 uint8_t by, subby;
 int i;

 *ObjType = 0;
 if(this->TAG.isEmpty()) ReadXMLTag();
 by = this->by;
 subby = this->subby;

 switch(by)
	{
	case XML_char:
              switch(this->subby)
	      {
	        case 10:
	        case 13:by=128;break; //CR
	        case  9:strcpy(this->ObjType, "!Tab");
	        case 32:by=32; break;  //Space
                default: if(RequiredFont==FONT_HEBREW)
		        {
		          if(by=='.')
                            {TAG="\\textrm{.}";by=XML_extchar;break;}
                          if(by==',')
                            {TAG="\\textrm{,}";by=XML_extchar;break;}
		          if(by==':')
                            {TAG="\\textrm{:}";by=XML_extchar;break;}
                          if(by==';')
                            {TAG="\\textrm{;}";by=XML_extchar;break;}
                        }
                        if(Font>=FONT_CYRILLIC && Font<=FONT_ARABIC)
                        {
                          RequiredFont = FONT_NORMAL;
                        }
                        break;
              }
	      break;					//Normal character

	case XML_extchar:
	case XML_badextchar:
            TAG = copy(this->TAG,1,length(this->TAG)-2);   //Extended chatacter &xxx;
            tag = TAG();
            if(TAG.length()<=0) break;	    
	    if(TAG=="nbsp")	{by=TAG_HSPACE;break;}  	//Hard space
            if(TAG=="lrm")	{by=TAG_DIRECTION;break;}

            if(*tag=='#' && isdigit(tag[1]))
                {
                by = TAG_EXT_CHR;
                i = atoi(tag+1);
		tag = Ext_chr_str(i, this, ConvertUnicode);
                break;
                }

	    if((i=(TAG() IN HTMLChars))>0)
		{
		i--;
                by = TAG_EXT_CHR;
		tag = Ext_chr_str(i, this, ConvertHTML); // Translate HTML character set to internal charset.
		}
             else
                {
                by = TAG_UNKNOWN;
                if(!(TAG() IN this->UnknownChars))
                  {
                  this->UnknownChars += TAG();
                  if(err != NULL)
                    {
                    perc.Hide();
	            fprintf(err,_("\nError: Unknown translation for character \"&%s;\"."),TAG());
                    }
                  }
                }
//	       fprintf(strip," !!!&%s; ",TAG.ch);
	     break;

	case XML_tag:
        case XML_closedtag:
               TAG = copy(this->TAG,1,length(this->TAG)-2);	//Normal tag <xxx>
	       if(TAG.length() <= 0) break;
               for(i=0; i<sizeof(OpenTags)/sizeof(TagStruct); i++)
                 {
                 if(TAG==OpenTags[i].String)
                   {
                     by = OpenTags[i].Type;
                     subby = OpenTags[i].SubType;
                     break;
                   }
                 }
	       break;

	case XML_closetag:
	case XML_closedclosetag:
               TAG = copy(this->TAG,2,length(this->TAG)-3);	//Closing tag </xxx>
	       if(TAG.length() <= 0) break;
               for(i=0; i<sizeof(CloseTags)/sizeof(TagStruct); i++)
                 {
                 if(TAG==CloseTags[i].String)
                   {
                     by = CloseTags[i].Type;
                     subby = CloseTags[i].SubType;
                     break;
                   }
                 }
	       break;

	case XML_comment:  			//comment
	       break;
        case XML_CDATA:
               break;
	}

  this->by = by;
  this->subby = subby;
  if(this->flag<Nothing)
    switch(by)
	{
	case XML_char:  tag = Ext_chr_str(subby,this,ConvertCpg);
	                CharacterStr(this,tag);
                        break;		//Normal character
        case XML_CDATA:
	case XML_comment:CommentXML();
                        break;
	case XML_unicode:CharacterStr(this,this->TAG);
	                break;		//Already expanded unicode character

	case 32:        putc(' ', strip);   /*soft space*/
		        break;

	case 128:       if(TablePos!=1 && TablePos!=3)
		          if(char_on_line)
                            SoftReturn(this);
                        break;
	case TAG_ATTR:	attr.AttrOn(subby); break;
	case TAG_xATTR:	AttrOff(subby);     break;
	case TAG_BR:	HardReturn(this);        break;
	case TAG_P:	if(char_on_line) HardReturn(this);  //Paragraph on
			SoftReturn(this);
			break;
	case TAG_xP:	if(char_on_line) HardReturn(this);  //Paragraph off
			break;
	case TAG_JUST:	Justification(this,subby);break;
	case TAG_H:	StartSection(this,-subby);break;
	case TAG_xH:	EndSection(this,-subby);  break;
	case TAG_META:	MetaHTML();		  break;
	case TAG_SCRIPT:ScriptXML();		  break;
	case TAG_HR:	HLine(this,-16);	  break;
	case TAG_DD:	IndentHTML();	break;
	case TAG_DIRECTION: strcpy(ObjType, "!Direction"); break;
	case TAG_xINDENT:End_of_indent(this);	break;
	case TAG_IMG:	ImageHTML();		break;
	case TAG_TABLE: switch(subby)
		   {
		   case 0:TableHTML(); TablePos=1;break;
		   case 1:EndTable(this); TablePos=0; break;
		   case 2:RowTable(this); TablePos|=2;break;
		   case 3:TablePos&=~2;break;
		   case 4:
		   case 6:CellTable(this);TablePos|=4;break;
		   case 5:
		   case 7:TablePos&=~4;break;
		   }
		 break;
	case TAG_ITEMIZE: switch(subby)
		   {
		   case 0:ItemizeHTML(Itemize_NO_NUMBER);break;
                   case 4:if((i=TAG_Args IN "type")>=0)		// 1:numbers, A:uppercase letters, a:lowercase letters, I:Roman Numbers; start="50"
                          {
                            const char *OlTypeS=TAG_Args.Member(i,1);
                            if(strcmp(OlTypeS,"1")) ItemizeHTML(Itemize_NO_NUMBER);
			    else if(strcmp(OlTypeS,"a")) ItemizeHTML(Itemize_alpha);
			    else if(strcmp(OlTypeS,"A")) ItemizeHTML(Itemize_ALPHA);
		            else if(strcmp(OlTypeS,"i")) ItemizeHTML(Itemize_roman);
		            else if(strcmp(OlTypeS,"I")) ItemizeHTML(Itemize_ROMAN);
			    else ItemizeHTML(Itemize_NO_NUMBER);
                          }
                          else
                            ItemizeHTML(Itemize_NO_NUMBER);
		          }
		          break;
	case TAG_HTML:
		{
		if((i=TAG_Args IN "lang")>=0 || (i=TAG_Args IN "LANG")>=0)
		  {		  
		  LanguageHTML(TAG_Args.Member(i,1));
		  if(ConvertCpg==NULL) SelectTranslator("iso_8859_1");
		  }

		break;
		}

	case TAG_SVG:   ImageSVG(); break;
	case TAG_TITLE: TitleHTML(); break;

	case TAG_STYLE: StyleHTML(); break;

	case TAG_HSPACE:fputc('~', strip); strcpy(ObjType, " ");
		 break;
	case TAG_EXT_CHR:CharacterStr(this,tag);break;
        case TAG_UNKNOWN:fputc(' ', strip);
                 break;
	}


 this->by = by;
 this->subby = subby;
 if(log != NULL)
    {   /**/
    switch(by)
      {
      case 128: fputc('\n',log); break;

      case TAG_HSPACE:
      case ' ': fputc(' ',log); break;

      case TAG_EXT_CHR:
      case XML_char:
 	        if(tag)
	          fprintf(log,"%s",tag);
                else
	          fprintf(log,"!%c",this->subby);
                break;

      case TAG_UNKNOWN:
               fprintf(log,"!%s",this->TAG());
               break;

      default:
	        fprintf(log, "\n%*s [%s %s]   ",
		        recursion * 2, "", this->TAG(), ObjType);
                //	if(*ObjType==0) UnknownObjects++;
                break;
      }
    }

 ActualPos = ftell(wpd);
}


int TconvertedPass1_HTML::Convert_first_pass(void)
{
#ifdef DEBUG
  fprintf(log,"\n#Convert_pass1_HTML() ");fflush(log);
#endif
uint32_t fsize;

  if(Verbosing >= 1)
     printf(_("\n>>>HTML2LaTeX<<< Conversion program: From HTML to LaTeX Version %s\n"
	      "      Made by J.Fojtik  (Hosted on WP2LaTeX :))))\n\n"),
	    HTMLVersion);

  ConvertHTML = GetTranslator("htmlTOinternal");
  ConvertUnicode = GetTranslator("unicodeTOinternal");
  CharReader = &ch_fgetc;

  DocumentStart=ftell(wpd);

  TablePos=0;

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

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

      TAG.erase();
      ProcessKeyHTML();
      }

  Finalise_Conversion();
  return(1);
}
