/******************************************************************************
 * program:     wp2latex                                                      *
 * function:    convert WordPerfect 5.x,6,7,8.x files into LaTeX              *
 * modul:       pass2.cc                                                      *
 * description: This modul contains functions for second pass. In the second  *
 *              pass the text file stripped from the WP binary file will be   *
 *              completed with the information of the binary table file which *
 *              contains additional information about environments.           *
 * licency:     GPL		                                              *
 ******************************************************************************/

//Ukoly: podivat se na: \\justified \\raggedright

#include <string.h>
#include <stdio.h>
#include <math.h>
#include <ctype.h>

#include <strings.h>
#include <lists.h>
#include "wp2latex.h"

extern list Counters,UserLists;


typedef struct TLinePass2
  {
  string Lstring;
  boolean new_tabset;
  int tabent_num_of_tabs;
  char envir, line_term;
  char Columns;
  signed char Empty;
  unsigned char LineFlag;

  attribute attr;

  boolean InhibitBsBslash;

  int ind_leftmargin;
  signed char Indent_Level;
  } TLinePass2;

typedef long pchar;


typedef struct TconvertedPass2 
{
  Percentor perc;
  long rownum;
  BYTE LangCount;

  TLinePass2 Lines[4];

  boolean underline, illegal_argument, just_envir_closed;

  int num_of_tabs;
  char Col2Break;			///< Amount of \columnbreak inside multicol environment
  unsigned short tabpos[40];

  unsigned int tabent_tabpos[4][40];

  short int pre, cur, next, next2;
  FILE *table;
  FILE *Strip, *LaTeX;
  FILE *log,*err;
  unsigned int  LineSpacing;
} TconvertedPass2;



void Open_All_Attr(attribute & a, string & s)
{
s="";
while(a.Opened_Depth<a.Closed_Depth)
	{
        s+=Open_com[a.stack[a.Opened_Depth++]];
        }
}

void Close_All_Attr(attribute & a, string & s)
{
s="";
while(a.Opened_Depth>0)
	{
	s += Close_com[a.stack[--a.Opened_Depth]];
	}
}


static void Read_TableEntry(TconvertedPass2 *cq2, short n)
{
#ifdef DEBUG
  fprintf(cq2->log,"\n#Read_TableEntry(%d) ",(int)n);fflush(cq2->log);
#endif
WORD w;
BYTE b;
int j;
TLinePass2 *pCurLine;

  pCurLine=&cq2->Lines[n];	/* Begin met one schone lei die dan door this procedure verder wordt opgevuld. */
  pCurLine->envir = ' ';
  pCurLine->LineFlag = 0;
  pCurLine->new_tabset = false;

  InitAttr(pCurLine->attr);

  if (feof(cq2->table)) return;

  b = 0;
  while(b != 0xff)
    {
    if(fread(&b, 1, 1, cq2->table)==0) // We are probaly at the end of the file
		break;

    switch (b)
	{
	case 'B':pCurLine->envir = 'B';    break;
	case 'C':pCurLine->envir = 'C';    break;
	case 'L':pCurLine->envir = 'L';    break;
	case 'R':pCurLine->envir = 'R';    break;
	case 'T':pCurLine->envir = 'T';    break;
	case 'q':pCurLine->envir = 'q';    break;
	case 'Q':pCurLine->envir = 'Q';    break;
	case 'I':
	case 'i':pCurLine->envir=b;
		 Rd_word(cq2->table, &w);
		 pCurLine->ind_leftmargin=w;
		 fread(&pCurLine->Indent_Level, 1, 1, cq2->table);
		 break;

	case 'S':pCurLine->new_tabset = true;
		 fread(&b, 1, 1, cq2->table);
		 pCurLine->tabent_num_of_tabs = b;
		 for (j = 0; j < b; j++)
		     {
		     Rd_word(cq2->table, &w);
		     cq2->tabent_tabpos[n][j] = w;
		     }
		 break;

       case 'l': Rd_word(cq2->table, &w);
		 if(w!=cq2->LineSpacing)
			    {
			    fprintf(cq2->LaTeX,"\\baselineskip=%2.2fex ",float(w)/128);
			    cq2->LineSpacing=w;
			    }
		  break;

	case 'M':fread(&pCurLine->Columns, 1, 1, cq2->table);	break;

	case 'h':
	case 's':
	case 'P':
	case 'p':pCurLine->line_term = b;
		 break;

	case '%':pCurLine->LineFlag |= 1;  break; /* Useless comment line */

	case '!':pCurLine->envir = '!';    break; /* Ignore enviroment before */
	case '^':pCurLine->envir = '^';    break; /* Ignore enviroment after */

		    // Read all opened attributes into attr structure
	case 0xF0:fread(&b, 1, 1, cq2->table);
		  pCurLine->attr.Opened_Depth=pCurLine->attr.Closed_Depth = b;
		  for (j = 0; j < b; j++)
			fread(&(pCurLine->attr.stack[j]), 1, 1, cq2->table);
		  b=0xF0;
		  break;

	case 0xFF:
	case 10:
	case 13:break;               //do nothing

	default:if(cq2->err!=NULL)
		    fprintf(cq2->err,_("\nError: Bad command '%c' in table file!"),b);
	}
  }
}


static void UsePackage(TconvertedPass2 *cq2,const char *PkgName)
{
  fprintf(cq2->LaTeX, "\\usepackage{%s}\n",PkgName);
}


