/******************************************************************************
 * 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.28"


/** 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 IndentHTML(void);
    void ItemizeHTML(void);
    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_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
  {"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
  {"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
  {"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
  {"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
};


typedef struct
{
  const char* MimeType;
  int TypeLen;
  const char *ImageExt;
} TMimeItem;

// See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types
const TMimeItem MimeList[] =
{
  {"data:image/bmp;base64", 21, ".bmp"},
  {"data:image/gif;base64", 21, ".gif"},
  {"data:image/jpg;base64", 21, ".jpg"},
  {"data:image/jpeg;base64",22, ".jpg"},
  {"data:image/png;base64", 21, ".png"},
  {"data:image/svg+xml;base64", 25, ".svg"},
  {"data:image/tiff;base64",22, ".tif"},
  {"data:image/tif;base64", 21, ".tif"}
};


static inline bool is_base64(BYTE c) 
{
 return (isalnum(c) || (c == '+') || (c == '/'));
}


// static const char *base64_chars = 
//             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
//             "abcdefghijklmnopqrstuvwxyz"
//             "0123456789+/";

static inline BYTE FindBase64(char ch)
{
  if(ch>='A' && ch<='Z') return ch - 'A';
  if(ch>='a' && ch<='z') return ch - 'a' + 'Z'-'A'+1;
  if(ch>='0' && ch<='9') return ch - '0' + 2*('Z'-'A')+2;
  if(ch=='+') return 2*('Z'-'A')+2 + 10;  
  if(ch=='/') return 2*('Z'-'A')+2 + 11;
return 0xFF;
}


void base64_decode(const char *encoded_string, FILE *FOut) 
{
int in_len = strlen(encoded_string);
int i = 0;
int in_ = 0;
BYTE char_array_4[4], char_array_3[3];

  while(in_len-- && (encoded_string[in_]!='=') && is_base64(encoded_string[in_])) 
    {
    char_array_4[i++] = FindBase64(encoded_string[in_++]);

    if(i==4) 
      {
      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

      fwrite(char_array_3,1,3,FOut);      
      i = 0;
      }
    }

  if(i) 
  {
    memset(char_array_4+i, FindBase64(0), 4-i);    

    char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
    char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
    char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
    
    fwrite(&char_array_3, 1, i-1, FOut);
  }

  return;
}


#define PAPER_SIZE	210.0
#define PagePixels 800.0
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.length()>0 && SaveWPG<0)
    {
    unlink(NewFileName());
    }

return;
}


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(void)
{
#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;
  recursion++;

  line_term = 's';   /* Soft return */
  if(char_on_line == -20)    /* Left one enpty line for new enviroment */
	{
	fputc('%', table);fputc('%', strip);
	NewLine(this);
	}
  if(char_on_line>=true) //  if(char_on_line>=-1)
	{
	NewLine(this);
	}
  envir='!';
  fputc('%', table);fputc('%', strip);
  NewLine(this);

  envir = ' ';

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

  char_on_line = false;
  nomore_valid_tabs = false;
  rownum++;
  Make_tableentry_attr(this);
  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) break; /*End of itemize*/
		if(subby==2) fprintf(strip, "\\item ");
		}

	ReadXMLTag();
	}

  fprintf(strip, "\\end{itemize}");
  if(OldEnvir=='B') fprintf(strip, "}");
  if(char_on_line <= -10)    /* 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) return;
	charset = strstr(content,"CHARSET");
	if(charset==NULL) charset = strstr(content,"charset");
	if(charset==NULL) return;
	charset+=7;
	while(*charset==' ') charset++;
	if(*charset++!='=') return;

	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 == -20)    /* Left one enpty line for new enviroment */
	{
	fputc('%', table);fputc('%', strip);
	NewLine(this);
	}
    if(char_on_line>=true) //  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(this);
    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 <= -10)    /* 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="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;

 fprintf(strip, "\\title{");
 do {
    TAG.erase();
    ProcessKeyHTML();
    if(by==TAG_xTITLE) break;
    } while(!feof(wpd));
 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;
 BYTE by, subby;
 int i;

 *ObjType = 0;
 if(this->TAG=="") 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_HEBREW || Font==FONT_CYRILLIC)
                        {
                          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:
               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:
               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:	AttrOn(attr,subby); break;
	case TAG_xATTR:	AttrOff(this,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();break;
		   }
		 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_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
DWORD 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(this);
  return(1);
}