/** -- Make the standard-heading for one latex-file -- */
static void Latex_head(TconvertedPass2 *cq2)
{
#ifdef DEBUG
  fprintf(cq2->log,"\n#Latex_head() ");fflush(cq2->log);
#endif
int i;
string TeX_RelativeFigDir;

  fprintf(cq2->LaTeX,_("%% This file was created by the WP2LaTeX program version: %s \n"), version );
  if(LaTeX_Version<0x300)
    {
    fprintf(cq2->LaTeX, "\\documentstyle[11pt,");
    if(Amssymb>=1)  fprintf(cq2->LaTeX, "amssymb,");
    if(MakeIdx>=1)  fprintf(cq2->LaTeX, "makeidx,");
    if(Ulem>=1)     fprintf(cq2->LaTeX, "ulem,");
    if(Rotate>=1)   fprintf(cq2->LaTeX, "rotate,");
    if(LineNo>=1)   fprintf(cq2->LaTeX, "lineno,");
    fprintf(cq2->LaTeX, "wp2latex");
    if(twoside)     fprintf(cq2->LaTeX, ",twoside");
    if(Columns==2)  fprintf(cq2->LaTeX, ",twocolumn");
    if(Columns>2)   fprintf(cq2->LaTeX, ",multicol");
    if(EndNotes>=1) fprintf(cq2->LaTeX, ",endnotes");
    if(Cyrillic>=1) fprintf(cq2->LaTeX, ",cyrillic");
    if(cjHebrew>=1) fprintf(cq2->LaTeX, ",cjhebrew");
    if(InputPS==(IMG_InputPS|1))  fprintf(cq2->LaTeX, ",InputPS");
    if(InputPS==(IMG_graphicx|1)) fprintf(cq2->LaTeX, ",graphicx");
    if(InputPS==(IMG_epsfig|1))   fprintf(cq2->LaTeX, ",epsfig");
    if(InputPS==(IMG_graphics|1)) fprintf(cq2->LaTeX, ",graphics");
    if(Wasy>=1)     fprintf(cq2->LaTeX, ",wasyfont");
    if(textcomp>=1) fprintf(cq2->LaTeX, ",textcomp");
    if(Bbm>=1)      fprintf(cq2->LaTeX, ",bbm");
    if(Rsfs>=1)     fprintf(cq2->LaTeX, ",mathrsfs");
    if(FancyHdr>=1) fprintf(cq2->LaTeX, ",fancyhdr");
    if(LongTable>=1)fprintf(cq2->LaTeX, ",longtable");
    if(pifont>=1)   fprintf(cq2->LaTeX, ",pifont");
    for(int lng=0;lng<sizeof(LangTable)/sizeof(LangItem);lng++)
      {
      if(LangTable[lng].UseLang>=1)
	{
	fprintf(cq2->LaTeX, ",%s",LangTable[lng].LangDesc);
	cq2->LangCount++;
	}
      }       
    fprintf(cq2->LaTeX, "]{article}\n\n");
    }
  else
    {
    fprintf(cq2->LaTeX, "\\documentclass[11pt");
    if(twoside)     fprintf(cq2->LaTeX, ",twoside");
    if(Columns==2)  fprintf(cq2->LaTeX, ",twocolumn");
    fprintf(cq2->LaTeX, "]{article}\n");
    if(Amssymb>=1)  UsePackage(cq2, "amssymb");
    if(LaTeXsym>=1) UsePackage(cq2, "latexsym");
    if(MakeIdx>=1)  UsePackage(cq2, "makeidx");
    if(Ulem>=1)     UsePackage(cq2, "ulem");
    if(Rotate>=1)   UsePackage(cq2, "rotate");
    if(LineNo>=1)   UsePackage(cq2, "lineno");
    UsePackage(cq2, "wp2latex");
    if(CPStyles) switch(CodePage)
	{
	case 0: break;
	case ISO8859_1:fprintf(cq2->LaTeX, "\\usepackage[latin1]{inputenc}\n");
		       break;
	case ISO8859_2:fprintf(cq2->LaTeX, "\\usepackage[latin2]{inputenc}\n");
		       break;
	case KOI8R:    fprintf(cq2->LaTeX, "\\usepackage[koi8-r]{inputenc}\n");
		       break;
	default:fprintf(cq2->LaTeX, "\\usepackage[cp%d]{inputenc}\n", CodePage);
		break;
	}
    if(colors>=1)   UsePackage(cq2, "color");
    if(Cyrillic>=1) UsePackage(cq2, "cyrillic");
    if(cjHebrew>=1) UsePackage(cq2, "cjhebrew");
    if(EndNotes>=1) UsePackage(cq2, "endnotes");
    if(InputPS==(IMG_InputPS|1))  UsePackage(cq2, "InputPS");
    if(InputPS==(IMG_graphicx|1)) UsePackage(cq2, "graphicx");
    if(InputPS==(IMG_epsfig|1))   UsePackage(cq2, "epsfig");
    if(InputPS==(IMG_graphics|1)) UsePackage(cq2, "graphics");
    if(Columns>2)   UsePackage(cq2, "multicol");
    if(Wasy>=1)     UsePackage(cq2, "wasyfont");
    if(textcomp>=1) UsePackage(cq2, "textcomp");
    if(Bbm>=1)      UsePackage(cq2, "bbm");
    if(TIPA>=1)     fprintf(cq2->LaTeX, "\\usepackage[safe]{tipa}\n");
    if(Rsfs>=1)     UsePackage(cq2, "mathrsfs");
    if(FancyHdr>=1) UsePackage(cq2, "fancyhdr");
    if(pifont>=1)   UsePackage(cq2, "pifont");
    if(LongTable>=1)UsePackage(cq2, "longtable");

    for(int lng=0;lng<sizeof(LangTable)/sizeof(LangItem);lng++)
      {
      if(LangTable[lng].UseLang>=1)
	{
        if(cq2->LangCount==0)
          fprintf(cq2->LaTeX, "\\usepackage[%s",LangTable[lng].LangDesc);
        else
	  fprintf(cq2->LaTeX, ",%s",LangTable[lng].LangDesc);
	cq2->LangCount++;
	}     
      }
    if(cq2->LangCount>0)
      fprintf(cq2->LaTeX, "]{babel}\n");

    if(fontenc>=1)  switch(CodePage)
			{
			case 866:
			case KOI8R:
				 fprintf(cq2->LaTeX, "\\usepackage[T2A]{fontenc}\n");
				 break;
			default: fprintf(cq2->LaTeX, "\\usepackage[T1]{fontenc}\n");
			}

    fputc('\n',cq2->LaTeX);
    }

/*if (Cyrillic) fprintf(cq2->LaTeX, "\\font\\cyr=wncyr10\n");*/
  if(Columns==2)fprintf(cq2->LaTeX, "\\onecolumn\n");
  if (Index)    fprintf(cq2->LaTeX, "\\makeindex\n");
  if(FancyHdr>=1) fprintf(cq2->LaTeX, "\\pagestyle{fancy}\\renewcommand{\\headrulewidth}{0pt}\n\\fancyfoot{}\\fancyhead{}\n");
  if((InputPS&1)==1) TeX_RelativeFigDir=replacesubstring(RelativeFigDir,"\\","/");
  if(InputPS==(IMG_InputPS|1) || InputPS==(IMG_epsfig|1))
       fprintf(cq2->LaTeX, "\\newcommand{\\FigDir}{%s}\n",TeX_RelativeFigDir());

  if(InputPS==(IMG_InputPS|1))
	fprintf(cq2->LaTeX, "\\ShowDisplacementBoxes\n");
  if(InputPS==(IMG_graphicx|1))
	fprintf(cq2->LaTeX, "\\graphicspath{{%s/}}\n",TeX_RelativeFigDir());


  fputc('\n',cq2->LaTeX);
  if(EndNotes<-1) fprintf(cq2->LaTeX, "\\def\\endnote{\\footnote}\n");
  if(length(Counters)>0)
	{
	for(i=0;i<length(Counters);i++)
	    {
	    fprintf(cq2->LaTeX, "\\newcounter{%s}\n",chk(Counters[i]));
	    }
	fputc('\n',cq2->LaTeX);
	}


  for(i=0;i<length(UserLists);i++)
	{
	fprintf(cq2->LaTeX, "\\InitUserList{l%c}  %%%s\n",i+'a',UserLists[i]);
	}
  if(length(UserLists)>0) fputc('\n',cq2->LaTeX);

  fprintf(cq2->LaTeX, "\\begin{document}\n");
}


/* -- Sluit the latex-file op the juiste wijze af -- */
static void Latex_foot(TconvertedPass2 * cq2)
{
#ifdef DEBUG
  fprintf(cq2->log,"\n#Latex_foot() ");fflush(cq2->log);
#endif
  if(EndNotes==1) fprintf(cq2->LaTeX,
  	"\\begingroup\n"
        "\\parindent 0pt \\parskip 1ex\n"
	"\\def\\enotesize{\\normalsize}\n"
	"\\theendnotes\n"
	"\\endgroup\n\n");

  fprintf(cq2->LaTeX, "\\end{document}\n");
}


static void Latex_tabset(TconvertedPass2 *cq2)
{
#ifdef DEBUG
  fprintf(cq2->log,"\n#Latex_tabset() ");fflush(cq2->log);
#endif

  long atpr = 0;
  long j;
  double l;
  double ol = 0.0;
  long FORLIM;

  /* Huiding aantal tabs per row */
  FORLIM = cq2->num_of_tabs;
  for (j = 0; j < FORLIM; j++)
     {
     l = cq2->tabpos[j] / 1200.0 * 2.54;
     fprintf(cq2->LaTeX, "\\hspace{%3.2fcm}\\=", l - ol);
     atpr++;
     if (atpr >= 4)
       {
       fprintf(cq2->LaTeX, "%%\n");
       atpr = 0;
       }
     ol = l;
     }
  fprintf(cq2->LaTeX, "\\kill\n");
}


static boolean Change_envir_BOL(TconvertedPass2 *cq2)
{
#ifdef DEBUG
  fprintf(cq2->log,"\n#Change_envir_BOL() ");fflush(cq2->log);
#endif

  return (cq2->Lines[cq2->cur].envir != cq2->Lines[cq2->pre].envir &&
	  (cq2->Lines[cq2->cur].envir == 'q' ||
	   cq2->Lines[cq2->cur].envir == 'Q' ||
	   cq2->Lines[cq2->cur].envir == 'T' ||
	   cq2->Lines[cq2->cur].envir == 'C' ||
	   cq2->Lines[cq2->cur].envir == 'R' ||
	   cq2->Lines[cq2->cur].envir == 'L' ||
	   cq2->Lines[cq2->cur].envir == 'B' ||
	   toupper(cq2->Lines[cq2->cur].envir) == 'I' ) &&

	   cq2->Lines[cq2->pre].envir != '^');
//	   && cq2->Lines[cq2->cur].envir != '!'
}


static boolean Change_envir_EOL(TconvertedPass2 *cq2)
{
#ifdef DEBUG
  fprintf(cq2->log,"\n#Change_envir_EOL() ");fflush(cq2->log);
#endif

  return (cq2->Lines[cq2->next].envir != cq2->Lines[cq2->cur].envir &&
	  (cq2->Lines[cq2->cur].envir == 'Q' ||
	   cq2->Lines[cq2->cur].envir == 'q' ||
	   toupper(cq2->Lines[cq2->cur].envir) == 'I' ||
	   cq2->Lines[cq2->cur].envir == 'T' ||
	   cq2->Lines[cq2->cur].envir == 'C' ||
	   cq2->Lines[cq2->cur].envir == 'R' ||
	   cq2->Lines[cq2->cur].envir == 'L' ||
	   cq2->Lines[cq2->cur].envir == 'B' ||
	   cq2->Lines[cq2->next].envir == 'Q' ||
           cq2->Lines[cq2->next].envir == 'q' ||
	   toupper(cq2->Lines[cq2->next].envir) == 'I' ||
	   cq2->Lines[cq2->next].envir == 'T' ||
	   cq2->Lines[cq2->next].envir == 'C' ||
	   cq2->Lines[cq2->next].envir == 'R' ||
	   cq2->Lines[cq2->next].envir == 'L' ||
	   cq2->Lines[cq2->next].envir == 'B') &&

	   cq2->Lines[cq2->next].envir != '!' &&
	   cq2->Lines[cq2->cur].envir != '^');
}


static void Close_environment(TconvertedPass2 *cq2)
{
#ifdef DEBUG
  fprintf(cq2->log,"\n#Close_environment() ");fflush(cq2->log);
#endif

 switch (cq2->Lines[cq2->cur].envir)
   {
  case 'B':if(LongTable>=1) fprintf(cq2->LaTeX, "\\end{longtable}\n");
		       else fprintf(cq2->LaTeX, "\\end{tabular}\n");
           break;

  case 'C':fprintf(cq2->LaTeX, "\\end{center}\n");
	   break;

  case 'L':fprintf(cq2->LaTeX, "\\end{flushleft}\n");
           break;

  case 'R':fprintf(cq2->LaTeX, "\\end{flushright}\n");
           break;

  case 'T':fprintf(cq2->LaTeX, "\\end{tabbing}\n");
	   break;

  case 'I':
  case 'i':fprintf(cq2->LaTeX, "\\end{indenting}\n");
           break;

  case 'q':fprintf(cq2->LaTeX, "\\end{eqnarray}\n");
           break;
  case 'Q':fprintf(cq2->LaTeX, "\\end{displaymath}\n");
           break;
  }

  cq2->just_envir_closed = true;
}


static boolean Open_environment(TconvertedPass2 *cq2)
{
#ifdef DEBUG
  fprintf(cq2->log,"\n#Open_environment() ");fflush(cq2->log);
#endif
  string s;

  if(cq2->Lines[cq2->cur].Columns!=cq2->Lines[cq2->pre].Columns)
	{
	if (cq2->Lines[cq2->cur].attr.Opened_Depth>0)	 /* Attributes are opened */
	    {
	    Close_All_Attr(cq2->Lines[cq2->cur].attr,s);
	    cq2->Lines[cq2->cur].Lstring=s+cq2->Lines[cq2->cur].Lstring;
	    }
	if(!cq2->just_envir_closed) Close_environment(cq2);	//Close enviroment if still opened

	if(Columns>=3)	//style Multicol used
	  {
	  if(cq2->Lines[cq2->pre].Columns>1) fprintf(cq2->LaTeX,"\\end{multicols}\n");
	  if(cq2->Lines[cq2->cur].Columns>1) 
	    {
	    fprintf(cq2->LaTeX,"\\begin{multicols}{%d}\n",(int)cq2->Lines[cq2->cur].Columns);
	    cq2->Col2Break=1;
	    }
	  }
	else
	  {
	  switch(cq2->Lines[cq2->cur].Columns)
	     {
	     case 0:
	     case 1:fprintf(cq2->LaTeX, "\\onecolumn\n"); break;
	     case 2:fprintf(cq2->LaTeX, "\\twocolumn\n"); break;
	     default:if(cq2->err!=NULL)
			fprintf(cq2->err,_("\nError: Bad number of columns:%d !"),(int)cq2->Lines[cq2->cur].Columns);
	     }
	  }
	}
  else if (!Change_envir_BOL(cq2))  /* Changed environment ? */
       {
       if (cq2->Lines[cq2->cur].new_tabset && cq2->Lines[cq2->cur].envir == 'T')
		Latex_tabset(cq2);
       if(cq2->Lines[cq2->cur].envir != ' ' && cq2->Lines[cq2->pre].envir == '^')
		cq2->just_envir_closed = false;  //mark popped enviroment as open
//      if(!cq2->just_envir_closed)
		return(false);
       }

  if (cq2->Lines[cq2->cur].attr.Opened_Depth>0)	 /* Attributes are opened */
	{
	Close_All_Attr(cq2->Lines[cq2->cur].attr,s);
	cq2->Lines[cq2->cur].Lstring=s+cq2->Lines[cq2->cur].Lstring;
	}

  cq2->just_envir_closed = false;
  switch (cq2->Lines[cq2->cur].envir)
    {
    case 'B':if(LongTable>=1) fprintf(cq2->LaTeX, "\\begin{longtable}\n");
			 else fprintf(cq2->LaTeX, "\\begin{tabular}\n");
	     break;

    case 'C':fprintf(cq2->LaTeX, "\\begin{center}\n");
	     break;

    case 'L':fprintf(cq2->LaTeX, "\\begin{flushleft}\n");
	     break;

    case 'R':fprintf(cq2->LaTeX, "\\begin{flushright}\n");
	     break;

    case 'T':fprintf(cq2->LaTeX, "\\begin{tabbing}\n");
	     Latex_tabset(cq2);
	     break;

    case 'I':
    case 'i':if(cq2->Lines[cq2->cur].Lstring=="")  //indent nothing ??
		 {
		 return(true);
                 }
	     if ((cq2->Lines[cq2->cur].Indent_Level<2)||(toupper(cq2->Lines[cq2->pre].envir)!='I'))
		      {
		      if(cq2->Lines[cq2->pre].Lstring!="")
					   fprintf(cq2->LaTeX,"\\testlastline\n\n");
                       		      else fprintf(cq2->LaTeX,"\\zerotestlastline\n");
                      }
             fprintf(cq2->LaTeX, "\\begin{indenting}"
                                 "{%3.2fcm}\n",cq2->Lines[cq2->cur].ind_leftmargin / 1200.0 * 2.54);
             break;

    case 'q':fprintf(cq2->LaTeX, "\\begin{eqnarray}\n");
	     break;
    case 'Q':fprintf(cq2->LaTeX, "\\begin{displaymath}\n");
	     break;
    }

return(false);
}


static void Update_global_information(TconvertedPass2 *cq2)
{
#ifdef DEBUG
  fprintf(cq2->log,"\n#Update_global_information() ");fflush(cq2->log);
#endif
  int j, FORLIM;

  if (cq2->Lines[cq2->cur].new_tabset)
        {
	cq2->num_of_tabs = cq2->Lines[cq2->cur].tabent_num_of_tabs;
        FORLIM = cq2->num_of_tabs;
        for (j = 0; j < FORLIM; j++)
        cq2->tabpos[j] = cq2->tabent_tabpos[cq2->cur][j];
	}

}


static void Select_NextLine(TconvertedPass2 *cq2)
{
#ifdef DEBUG
  fprintf(cq2->log,"\n#Select_NextLine() ");fflush(cq2->log);
#endif
  int help;

  help = cq2->pre;
  cq2->pre = cq2->cur;
  cq2->cur = cq2->next;
  cq2->next= cq2->next2;
  cq2->next2 = help;
}


static boolean FixTabs(TconvertedPass2 *cq2,char * Helps)
{
  int i, j = 0, tabs = 0;
  string s;
  char CharStr[10];

  if (Helps == NULL) return false;
  if (Helps == "") return false;

  while(Helps[j++]=='\\')
  	{
	if (Helps[j++] != 'T') break;
	if (Helps[j++] != 'A') break;
	if (Helps[j++] != 'B') break;
	if (Helps[j++] != ' ') break;
        tabs++;
        }
  if (tabs <= 0) return false;

  if((j>(int)strlen(Helps))&&(cq2->Lines[cq2->cur].line_term!='s')&&(cq2->Lines[cq2->cur].line_term!='p'))
  	{
	if(cq2->err!=NULL && Verbosing>0)
	   {
	   cq2->perc.Hide();
	   fprintf(cq2->err,_("\nWarning: Incorrect line with TABs at the end - fixed."));
	   }
	*Helps=0;
        return false;
        }


  if(cq2->Lines[cq2->cur].envir == 'T')
     {
     j=0;
     for(i=0;i<tabs;i++)
  	   {
	   Helps[j++]='\\';
	   Helps[j++]='>';
           }
     i=5*tabs;
     while (Helps[i] != '\0')
            {
	    Helps[j] = Helps[i];
	    i++;
	    j++;
	    }
     Helps[j] = '\0';
     }
  else {
       i=Helps-cq2->Lines[cq2->cur].Lstring();
       s=copy(cq2->Lines[cq2->cur].Lstring,0,i);
       sprintf(CharStr,"%2.2f",float(cq2->tabpos[tabs-1])/ 470.0);
       s+="\\hspace*{";
       s+=CharStr;
       s+="cm}";
       s+=copy(cq2->Lines[cq2->cur].Lstring,i + 5*tabs,length(cq2->Lines[cq2->cur].Lstring)- i - 5*tabs);
       cq2->Lines[cq2->cur].Lstring=s;
       }
  return true;
}



static void OptimSectionStr(char *aline)
{
boolean optimized;
int i,r;
char *str,*str2;

  do {
     optimized = false;
     if(aline == NULL) return;


     i = strlen(aline);
     while(aline[i]==' ')
	{
	aline[i--] = 0;
	}
     if(aline == "") return;

     //i still contains strlen(aline)
     if(aline[i-1] == '\\' && aline[i-2] == '\\')
	{
	aline[i-2] = '\0';
	i -= 2;
	}

     if((str=StrStr(aline, "{\\bf")) != NULL)
	     {
	     str2=str+1;
	     for(r=0;r<3;r++)
		{
		*str2++=' ';
		}

	     str2=str+4;
	     r=0;
	     while(*str2!=0)
		{
		if(*str2=='{') r++;
		if(*str2=='}')
		  if(r==0)
			{
			*str2=' ';
			strcpy(str,str+4);	// Overlapping regions
			i -= 4;
			optimized = true;
			break;
			}
			else r--;
		str2++;
		}
	     }


      if (((str=StrStr(aline, "{\\large")) != NULL)||
	  ((str=StrStr(aline, "{\\Large")) != NULL)||
	  ((str=StrStr(aline, "{\\LARGE")) != NULL))
	     {
	     str2=str+1;
	     for(r=0;r<6;r++)
		{
		*str2++=' ';
		}

	     str2=str+7;
	     r=0;
	     while(*str2!=0)
		{
		if(*str2=='{') r++;
		if(*str2=='}')
		  if(r==0)
		    {
		    *str2=' ';
		    i -= 7;
		    strcpy(str,str+7);
		    //memmove(str,str+7,strlen(str+7));str[i]=0; // Overlapping regions, but terminating 0 must be added			
		    optimized = true;
		    break;
		    }
		  else r--;
		str2++;
		}
	     }

  } while(optimized);
}


static int FixBracket(string & Line)
{
  if (Line == "") return 0;

  Line="{}"+Line;

  return length(Line);
}


static char *TryToRemoveGeneric(char *Helps, const char *Generic)
{
  int i = 0, j;

  if (Helps == NULL) return NULL;
  if (Generic == NULL) return NULL;
  if (*Helps == 0) return NULL;
  if (*Generic == 0) return NULL;

  Helps = StrStr(Helps, Generic);
  if(Helps == NULL) return NULL;

  j = strlen(Generic);

  while (Helps[j] == ' ')
  	{
        j++;
        }
  if (Helps[j++] != '}') return Helps+1;

  while (Helps[j] != '\0')
         {
	 Helps[i] = Helps[j];
	 i++;
	 j++;
	 } 
  Helps[i] = '\0';
  return Helps;
}


static char *TryToRemoveSelectLanguage(char * Helps)
{
  int i = 0, j, k;

  if (Helps == NULL) return NULL;
  if (*Helps == 0) return NULL;
  Helps = StrStr(Helps, "\\selectlanguage{");
  if (Helps == NULL) return NULL;

  j = 16;				// strlen("\\selectlanguage{");
  while (Helps[j] != '}')
  	{
	if(Helps[j]==0) return Helps+1;
        j++;
        }
  if (Helps[j++] != '}') return Helps+1;

  k = j;
  while (Helps[j] == '~' || Helps[j] == ' ')
  	{
        j++;
        }

  if (Helps[j++] != '\\') return Helps+1;
  if (Helps[j++] != 's') return Helps+1;
  if (Helps[j++] != 'e') return Helps+1;
  if (Helps[j++] != 'l') return Helps+1;
  if (Helps[j++] != 'e') return Helps+1;
  if (Helps[j++] != 'c') return Helps+1;
  if (Helps[j++] != 't') return Helps+1;
  if (Helps[j++] != 'l') return Helps+1;
  if (Helps[j++] != 'a') return Helps+1;
  if (Helps[j++] != 'n') return Helps+1;
  if (Helps[j++] != 'g') return Helps+1;
  if (Helps[j++] != 'u') return Helps+1;
  if (Helps[j++] != 'a') return Helps+1;
  if (Helps[j++] != 'g') return Helps+1;
  if (Helps[j++] != 'e') return Helps+1;
  if (Helps[j++] != '{') return Helps+1;

  while (Helps[k] != '\0')
         {
	 Helps[i] = Helps[k];
	 k++;
	 i++;
	 } 
  Helps[i] = '\0';
  return Helps;		//one command removed, try again next command
}


static char *TryToRemoveLineNumbering(char * Helps)
{
  int i = 0, j, k;

  if (Helps == NULL) return NULL;
  if (*Helps == 0) return NULL;
  Helps = StrStr(Helps, "\\begin{linenumbers}");
  if (Helps == NULL) return NULL;

  j = 19;				// strlen("\\begin{linenumbers}");
  k = j;  

  while (Helps[j]==' ' || Helps[j]=='\t')
  	{
        j++;
        }
  
  if (Helps[j++] != '\\') return Helps+1;
  if (Helps[j++] != 'e') return Helps+1;
  if (Helps[j++] != 'n') return Helps+1;
  if (Helps[j++] != 'd') return Helps+1;
  if (Helps[j++] != '{') return Helps+1;
  if (Helps[j++] != 'l') return Helps+1;
  if (Helps[j++] != 'i') return Helps+1;
  if (Helps[j++] != 'n') return Helps+1;
  if (Helps[j++] != 'e') return Helps+1;
  if (Helps[j++] != 'n') return Helps+1;
  if (Helps[j++] != 'u') return Helps+1;
  if (Helps[j++] != 'm') return Helps+1;
  if (Helps[j++] != 'b') return Helps+1;
  if (Helps[j++] != 'e') return Helps+1;
  if (Helps[j++] != 'r') return Helps+1;
  if (Helps[j++] != 's') return Helps+1;
  if (Helps[j++] != '}') return Helps+1;

	/* Copy spaces among linenum commands */
  while (Helps[k]!='\0' && Helps[k]!='\\')  
	{
	Helps[i] = Helps[k];
	i++; k++;
	}    
  
	/* Copy rest of a text */
  while (Helps[j] != '\0')
         {
	 Helps[i] = Helps[j];
	 i++;
	 j++;
	 } 
  Helps[i] = '\0';
  return Helps;		//one command removed, try again next command
}


/* Returns 1 when line contains no printable character, control sequences only. */
int EmptyLine(const string & s)
{
int i;
char ch;

i=0;
while(i<length(s))
	{
        ch=s[i++];
        if(ch==' ') continue;
        if(ch=='\t') continue;
	if(ch=='}') continue;
	if(ch=='{') continue;
	if(ch=='\\')
	   {
	   if(s[i]=='/')	 //ignore \/
		 {
		 i++;
		 continue;
		 }

	   if(s[i]=='b')	 //ignore \bf
		 {
		 i++;
		 if(s[i++]!='f') return(0);
		 continue;
		 }

	   if(s[i]=='c')
		 {
		 i++;
		 if(s[i]=='l')	//ignore \clubpenalty number
		    {
		    i++;
		    if(s[i++]!='u') return(0);
		    if(s[i++]!='b') return(0);
		    if(s[i++]!='p') return(0);
		    if(s[i++]!='e') return(0);
		    if(s[i++]!='n') return(0);
		    if(s[i++]!='a') return(0);
		    if(s[i++]!='l') return(0);
		    if(s[i++]!='t') return(0);
		    if(s[i++]!='y') return(0);
		    while(s[i]==' ') i++;
		    while(isdigit(s[i])) i++;
		    continue;
		    }
		 if(s[i++]!='o') return(0); //ignore \color{\anything}
		 if(s[i++]!='l') return(0);
		 if(s[i++]!='o') return(0);
		 if(s[i++]!='r') return(0);

		 if(s[i++]!='{') return(0);
		 while(s[i++]!='}')
			 {
			 if(i>=length(s)) return(1);
			 };
		 continue;
		 }

	   if(s[i]=='f')	 //ignore \foottext{\anything}
		 {
		 i++;
		 if(s[i++]!='o') return(0);
		 if(s[i++]!='o') return(0);
		 if(s[i++]!='t') return(0);
		 if(s[i++]!='t') return(0);
		 if(s[i++]!='e') return(0);
		 if(s[i++]!='x') return(0);
		 if(s[i++]!='t') return(0);

		 if(s[i++]!='{') return(0);
		 while(s[i++]!='}')
			 {
			 if(i>=length(s)) return(1);
			 };
		 continue;
		 }


	   if(s[i]=='h')	 //ignore \headtext{\anything}
		 {
		 i++;
		 if(s[i++]!='e') return(0);
		 if(s[i++]!='a') return(0);
		 if(s[i++]!='d') return(0);
		 if(s[i++]!='t') return(0);
		 if(s[i++]!='e') return(0);
		 if(s[i++]!='x') return(0);
		 if(s[i++]!='t') return(0);

		 if(s[i++]!='{') return(0);
		 while(s[i++]!='}')
			 {
			 if(i>=length(s)) return(1);
			 };
		 continue;
		 }

	   if(s[i]=='i')	 //ignore \it
		 {
		 i++;
		 if(s[i++]!='t') return(0);
		 continue;
		 }

	   if(s[i]=='l')	 //ignore \label{anything}
		 {
		 i++;
		 if(s[i++]!='a') return(0);
		 if(s[i++]!='b') goto TryLanguage;
		 if(s[i++]!='e') return(0);
		 if(s[i++]!='l') return(0);
		 if(s[i++]!='{') return(0);
		 while(s[i++]!='}')
			 {
			 if(i>=length(s)) return(1);
			 };
		 continue;

TryLanguage:            	//ignore \language anything
		 i--;
		 if(s[i++]!='n') return(0);
		 if(s[i++]!='g') return(0);
		 if(s[i++]!='u') return(0);
		 if(s[i++]!='a') return(0);
		 if(s[i++]!='g') return(0);
		 if(s[i++]!='e') return(0);
		 if(s[i++]!='=') return(0);
		 if(s[i++]!='\\') return(0);

		 while(isalpha(s[i]))
			 {
			 i++;
			 }
		 continue;
		 };

	   if(s[i]=='o')	 //ignore  \onecolumn
		 {
		 i++;
		 if(s[i++]!='n') return(0);
		 if(s[i++]!='e') return(0);
		 goto ColumnText;
		 }

	   if(s[i]=='p')	 //ignore  \penalty NUM
		 {
		 i++;
		 if(s[i++]!='e') return(0);
		 if(s[i++]!='n') return(0);
		 if(s[i++]!='a') return(0);
                 if(s[i++]!='l') return(0);
		 if(s[i++]!='t') return(0);
                 if(s[i++]!='y') return(0);
	         while(s[i]==' ') i++;
	         while(isdigit(s[i])) i++;
                 continue;
	         };

	   if(s[i]=='s')
		 {
		 i++;
		 if(s[i]=='c') continue;	//ignore \sc

		 if(s[i++]!='e') return(0);  
                 if(s[i]=='l')
		   {				//ignore  \selectlanguage{lang}
		   i++;
		   if(s[i++]!='e') return(0);
                   if(s[i++]!='c') return(0);
  		   if(s[i++]!='t') return(0);
		   if(s[i++]!='l') return(0);
		   if(s[i++]!='a') return(0);
                   if(s[i++]!='n') return(0);
                   if(s[i++]!='g') return(0);
                   if(s[i++]!='u') return(0);
                   if(s[i++]!='a') return(0);
                   if(s[i++]!='g') return(0);
                   if(s[i++]!='e') return(0);
                   if(s[i++]!='{') return(0);
 		   while(s[i]!='}') i++;
 		   continue;
		   }
		 
		 if(s[i++]!='t') return(0);	//ignore  \setcounter{counter}{number}
                 if(s[i++]!='c') return(0);
		 if(s[i++]!='o') return(0);
		 if(s[i++]!='u') return(0);
		 if(s[i++]!='n') return(0);
                 if(s[i++]!='t') return(0);
                 if(s[i++]!='e') return(0);
                 if(s[i++]!='r') return(0);

                 if(s[i++]!='{') return(0);
                 while(s[i]!='}' && s[i]!=0) i++;
                 if(s[++i]!='{') return(0);
                 while(s[i]!='}' && s[i]!=0) i++;
                 i++;

		 continue;
		 };

	   if(s[i]=='T')	 //ignore  \TAB
		 {
		 i++;
		 if(s[i++]!='A') return(0);
		 if(s[i++]!='B') return(0);
		 continue;
		 }

	   if(s[i]=='t')	 //ignore  \twocolumn
		 {
		 i++;
		 if(s[i]!='w') goto ThisPageStyle;
		 i++;
ColumnText:	 if(s[i++]!='o') return(0);
		 if(s[i++]!='c') return(0);
		 if(s[i++]!='o') return(0);
		 if(s[i++]!='l') return(0);
		 if(s[i++]!='u') return(0);
		 if(s[i++]!='m') return(0);
		 if(s[i++]!='n') return(0);
		 if(s[i]==0) return(1);
		 if(s[i++]!=' ') return(0);
		 continue;

ThisPageStyle:   i++;
		 if(s[i++]!='h') return(0);
		 if(s[i++]!='i') return(0);
		 if(s[i++]!='s') return(0);
		 if(s[i++]!='p') return(0);
		 if(s[i++]!='a') return(0);
		 if(s[i++]!='g') return(0);
		 if(s[i++]!='e') return(0);
		 if(s[i++]!='s') return(0);
		 if(s[i++]!='t') return(0);
		 if(s[i++]!='y') return(0);
		 if(s[i++]!='l') return(0);
		 if(s[i++]!='e') return(0);
		 if(s[i++]!='{') return(0);

		 while(isalpha(s[i]))
		       {
		       i++;
		       }
		 if(s[i++]!='}') return(0);
		 continue;
		 }

	   if(s[i]=='v')
	         {
                 i++;
                 if(s[i++]!='s') return(0);
		 switch(s[i++])
                   {
				//ignore  \vskip xxcm
		     case 'k': if(s[i++]!='i') return(0);
                               if(s[i++]!='p') return(0);
                               if(s[i++]!=' ') return(0);
                               while(s[i]==' ') i++;
                               while(isdigit(s[i]) || (s[i]=='-') || (s[i]=='.')) i++;
		               if(s[i]!='c') continue;
		               i++;
		               if(s[i]!='m') continue;
		               i++;
			       break;
				//ignore  \vspace {xx cm}
                     case 'p': if(s[i++]!='a') return(0);
                               if(s[i++]!='c') return(0);
			       if(s[i++]!='e') return(0);
			       while(s[i]==' ') i++;
			       if(s[i++]!='{') return(0);
			       while(s[i]!='}')
			         {
				 if(s[i]==0) return(1);
				 i++;
                                 }
			       break;
                     default:  return(0); 
                   }
                 continue;
	         };
	  if(s[i]=='w')	//ignore \widowpenalty number
		{
		i++;
		if(s[i++]!='i') return(0);
		if(s[i++]!='d') return(0);
		if(s[i++]!='o') return(0);
		if(s[i++]!='w') return(0);
 		if(s[i++]!='p') return(0);
 		if(s[i++]!='e') return(0);
 		if(s[i++]!='n') return(0);
 		if(s[i++]!='a') return(0);
 		if(s[i++]!='l') return(0);
 		if(s[i++]!='t') return(0);
 		if(s[i++]!='y') return(0);
 		while(s[i]==' ') i++;
 		while(isdigit(s[i])) i++;
 		continue;
		}
           }
        return(0);		//Line is not Empty
        }
return(1);			//Line is Empty
}


/** This function groups multiple rows inside one table cell into a \shortstack*/
static int OptimizeMultiRows(string & aLine)
{
string NewLine,Cell;
int i;
char *HelpS,*aLinePtr,OldChar;
int shortstack;

HelpS=StrStr(aLine(), "\\penalty-10001");
shortstack=false;
aLinePtr=aLine();
OldChar=0;
while(*aLinePtr!=0)
	{
	if(aLinePtr==HelpS)
	     {
	     i=0;
	     HelpS=StrStr(++HelpS, "\\penalty-10001");
	     aLinePtr+=strlen("\\penalty-10001");
	     while(aLinePtr[i]==' ')
		 {
		 if(aLinePtr[i]==0)   goto Reject;
		 if(aLinePtr[i]=='&') goto Reject;
		 if(aLinePtr[i]=='\\')
		   {
		   if(aLinePtr[++i]=='\\') goto Reject;
		   }

		 i++;
		 }

	     if(!shortstack) Cell="\\shortstack{"+Cell;
	     Cell+="\\\\";
	     if(aLinePtr[i]=='[') Cell+="{}";
			     else if(*aLinePtr!=' ') Cell+=' ';
	     shortstack=3;
	     }

Reject:	if(OldChar!='\\')
	  if(*aLinePtr==0 || *aLinePtr=='&' || (*aLinePtr=='\\' && aLinePtr[1]=='\\'))
	     {
	     NewLine+=Cell;
	     if(shortstack)
		 {
		 if(shortstack>1) NewLine+="\\strut";
		 NewLine+='}';
		 }

	     NewLine+=OldChar=*aLinePtr++;
	     Cell="";
	     shortstack=0;
	     continue;
	     }

	if(*aLinePtr!=' ') shortstack&=~2;
	Cell+=OldChar=*aLinePtr++;
	}

NewLine+=Cell;
if(shortstack)
   {
   if(shortstack>1) NewLine+="\\strut";
   NewLine+='}';
   }

aLine=NewLine;
return(shortstack);
}


/** fix occurence \/ in the vertical mode - remove it */
static void FixItallicAlignment(TconvertedPass2 & cq2, string *aLineStr)
{
  if( (cq2.Lines[cq2.pre].Lstring=="")&&(length(*aLineStr)>=2) )
    if (  (*aLineStr)[0]=='\\' &&  (*aLineStr)[1]=='/' )
	*aLineStr=copy(*aLineStr,2,length(*aLineStr)-2);

  if( (length(cq2.Lines[cq2.next].Lstring)>=2) &&
     (*aLineStr=="" ||
       cq2.Lines[cq2.cur].line_term=='h' || cq2.Lines[cq2.cur].line_term=='p') )
    if( (cq2.Lines[cq2.next].Lstring)[0]=='\\' &&  (cq2.Lines[cq2.next].Lstring)[1]=='/' )
	cq2.Lines[cq2.next].Lstring=copy(cq2.Lines[cq2.next].Lstring,2,length(cq2.Lines[cq2.next].Lstring)-2);
}


/** move } from the beginning of next line to the current line, only when some attribute is opened. */
static void MoveCurlyBrace(TconvertedPass2 & cq2)
{
const char *CHelpS;
TLinePass2 *NextLine = &cq2.Lines[cq2.next];
TLinePass2 *CurLine = &cq2.Lines[cq2.cur];

  while(NextLine->attr.Opened_Depth>0)
  {
    CHelpS = NULL;
    
		// check whether curly brace belongs to a style opened
    if(NextLine->attr.Closed_Depth>0)
    {
      if(NextLine->attr.Opened_Depth >= NextLine->attr.Closed_Depth)
        {		// try to remove all string belonging to the attr
        CHelpS = Close_com[NextLine->attr.stack[NextLine->attr.Opened_Depth-1]];
MatchAgain:
        if(StrNCmp(NextLine->Lstring,CHelpS,strlen(CHelpS)))
	  {
	  if(CHelpS[0]=='\\' && CHelpS[1]=='/') // give a last chance to match without \/
	    {
	    CHelpS += 2;
	    if(*CHelpS!=0) goto MatchAgain;
	    }
	  break;		// close command differs, break the loop
          }
        NextLine->attr.Opened_Depth--;
        }
      NextLine->attr.Closed_Depth--;    
    }

    if(CHelpS==NULL)
    {
      if(NextLine->Lstring[0]!='}') break;
      CHelpS = "}";
    }
  
		// remove string from the next line
    NextLine->Lstring = copy(NextLine->Lstring,strlen(CHelpS),length(NextLine->Lstring)-strlen(CHelpS));

		// and append it to a current line    
    if(CurLine->Lstring=="" && cq2.Lines[cq2.pre].Lstring!="")
        {	// When a current line is empty, add \n	
	CurLine->Lstring += CHelpS;
	CurLine->Lstring += "\n";
	}
    else
        CurLine->Lstring += CHelpS;
    }
}



static const char *GenericStr[] = 
	{"{\\bf", "{\\footnotesize", "{\\it",
	 "{\\large", "{\\Large", "{\\LARGE", "{\\rm", 
	 "{\\sc", "{\\small","{\\tt"};

/*******************---PASS2---******************/
void Convert_second_pass(FILE *Strip, FILE *table, FILE *FileOut, FILE *log,FILE *ErrorFile)
{
#ifdef DEBUG
  fprintf(log,"\n#Convert_second_pass() ");fflush(log);
#endif
int i, len_reg;
string *aLineStr, s;
char *HelpS;
TconvertedPass2 cq2;

  if(FileOut==NULL) return;

  cq2.table = table;
  cq2.Strip = Strip;
  cq2.LaTeX = FileOut;
  cq2.log   = log;
  cq2.err   = ErrorFile;

  cq2.pre = 0;
  cq2.cur = 1;
  cq2.next = 2;
  cq2.next2 = 3;
  cq2.LangCount = 0;

  cq2.Lines[cq2.pre].envir = ' ';
  cq2.Lines[cq2.pre].new_tabset = false;

  cq2.just_envir_closed = true;
  cq2.LineSpacing=0;
  cq2.Col2Break=1;

  for (i = 0; i <= 3; i++)
      {
      cq2.Lines[i].Lstring = "";
      cq2.Lines[i].Empty   = true;
      cq2.Lines[i].Columns = 1;
      cq2.Lines[i].InhibitBsBslash = false;
      InitAttr(cq2.Lines[i].attr);
      }


  cq2.rownum = 1;
  cq2.perc.Init(0, num_of_lines_stripfile,_("Second pass:"));

  Latex_head(&cq2);
			/*read current row from strip file*/
  Read_TableEntry(&cq2, cq2.cur);
  fGets2(Strip, cq2.Lines[cq2.cur].Lstring );
  cq2.Lines[cq2.cur].Empty = EmptyLine(cq2.Lines[cq2.cur].Lstring);
			/*read next row from strip file*/
  fGets2(Strip, cq2.Lines[cq2.next].Lstring);
  Read_TableEntry(&cq2, cq2.next);
  cq2.Lines[cq2.next].Empty = EmptyLine(cq2.Lines[cq2.next].Lstring);
				/*read row after next row from strip file*/
  fGets2(Strip, cq2.Lines[cq2.next2].Lstring);
  Read_TableEntry(&cq2, cq2.next2);
  cq2.Lines[cq2.next2].Empty = EmptyLine(cq2.Lines[cq2.next2].Lstring);


  while((!feof(Strip) || cq2.Lines[cq2.cur].Lstring != "" || cq2.Lines[cq2.next].Lstring != "" || cq2.Lines[cq2.next2].Lstring != ""))
     {
     Update_global_information(&cq2);

     if(Verbosing >= 1)		//actualise a procentage counter
	      cq2.perc.Actualise(cq2.rownum);

     aLineStr = &cq2.Lines[cq2.cur].Lstring;

     if(TIPA>=2)	// Unsafe Tipa
       {
       *aLineStr = replacesubstring(*aLineStr,"\\!","\\!{}");
       }

     len_reg = length(*aLineStr);

	/* Remove all language mess if only one language is present in a document. */
     if(cq2.LangCount<2)
       {
       HelpS = StrStr((*aLineStr)(), "\\selectlanguage{");
       if(HelpS!=NULL)
         {
	 i=*HelpS;
	 *HelpS = NULL;
	 s = (*aLineStr)();
	 *HelpS = i;

	 HelpS+=16;

	 for(i=0;i<strlen(HelpS);i++)
	   {
	   if(HelpS[i]==0) break;
	   if(HelpS[i]=='}')		// remove everything till closing brace
	     {
	     s += HelpS+i+1;
	     *aLineStr = s;
             break;
	     }
	   }	         
	 }
       }

	/* fix an empty environments C and L */
     if(((cq2.Lines[cq2.cur].envir==' ')||(cq2.Lines[cq2.cur].envir=='Q')||(cq2.Lines[cq2.cur].envir=='B')) &&
	 (cq2.Lines[cq2.next].Empty>0) && (cq2.Lines[cq2.next2].envir!='!') )
	   {
	   if(cq2.Lines[cq2.next].envir == 'C' || cq2.Lines[cq2.next].envir == 'L')
		{
		cq2.Lines[cq2.next].envir = ' ';
		}
	   }

    /* fix tabs, which are not in the tabbing environment */
    HelpS = StrStr((*aLineStr)(), "\\TAB ");
    if(HelpS!=NULL)
	{
	FixTabs(&cq2,HelpS); /* Fix tabs must be called first because it can change environment */
	check(*aLineStr);
	}
    if(cq2.Lines[cq2.cur].envir == 'T')  /* fix wrongly accented chars in Tabbing enviroment */
	{
	if(StrStr((*aLineStr)(), "\\'{")!=NULL)
	   *aLineStr=replacesubstring(*aLineStr,"\\'{","\\a'{");
	if(StrStr((*aLineStr)(), "\\`{")!=NULL)
	   *aLineStr=replacesubstring(*aLineStr,"\\`{","\\a`{");
	}


    if (FixSpaces) {   /* More than two spaces must be fixed. */
      if (toupper(cq2.Lines[cq2.cur].envir) != 'Q') {
	for (i = 1; i < len_reg; i++)
	  {
	  if ((*aLineStr)[i] == ' ' && (*aLineStr)[i+1] == ' ')
	    {
	    (*aLineStr)[i+1] = '~';
	    }
	  }
      }
    }

    /* Correct illegal argument which begins '['. */
    if (len_reg >= 1 && (*aLineStr)[1] == '[' ||
	len_reg >= 2 && (*aLineStr)[1] == ' ' && (*aLineStr)[2] == '[') {
      len_reg = FixBracket(*aLineStr);
    }


	/* Try to repair \section{ */
    if (OptimizeSection)
      {
      if (StrStr((*aLineStr)(), "\\part{") != NULL)
          {
	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
	  OptimSectionStr(strstr((*aLineStr)(), "\\part{") + 6L);
	  check(*aLineStr);
	  }
      if (StrStr((*aLineStr)(), "\\chapter{") != NULL)
	  {
	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
	  OptimSectionStr(strstr((*aLineStr)(), "\\chapter{") + 9L);
	  check(*aLineStr);
	  }
      if (StrStr((*aLineStr)(), "\\section{") != NULL)
	  {
	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
	  OptimSectionStr(strstr((*aLineStr)(), "\\section{") + 9L);
	  check(*aLineStr);
	  }
      if (StrStr((*aLineStr)(), "\\subsection{") != NULL)
	  {
	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
	  OptimSectionStr(strstr((*aLineStr)(), "\\subsection{") + 12L);
	  check(*aLineStr);
	  }
      if (StrStr((*aLineStr)(), "\\subsubsection{") != NULL)
	  {
	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
	  OptimSectionStr(strstr( (*aLineStr)(), "\\subsubsection{") + 15L);
	  check(*aLineStr);
	  }
      if (StrStr((*aLineStr)(), "\\paragraph{") != NULL)
	  {
	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
	  OptimSectionStr(strstr( (*aLineStr)(), "\\paragraph{") + 11L);
	  check(*aLineStr);
	  }
      if (StrStr((*aLineStr)(), "\\subparagraph{") != NULL)
	  {
	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
	  OptimSectionStr(strstr((*aLineStr)(), "\\subparagraph{") + 14L);
	  check(*aLineStr);
	  }
       }


	/* Some optimizations of text on current line */

			//fix beginning paragraph with \raise command
    if(cq2.Lines[cq2.pre].Lstring=="" && length(*aLineStr)>=6)
	{
	if(!strncmp((*aLineStr),"\\raise",6))
		*aLineStr="\\strut"+*aLineStr;
	}

          // fix occurence \/ in the vertical mode - remove it
    FixItallicAlignment(cq2,aLineStr);

	  // move } from the beginning of next line to the current line, only when some attribute is opened.
    MoveCurlyBrace(cq2);

	//fix \/ again - moving } could free \/
    FixItallicAlignment(cq2,aLineStr);


    if(Open_environment(&cq2))    //this procedure tests change of the environment
	{
	i=cq2.cur;	//opening enviroment rejected for an empty line
	cq2.cur=cq2.next;
	cq2.next=cq2.next2;
	cq2.next2=i;

	fGets2(Strip, cq2.Lines[cq2.next2].Lstring);
	cq2.Lines[cq2.next2].Columns = cq2.Lines[cq2.next].Columns;
	Read_TableEntry(&cq2, cq2.next2);

	if((cq2.Lines[cq2.cur].envir=='i')&&(cq2.Lines[cq2.pre].envir=='i'))
			cq2.Lines[cq2.pre].envir='I';
        if((cq2.Lines[cq2.cur].envir=='I')&&(cq2.Lines[cq2.pre].envir=='I'))
			cq2.Lines[cq2.pre].envir='i';

        goto SkipThisLine;
        }


//fix closed attributes problem
    if(ClosedAttr(cq2.Lines[cq2.cur].attr)) /* Are attributes closed? */
      if(*aLineStr == "")
	 {
	 if(cq2.Lines[cq2.next].attr.Closed_Depth==cq2.Lines[cq2.cur].attr.Closed_Depth)
		{
		for(i=0;i<cq2.Lines[cq2.next].attr.Closed_Depth;i++)
                	{
                        if(cq2.Lines[cq2.next].attr.stack[i]!=cq2.Lines[cq2.cur].attr.stack[i])
				{	//attributes are not same for next line
                                goto FixOpen;
				}
			}
		cq2.Lines[cq2.next].attr.Opened_Depth=cq2.Lines[cq2.cur].attr.Opened_Depth;
		}
	     else {
FixOpen:	  Open_All_Attr(cq2.Lines[cq2.cur].attr,*aLineStr);
		  }
         }


  if (*aLineStr != "" || cq2.Lines[cq2.next].envir=='!')
	 {		/* Attributes are closed */
	 if(cq2.Lines[cq2.cur].LineFlag & 1  && (*aLineStr == '%'||*aLineStr == ""))
		 {
		 if (Change_envir_EOL(&cq2))
		   if(!cq2.just_envir_closed) Close_environment(&cq2);
		 goto EmptyThisLine; /* Remove empty line added by wp2latex */
		 }

	 if(cq2.Lines[cq2.cur].attr.Closed_Depth > cq2.Lines[cq2.cur].attr.Opened_Depth)
		{
		Open_All_Attr(cq2.Lines[cq2.cur].attr,s);
		*aLineStr=s+*aLineStr;
		}

	 HelpS = StrStr((*aLineStr)(), "@{\\");   /*ignore tabular formater @{...}*/
	 if(HelpS==NULL)
	   {
	   for(i=0;i<sizeof(GenericStr)/sizeof(char*);i++)
	     {
	     HelpS = (*aLineStr)();   /**/
	     do {
	        HelpS = TryToRemoveGeneric(HelpS,GenericStr[i]);
	        } while(HelpS!=NULL);
             }
	   }

		/* remove duplicit items \selectlanguage */
	 HelpS = (*aLineStr)();
	 do {
	    HelpS = TryToRemoveSelectLanguage(HelpS);
	    } while(HelpS);

	 HelpS = (*aLineStr)();
	 do {
	    HelpS = TryToRemoveLineNumbering(HelpS);
	    } while(HelpS);
	   
	 check(*aLineStr);

	 if(cq2.Lines[cq2.cur].envir=='B')
		{
		HelpS=StrStr((*aLineStr)(), "\\penalty-10001");
		if(HelpS!=NULL)
		  {
		  if(OptimizeMultiRows(*aLineStr))
		    if(cq2.Lines[cq2.next].envir=='!' && cq2.Lines[cq2.next].Lstring=="%")
		       *aLineStr+="\\\\";
		  }
		}

	 if(length(*aLineStr)>0)
	   if((i=fputs(*aLineStr,cq2.LaTeX))==EOF) /*here is written current line*/
			{
			RunError(0x20,"");
			}
	 }

			   /*Is it possible to expand the tabbing enviroment? */
    HelpS=StrStr(cq2.Lines[cq2.next].Lstring(), "\\TAB ");
    if((HelpS!=NULL)&&(cq2.Lines[cq2.cur].envir=='T')&&(cq2.Lines[cq2.next].envir==' '))
	{
	cq2.Lines[cq2.next].envir='T';  /* Tabbing expanded for next line */
	}


    switch (cq2.Lines[cq2.cur].line_term)
      {
      case 's':
      case 'p':if(Change_envir_EOL(&cq2))
		   {
		   if (cq2.Lines[cq2.next].attr.Opened_Depth>0) /* Attributes are opened */
		     {
		     Close_All_Attr(cq2.Lines[cq2.next].attr,s); /* close attributes on EOL */
		     if((cq2.Lines[cq2.pre].Lstring=="") && cq2.Lines[cq2.cur].Empty)
			s=replacesubstring(s,"\\/","");  //remove \/ in vertical mode
		     fprintf(cq2.LaTeX,s());
		     }
		   putc('\n', cq2.LaTeX);
		   if(!cq2.just_envir_closed) Close_environment(&cq2);
		   }
	       else putc('\n', cq2.LaTeX);
	       break;

      case 'h':if (toupper(cq2.Lines[cq2.cur].envir) == 'I')
		  {
		  if (cq2.Lines[cq2.next].attr.Opened_Depth>0) /* Attributes are opened */
		     {
		     Close_All_Attr(cq2.Lines[cq2.next].attr,cq2.LaTeX); /* close attributes on EOL */
		     }
		  putc('\n', cq2.LaTeX);
		  if(!cq2.just_envir_closed) Close_environment(&cq2);
		  cq2.Lines[cq2.cur].envir = ' ';
		  }

	       else {
		    cq2.underline = false;
		    for (i = 0; i < cq2.Lines[cq2.next].attr.Closed_Depth; i++)
		      cq2.underline = (cq2.underline ||
				       cq2.Lines[cq2.next].attr.stack[i] == 0xb || //DblUnd
				       cq2.Lines[cq2.next].attr.stack[i] == 0xd || //StrikeOut
				       cq2.Lines[cq2.next].attr.stack[i] == 0xe);  //Underline

		    if (cq2.underline && (cq2.Lines[cq2.next].attr.Opened_Depth>0) &&
			  !ClosedAttr(cq2.Lines[cq2.cur].attr) )
		      {
		      Close_All_Attr(cq2.Lines[cq2.next].attr,cq2.LaTeX); /* close attributes on EOL */
		      }

	/* Elke Indent-environment moet na one harde Return*/
	/* Afgesloten worden.*/

		   if (Change_envir_EOL(&cq2))
			{
			if (cq2.just_envir_closed) fprintf(cq2.LaTeX, "\\nwln\n");
					      else putc('\n', cq2.LaTeX);
			if (cq2.Lines[cq2.next].attr.Opened_Depth>0) /* Attributes are opened */
				 {
				 Close_All_Attr(cq2.Lines[cq2.next].attr,cq2.LaTeX); /* close attributes on EOL */
				 }
			if(!cq2.just_envir_closed) Close_environment(&cq2);
			}
		    else {
			 if(cq2.Lines[cq2.next].envir=='^'); // do not solve anything at the end of the minipage
			 else if (*aLineStr == "" &&
				cq2.Lines[cq2.pre].Lstring == "")
				   {
				   fprintf(cq2.LaTeX, "\\bigskip");
				   }
			 else if (cq2.Lines[cq2.next].Empty>0)
				{
				cq2.Lines[cq2.next].InhibitBsBslash = true;
				}
			 else if (!cq2.Lines[cq2.cur].InhibitBsBslash)
				{
/*				if (!cq2.just_envir_closed && (cq2.Lines[cq2.cur].envir=='L' || cq2.Lines[cq2.cur].envir=='R'))
					 fprintf(cq2.LaTeX, "\\nwln");
				   else*/ {
					if(cq2.Lines[cq2.cur].Empty>0)
						 {
						 if(cq2.Lines[cq2.pre].Lstring!="")
							fputc('\n',cq2.LaTeX);
						 fprintf(cq2.LaTeX, " \\bigskip");
						 }
					    else fprintf(cq2.LaTeX, "\\\\");
					}

				if (cq2.Lines[cq2.next].Lstring[0] == '[')
					  {
					  FixBracket(cq2.Lines[cq2.next].Lstring);
					  }
				}
		   putc('\n', cq2.LaTeX);
		   }
		 }
	     break;

    case 'P':if (cq2.Lines[cq2.next].attr.Opened_Depth>0) /* Attributes are opened */
		     {
		     Close_All_Attr(cq2.Lines[cq2.next].attr,s); /* close attributes on EOL */
		     if((cq2.Lines[cq2.pre].Lstring=="") && cq2.Lines[cq2.cur].Empty)
			s=replacesubstring(s,"\\/","");  //remove \/ in vertical mode
		     fprintf(cq2.LaTeX,s());
		     }
	     putc('\n', cq2.LaTeX);
	     if(!cq2.just_envir_closed) Close_environment(&cq2);
	     if(cq2.Lines[cq2.cur].Columns<=1 || Columns<3 || cq2.Col2Break>=cq2.Lines[cq2.cur].Columns)
	       {
	       fprintf(cq2.LaTeX, "\\newpage\n");
	       cq2.Col2Break=1;
	       }
	     else
	       {
	       fprintf(cq2.LaTeX, "\\columnbreak\n");	// every columnth's break do rather newpage
	       cq2.Col2Break++;
	       }
	     cq2.Lines[cq2.cur].envir = ' ';
	     break;
      }

EmptyThisLine:
    cq2.Lines[cq2.pre].Lstring = "";
    cq2.Lines[cq2.pre].InhibitBsBslash = false;

    Select_NextLine(&cq2);
				/*read next row from strip file*/
    fGets2(Strip, cq2.Lines[cq2.next2].Lstring);
    cq2.Lines[cq2.next2].Empty = EmptyLine(cq2.Lines[cq2.next2].Lstring);
    cq2.Lines[cq2.next2].Columns = cq2.Lines[cq2.next].Columns;
    Read_TableEntry(&cq2, cq2.next2);

SkipThisLine:
    cq2.rownum++;
    }

  if(cq2.Lines[cq2.cur].envir != ' ' && cq2.Lines[cq2.pre].envir == '^')
		cq2.just_envir_closed = false;  //mark popped enviroment as open
  if(!cq2.just_envir_closed) Close_environment(&cq2);	//Close enviroment if still opened
  if(Columns>=3 && cq2.Lines[cq2.pre].Columns>1) fprintf(cq2.LaTeX,"\\end{multicols}\n");
  Latex_foot(&cq2);

  if(Verbosing >= 1)		//finishing a procentage counter
     {
     cq2.perc.SetPercent(100);
     }
}

/* End of pass2.cc */
