PageRenderTime 157ms CodeModel.GetById 3ms app.highlight 139ms RepoModel.GetById 2ms app.codeStats 0ms

/trunk/sources.cc/pass2.cc

https://bitbucket.org/JaFojtik/wp2latex
C++ | 1857 lines | 1692 code | 116 blank | 49 comment | 227 complexity | 0fd4657272ee0b7f37a536e3e8c3e613 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/******************************************************************************
   2 * program:     wp2latex                                                      *
   3 * function:    convert WordPerfect 5.x,6,7,8.x files into LaTeX              *
   4 * modul:       pass2.cc                                                      *
   5 * description: This modul contains functions for second pass. In the second  *
   6 *              pass the text file stripped from the WP binary file will be   *
   7 *              completed with the information of the binary table file which *
   8 *              contains additional information about environments.           *
   9 * licency:     GPL		                                              *
  10 ******************************************************************************/
  11
  12//Ukoly: podivat se na: \\justified \\raggedright
  13
  14#include <string.h>
  15#include <stdio.h>
  16#include <math.h>
  17#include <ctype.h>
  18
  19#include <strings.h>
  20#include <lists.h>
  21#include "wp2latex.h"
  22
  23extern list Counters, UserLists;
  24
  25
  26//#define DEBUG_STOP_TEXT "xxxxx"
  27
  28#ifdef DEBUG_STOP_TEXT
  29 bool debug_stop = false;
  30 #define DEBUG_CHECK if(debug_stop) __asm int 3;   
  31#else
  32 #define DEBUG_CHECK /* void */
  33#endif
  34
  35
  36/// Attribute for each line of conferted text.
  37typedef struct TLinePass2
  38  {
  39  string Lstring;			///< Text on the line.
  40  boolean new_tabset;
  41  int tabent_num_of_tabs;
  42  char envir, line_term;
  43  char Columns;
  44  signed char Empty;
  45  unsigned char LineFlag;
  46
  47  attribute attr;			///< Attributes opened at the beginning of this line.
  48
  49  boolean InhibitBsBslash;
  50
  51  int ind_leftmargin;
  52  signed char Indent_Level;
  53  } TLinePass2;
  54
  55typedef long pchar;
  56
  57
  58typedef struct TconvertedPass2 
  59{
  60  Percentor perc;
  61  long rownum;
  62  BYTE LangCount;
  63
  64  TLinePass2 Lines[4];
  65
  66  boolean underline, illegal_argument, just_envir_closed;
  67
  68  int num_of_tabs;
  69  char Col2Break;			///< Amount of \columnbreak inside multicol environment
  70  unsigned short tabpos[40];
  71
  72  unsigned int tabent_tabpos[4][40];
  73
  74  short int pre, cur, next, next2;
  75  FILE *table;
  76  FILE *Strip, *LaTeX;
  77  FILE *log, *err;
  78  unsigned int  LineSpacing;
  79} TconvertedPass2;
  80
  81
  82static void Read_TableEntry(TconvertedPass2 *cq2, short n)
  83{
  84#ifdef DEBUG
  85  fprintf(cq2->log,"\n#Read_TableEntry(%d) ",(int)n);fflush(cq2->log);
  86#endif
  87WORD w;
  88BYTE b;
  89int j;
  90TLinePass2 *pCurLine;
  91
  92  pCurLine=&cq2->Lines[n];	/* Begin met one schone lei die dan door this procedure verder wordt opgevuld. */
  93  pCurLine->envir = ' ';
  94  pCurLine->LineFlag = 0;
  95  pCurLine->new_tabset = false;
  96
  97  InitAttr(pCurLine->attr);
  98
  99  if (feof(cq2->table)) return;
 100
 101  b = 0;
 102  while(b != 0xff)
 103    {
 104    if(fread(&b, 1, 1, cq2->table)==0) // We are probaly at the end of the file
 105		break;
 106
 107    switch (b)
 108	{
 109	case 'B':pCurLine->envir = 'B';    break;
 110	case 'C':pCurLine->envir = 'C';    break;
 111	case 'L':pCurLine->envir = 'L';    break;
 112	case 'R':pCurLine->envir = 'R';    break;
 113	case 'T':pCurLine->envir = 'T';    break;
 114	case 'q':pCurLine->envir = 'q';    break;
 115	case 'Q':pCurLine->envir = 'Q';    break;
 116	case 'I':
 117	case 'i':pCurLine->envir=b;
 118		 Rd_word(cq2->table, &w);
 119		 pCurLine->ind_leftmargin=w;
 120		 fread(&pCurLine->Indent_Level, 1, 1, cq2->table);
 121		 break;
 122
 123	case 'S':pCurLine->new_tabset = true;
 124		 fread(&b, 1, 1, cq2->table);
 125		 pCurLine->tabent_num_of_tabs = b;
 126		 for (j = 0; j < b; j++)
 127		     {
 128		     Rd_word(cq2->table, &w);
 129		     cq2->tabent_tabpos[n][j] = w;
 130		     }
 131		 break;
 132
 133       case 'l': Rd_word(cq2->table, &w);
 134		 if(w!=cq2->LineSpacing)
 135			    {
 136			    fprintf(cq2->LaTeX,"\\baselineskip=%2.2fex ",float(w)/128);
 137			    cq2->LineSpacing=w;
 138			    }
 139		  break;
 140
 141	case 'M':fread(&pCurLine->Columns, 1, 1, cq2->table);	break;
 142
 143	case 'h':
 144	case 's':
 145	case 'P':
 146	case 'p':pCurLine->line_term = b;
 147		 break;
 148
 149	case '%':pCurLine->LineFlag |= 1;  break; /* Useless comment line */
 150
 151	case '!':pCurLine->envir = '!';    break; /* Ignore enviroment before */
 152	case '^':pCurLine->envir = '^';    break; /* Ignore enviroment after */
 153
 154		    // Read all opened attributes into attr structure
 155	case 0xF0:fread(&b, 1, 1, cq2->table);
 156		  pCurLine->attr.Opened_Depth=pCurLine->attr.Closed_Depth = b;
 157		  for (j = 0; j < b; j++)
 158			fread(&(pCurLine->attr.stack[j]), 1, 1, cq2->table);
 159		  b=0xF0;
 160		  break;
 161
 162	case 0xFF:
 163	case 10:
 164	case 13:break;               //do nothing
 165
 166	default:if(cq2->err!=NULL)
 167		    fprintf(cq2->err,_("\nError: Bad command '%c' in table file!"),b);
 168	}
 169  }
 170}
 171
 172
 173static void UsePackage(TconvertedPass2 *cq2,const char *PkgName)
 174{
 175  fprintf(cq2->LaTeX, "\\usepackage{%s}\n",PkgName);
 176}
 177
 178
 179/** -- Make the standard-heading for one latex-file -- */
 180static void Latex_head(TconvertedPass2 *cq2)
 181{
 182#ifdef DEBUG
 183  fprintf(cq2->log,"\n#Latex_head() ");fflush(cq2->log);
 184#endif
 185int i;
 186string TeX_RelativeFigDir;
 187
 188  fprintf(cq2->LaTeX,_("%% This file was created by the WP2LaTeX program version: %s \n"), version );
 189  if(LaTeX_Version<0x300)
 190    {
 191    fprintf(cq2->LaTeX, "\\documentstyle[11pt,");
 192    if(Amssymb>=1)  fprintf(cq2->LaTeX, "amssymb,");
 193    if(AmsMath>=1)   fprintf(cq2->LaTeX, "amsmath,");
 194    if(MakeIdx>=1)  fprintf(cq2->LaTeX, "makeidx,");
 195    if(Ulem>=1)     fprintf(cq2->LaTeX, "ulem,");
 196    if(Rotate>=1)   fprintf(cq2->LaTeX, "rotate,");
 197    if(LineNo>=1)   fprintf(cq2->LaTeX, "lineno,");
 198    fprintf(cq2->LaTeX, "wp2latex");
 199    if(twoside)     fprintf(cq2->LaTeX, ",twoside");
 200    if(Columns==2)  fprintf(cq2->LaTeX, ",twocolumn");
 201    if(Columns>2)   fprintf(cq2->LaTeX, ",multicol");
 202    if(EndNotes>=1) fprintf(cq2->LaTeX, ",endnotes");
 203    if(Cyrillic>=1) fprintf(cq2->LaTeX, ",cyrillic");
 204    if(cjHebrew>=1) fprintf(cq2->LaTeX, ",cjhebrew");
 205    if(InputPS==(IMG_InputPS|1))  fprintf(cq2->LaTeX, ",InputPS");
 206    if(InputPS==(IMG_graphicx|1)) fprintf(cq2->LaTeX, ",graphicx");
 207    if(InputPS==(IMG_epsfig|1))   fprintf(cq2->LaTeX, ",epsfig");
 208    if(InputPS==(IMG_graphics|1)) fprintf(cq2->LaTeX, ",graphics");
 209    if(Wasy>=1)     fprintf(cq2->LaTeX, ",wasyfont");
 210    if(textcomp>=1) fprintf(cq2->LaTeX, ",textcomp");
 211    if(Bbm>=1)      fprintf(cq2->LaTeX, ",bbm");
 212    if(Rsfs>=1)     fprintf(cq2->LaTeX, ",mathrsfs");
 213    if(FancyHdr>=1) fprintf(cq2->LaTeX, ",fancyhdr");
 214    if(LongTable>=1)fprintf(cq2->LaTeX, ",longtable");
 215    if(pifont>=1)   fprintf(cq2->LaTeX, ",pifont");
 216    for(int lng=0;lng<sizeof(LangTable)/sizeof(LangItem);lng++)
 217      {
 218      if(LangTable[lng].UseLang>=1)
 219	{
 220	fprintf(cq2->LaTeX, ",%s",LangTable[lng].LangDesc);
 221	cq2->LangCount++;
 222	}
 223      }       
 224    fprintf(cq2->LaTeX, "]{article}\n\n");
 225    }
 226  else
 227    {
 228    fprintf(cq2->LaTeX, "\\documentclass[11pt");
 229    if(twoside)     fprintf(cq2->LaTeX, ",twoside");
 230    if(Columns==2)  fprintf(cq2->LaTeX, ",twocolumn");
 231    fprintf(cq2->LaTeX, "]{article}\n");
 232    if(Amssymb>=1)  UsePackage(cq2, "amssymb");
 233    if(AmsMath>=1)  UsePackage(cq2, "amsmath");
 234    if(LaTeXsym>=1) UsePackage(cq2, "latexsym");
 235    if(MakeIdx>=1)  UsePackage(cq2, "makeidx");
 236    if(Ulem>=1)     UsePackage(cq2, "ulem");
 237    if(Rotate>=1)   UsePackage(cq2, "rotate");
 238    if(LineNo>=1)   UsePackage(cq2, "lineno");
 239    UsePackage(cq2, "wp2latex");
 240    if(CPStyles) switch(CodePage)
 241	{
 242	case 0: break;
 243	case ISO8859_1:fprintf(cq2->LaTeX, "\\usepackage[latin1]{inputenc}\n");
 244		       break;
 245	case ISO8859_2:fprintf(cq2->LaTeX, "\\usepackage[latin2]{inputenc}\n");
 246		       break;
 247	case KOI8R:    fprintf(cq2->LaTeX, "\\usepackage[koi8-r]{inputenc}\n");
 248		       break;
 249	default:fprintf(cq2->LaTeX, "\\usepackage[cp%d]{inputenc}\n", CodePage);
 250		break;
 251	}
 252    if(colors>=1)   UsePackage(cq2, "color");
 253    if(Cyrillic>=1) UsePackage(cq2, "cyrillic");
 254    if(cjHebrew>=1) UsePackage(cq2, "cjhebrew");
 255    if(EndNotes>=1) UsePackage(cq2, "endnotes");
 256    if(InputPS==(IMG_InputPS|1))  UsePackage(cq2, "InputPS");
 257    if(InputPS==(IMG_graphicx|1)) UsePackage(cq2, "graphicx");
 258    if(InputPS==(IMG_epsfig|1))   UsePackage(cq2, "epsfig");
 259    if(InputPS==(IMG_graphics|1)) UsePackage(cq2, "graphics");
 260    if(Columns>2)   UsePackage(cq2, "multicol");
 261    if(Wasy>=1)     UsePackage(cq2, "wasyfont");
 262    if(textcomp>=1) UsePackage(cq2, "textcomp");
 263    if(Bbm>=1)      UsePackage(cq2, "bbm");
 264    if(TIPA>=1)     fprintf(cq2->LaTeX, "\\usepackage[safe]{tipa}\n");
 265    if(Rsfs>=1)     UsePackage(cq2, "mathrsfs");
 266    if(FancyHdr>=1) UsePackage(cq2, "fancyhdr");
 267    if(pifont>=1)   UsePackage(cq2, "pifont");
 268    if(LongTable>=1)UsePackage(cq2, "longtable");
 269
 270    for(int lng=0;lng<sizeof(LangTable)/sizeof(LangItem);lng++)
 271      {
 272      if(LangTable[lng].UseLang>=1)
 273	{
 274        if(cq2->LangCount==0)
 275          fprintf(cq2->LaTeX, "\\usepackage[%s",LangTable[lng].LangDesc);
 276        else
 277	  fprintf(cq2->LaTeX, ",%s",LangTable[lng].LangDesc);
 278	cq2->LangCount++;
 279	}     
 280      }
 281    if(cq2->LangCount>0)
 282      fprintf(cq2->LaTeX, "]{babel}\n");
 283
 284    if(fontenc>=1)  switch(CodePage)
 285			{
 286			case 866:
 287			case KOI8R:
 288				 fprintf(cq2->LaTeX, "\\usepackage[T2A]{fontenc}\n");
 289				 break;
 290			default: fprintf(cq2->LaTeX, "\\usepackage[T1]{fontenc}\n");
 291			}
 292
 293    fputc('\n',cq2->LaTeX);
 294    }
 295
 296/*if (Cyrillic) fprintf(cq2->LaTeX, "\\font\\cyr=wncyr10\n");*/
 297  if(Columns==2)fprintf(cq2->LaTeX, "\\onecolumn\n");
 298  if (Index)    fprintf(cq2->LaTeX, "\\makeindex\n");
 299  if(FancyHdr>=1) fprintf(cq2->LaTeX, "\\pagestyle{fancy}\\renewcommand{\\headrulewidth}{0pt}\n\\fancyfoot{}\\fancyhead{}\n");
 300  if((InputPS&1)==1) TeX_RelativeFigDir=replacesubstring(RelativeFigDir,"\\","/");
 301  if(InputPS==(IMG_InputPS|1) || InputPS==(IMG_epsfig|1))
 302       fprintf(cq2->LaTeX, "\\newcommand{\\FigDir}{%s}\n",TeX_RelativeFigDir());
 303
 304  if(InputPS==(IMG_InputPS|1))
 305	fprintf(cq2->LaTeX, "\\ShowDisplacementBoxes\n");
 306  if(InputPS==(IMG_graphicx|1))
 307	fprintf(cq2->LaTeX, "\\graphicspath{{%s/}}\n",TeX_RelativeFigDir());
 308
 309
 310  fputc('\n',cq2->LaTeX);
 311  if(EndNotes<-1) fprintf(cq2->LaTeX, "\\def\\endnote{\\footnote}\n");
 312  if(length(Counters)>0)
 313	{
 314	for(i=0;i<length(Counters);i++)
 315	    {
 316	    fprintf(cq2->LaTeX, "\\newcounter{%s}\n",chk(Counters[i]));
 317	    }
 318	fputc('\n',cq2->LaTeX);
 319	}
 320
 321
 322  for(i=0;i<length(UserLists);i++)
 323	{
 324	fprintf(cq2->LaTeX, "\\InitUserList{l%c}  %%%s\n",i+'a',UserLists[i]);
 325	}
 326  if(length(UserLists)>0) fputc('\n',cq2->LaTeX);
 327
 328  fprintf(cq2->LaTeX, "\\begin{document}\n");
 329}
 330
 331
 332/** -- Sluit the latex-file op the juiste wijze af -- */
 333static void Latex_foot(TconvertedPass2 * cq2)
 334{
 335#ifdef DEBUG
 336  fprintf(cq2->log,"\n#Latex_foot() ");fflush(cq2->log);
 337#endif
 338  if(EndNotes==1) fprintf(cq2->LaTeX,
 339  	"\\begingroup\n"
 340        "\\parindent 0pt \\parskip 1ex\n"
 341	"\\def\\enotesize{\\normalsize}\n"
 342	"\\theendnotes\n"
 343	"\\endgroup\n\n");
 344
 345  fprintf(cq2->LaTeX, "\\end{document}\n");
 346}
 347
 348
 349static void Latex_tabset(TconvertedPass2 *cq2)
 350{
 351#ifdef DEBUG
 352  fprintf(cq2->log,"\n#Latex_tabset() ");fflush(cq2->log);
 353#endif
 354
 355  long atpr = 0;
 356  long j;
 357  double l;
 358  double ol = 0.0;
 359  long FORLIM;
 360
 361  /* Huiding aantal tabs per row */
 362  FORLIM = cq2->num_of_tabs;
 363  for (j = 0; j < FORLIM; j++)
 364     {
 365     l = cq2->tabpos[j] / 1200.0 * 2.54;
 366     fprintf(cq2->LaTeX, "\\hspace{%3.2fcm}\\=", l - ol);
 367     atpr++;
 368     if (atpr >= 4)
 369       {
 370       fprintf(cq2->LaTeX, "%%\n");
 371       atpr = 0;
 372       }
 373     ol = l;
 374     }
 375  fprintf(cq2->LaTeX, "\\kill\n");
 376}
 377
 378
 379static boolean Change_envir_BOL(TconvertedPass2 *cq2)
 380{
 381#ifdef DEBUG
 382  fprintf(cq2->log,"\n#Change_envir_BOL() ");fflush(cq2->log);
 383#endif
 384
 385  return (cq2->Lines[cq2->cur].envir != cq2->Lines[cq2->pre].envir &&
 386	  (cq2->Lines[cq2->cur].envir == 'q' ||
 387	   cq2->Lines[cq2->cur].envir == 'Q' ||
 388	   cq2->Lines[cq2->cur].envir == 'T' ||
 389	   cq2->Lines[cq2->cur].envir == 'C' ||
 390	   cq2->Lines[cq2->cur].envir == 'R' ||
 391	   cq2->Lines[cq2->cur].envir == 'L' ||
 392	   cq2->Lines[cq2->cur].envir == 'B' ||
 393	   toupper(cq2->Lines[cq2->cur].envir) == 'I' ) &&
 394
 395	   cq2->Lines[cq2->pre].envir != '^');
 396//	   && cq2->Lines[cq2->cur].envir != '!'
 397}
 398
 399
 400static boolean Change_envir_EOL(TconvertedPass2 *cq2)
 401{
 402#ifdef DEBUG
 403  fprintf(cq2->log,"\n#Change_envir_EOL() ");fflush(cq2->log);
 404#endif
 405
 406  return (cq2->Lines[cq2->next].envir != cq2->Lines[cq2->cur].envir &&
 407	  (cq2->Lines[cq2->cur].envir == 'Q' ||
 408	   cq2->Lines[cq2->cur].envir == 'q' ||
 409	   toupper(cq2->Lines[cq2->cur].envir) == 'I' ||
 410	   cq2->Lines[cq2->cur].envir == 'T' ||
 411	   cq2->Lines[cq2->cur].envir == 'C' ||
 412	   cq2->Lines[cq2->cur].envir == 'R' ||
 413	   cq2->Lines[cq2->cur].envir == 'L' ||
 414	   cq2->Lines[cq2->cur].envir == 'B' ||
 415	   cq2->Lines[cq2->next].envir == 'Q' ||
 416           cq2->Lines[cq2->next].envir == 'q' ||
 417	   toupper(cq2->Lines[cq2->next].envir) == 'I' ||
 418	   cq2->Lines[cq2->next].envir == 'T' ||
 419	   cq2->Lines[cq2->next].envir == 'C' ||
 420	   cq2->Lines[cq2->next].envir == 'R' ||
 421	   cq2->Lines[cq2->next].envir == 'L' ||
 422	   cq2->Lines[cq2->next].envir == 'B') &&
 423
 424	   cq2->Lines[cq2->next].envir != '!' &&
 425	   cq2->Lines[cq2->cur].envir != '^');
 426}
 427
 428
 429static void Close_environment(TconvertedPass2 *cq2)
 430{
 431#ifdef DEBUG
 432  fprintf(cq2->log,"\n#Close_environment() ");fflush(cq2->log);
 433#endif
 434
 435 switch (cq2->Lines[cq2->cur].envir)
 436   {
 437  case 'B':if(LongTable>=1) fprintf(cq2->LaTeX, "\\end{longtable}\n");
 438		       else fprintf(cq2->LaTeX, "\\end{tabular}\n");
 439           break;
 440
 441  case 'C':fprintf(cq2->LaTeX, "\\end{center}\n");
 442	   break;
 443
 444  case 'L':fprintf(cq2->LaTeX, "\\end{flushleft}\n");
 445           break;
 446
 447  case 'R':fprintf(cq2->LaTeX, "\\end{flushright}\n");
 448           break;
 449
 450  case 'T':fprintf(cq2->LaTeX, "\\end{tabbing}\n");
 451	   break;
 452
 453  case 'I':
 454  case 'i':fprintf(cq2->LaTeX, "\\end{indenting}\n");
 455           break;
 456
 457  case 'q':fprintf(cq2->LaTeX, "\\end{eqnarray}\n");
 458           break;
 459  case 'Q':fprintf(cq2->LaTeX, "\\end{displaymath}\n");
 460           break;
 461  }
 462
 463  cq2->just_envir_closed = true;
 464}
 465
 466
 467static boolean Open_environment(TconvertedPass2 *cq2)
 468{
 469#ifdef DEBUG
 470  fprintf(cq2->log,"\n#Open_environment() ");fflush(cq2->log);
 471#endif
 472  string s;
 473
 474  if(cq2->Lines[cq2->cur].Columns!=cq2->Lines[cq2->pre].Columns)
 475	{
 476	if (cq2->Lines[cq2->cur].attr.Opened_Depth>0)	 /* Attributes are opened */
 477	    {
 478	    Close_All_Attr(cq2->Lines[cq2->cur].attr,s);
 479	    cq2->Lines[cq2->cur].Lstring=s+cq2->Lines[cq2->cur].Lstring;
 480	    }
 481	if(!cq2->just_envir_closed) Close_environment(cq2);	//Close enviroment if still opened
 482
 483	if(Columns>=3)	//style Multicol used
 484	  {
 485	  if(cq2->Lines[cq2->pre].Columns>1) fprintf(cq2->LaTeX,"\\end{multicols}\n");
 486	  if(cq2->Lines[cq2->cur].Columns>1) 
 487	    {
 488	    fprintf(cq2->LaTeX,"\\begin{multicols}{%d}\n",(int)cq2->Lines[cq2->cur].Columns);
 489	    cq2->Col2Break=1;
 490	    }
 491	  }
 492	else
 493	  {
 494	  switch(cq2->Lines[cq2->cur].Columns)
 495	     {
 496	     case 0:
 497	     case 1:fprintf(cq2->LaTeX, "\\onecolumn\n"); break;
 498	     case 2:fprintf(cq2->LaTeX, "\\twocolumn\n"); break;
 499	     default:if(cq2->err!=NULL)
 500			fprintf(cq2->err,_("\nError: Bad number of columns:%d !"),(int)cq2->Lines[cq2->cur].Columns);
 501	     }
 502	  }
 503	}
 504  else if (!Change_envir_BOL(cq2))  /* Changed environment ? */
 505       {
 506       if (cq2->Lines[cq2->cur].new_tabset && cq2->Lines[cq2->cur].envir == 'T')
 507		Latex_tabset(cq2);
 508       if(cq2->Lines[cq2->cur].envir != ' ' && cq2->Lines[cq2->pre].envir == '^')
 509		cq2->just_envir_closed = false;  //mark popped enviroment as open
 510//      if(!cq2->just_envir_closed)
 511		return(false);
 512       }
 513
 514  if (cq2->Lines[cq2->cur].attr.Opened_Depth>0)	 /* Attributes are opened */
 515	{
 516	Close_All_Attr(cq2->Lines[cq2->cur].attr,s);
 517	cq2->Lines[cq2->cur].Lstring = s + cq2->Lines[cq2->cur].Lstring;
 518	}
 519
 520  cq2->just_envir_closed = false;
 521  switch (cq2->Lines[cq2->cur].envir)
 522    {
 523    case 'B':if(LongTable>=1) fprintf(cq2->LaTeX, "\\begin{longtable}\n");
 524			 else fprintf(cq2->LaTeX, "\\begin{tabular}\n");
 525	     break;
 526
 527    case 'C':fprintf(cq2->LaTeX, "\\begin{center}\n");
 528	     break;
 529
 530    case 'L':fprintf(cq2->LaTeX, "\\begin{flushleft}\n");
 531	     break;
 532
 533    case 'R':fprintf(cq2->LaTeX, "\\begin{flushright}\n");
 534	     break;
 535
 536    case 'T':fprintf(cq2->LaTeX, "\\begin{tabbing}\n");
 537	     Latex_tabset(cq2);
 538	     break;
 539
 540    case 'I':
 541    case 'i':if(cq2->Lines[cq2->cur].Lstring=="")  //indent nothing ??
 542		 {
 543		 return(true);
 544                 }
 545	     if((cq2->Lines[cq2->cur].Indent_Level<2)||(toupper(cq2->Lines[cq2->pre].envir)!='I'))
 546		 {
 547		 if(cq2->Lines[cq2->pre].Lstring!="")
 548			   fprintf(cq2->LaTeX,"\\testlastline\n\n");
 549                 else fprintf(cq2->LaTeX,"\\zerotestlastline\n");
 550                 }              
 551             fprintf(cq2->LaTeX, "\\begin{indenting}"
 552                                 "{%3.2fcm}\n",cq2->Lines[cq2->cur].ind_leftmargin / 1200.0 * 2.54);
 553             break;
 554
 555    case 'q':fprintf(cq2->LaTeX, "\\begin{eqnarray}\n");
 556	     break;
 557    case 'Q':fprintf(cq2->LaTeX, "\\begin{displaymath}\n");
 558	     break;
 559    }
 560
 561return(false);
 562}
 563
 564
 565static void Update_global_information(TconvertedPass2 *cq2)
 566{
 567#ifdef DEBUG
 568  fprintf(cq2->log,"\n#Update_global_information() ");fflush(cq2->log);
 569#endif
 570  int j, FORLIM;
 571
 572  if (cq2->Lines[cq2->cur].new_tabset)
 573        {
 574	cq2->num_of_tabs = cq2->Lines[cq2->cur].tabent_num_of_tabs;
 575        FORLIM = cq2->num_of_tabs;
 576        for (j = 0; j < FORLIM; j++)
 577        cq2->tabpos[j] = cq2->tabent_tabpos[cq2->cur][j];
 578	}
 579
 580}
 581
 582
 583static void Select_NextLine(TconvertedPass2 *cq2)
 584{
 585#ifdef DEBUG
 586  fprintf(cq2->log,"\n#Select_NextLine() ");fflush(cq2->log);
 587#endif
 588  int help;
 589
 590  help = cq2->pre;
 591  cq2->pre = cq2->cur;
 592  cq2->cur = cq2->next;
 593  cq2->next= cq2->next2;
 594  cq2->next2 = help;
 595}
 596
 597
 598static boolean FixTabs(TconvertedPass2 *cq2, char *Helps)
 599{
 600  int i, j = 0, tabs = 0;
 601  string s;
 602  char CharStr[10];
 603
 604  if(Helps == NULL) return false;
 605  if(*Helps == 0) return false;
 606
 607  while(Helps[j++]=='\\')
 608  	{
 609	if(Helps[j++] != 'T') break;
 610	if(Helps[j++] != 'A') break;
 611	if(Helps[j++] != 'B') break;
 612	if(Helps[j] != 0)
 613          {
 614	  if(Helps[j++] != ' ') break;
 615          }
 616        tabs++;
 617        }
 618  if(tabs <= 0) return false;
 619
 620  if((j>(int)strlen(Helps))&&(cq2->Lines[cq2->cur].line_term!='s')&&(cq2->Lines[cq2->cur].line_term!='p'))
 621  	{
 622	if(cq2->err!=NULL && Verbosing>0)
 623	   {
 624	   cq2->perc.Hide();
 625	   fprintf(cq2->err,_("\nWarning: Incorrect line with TABs at the end - fixed."));
 626	   }
 627	*Helps=0;
 628        return false;
 629        }
 630
 631
 632  if(cq2->Lines[cq2->cur].envir == 'T')
 633     {
 634     j=0;
 635     for(i=0;i<tabs;i++)
 636  	   {
 637	   Helps[j++]='\\';
 638	   Helps[j++]='>';
 639           }
 640     i=5*tabs;
 641     while (Helps[i] != '\0')
 642            {
 643	    Helps[j] = Helps[i];
 644	    i++;
 645	    j++;
 646	    }
 647     Helps[j] = '\0';
 648     }
 649  else {
 650       i=Helps-cq2->Lines[cq2->cur].Lstring();
 651       s=copy(cq2->Lines[cq2->cur].Lstring,0,i);
 652       sprintf(CharStr,"%2.2f",float(cq2->tabpos[tabs-1])/ 470.0);
 653       s+="\\hspace*{";
 654       s+=CharStr;
 655       s+="cm}";
 656       s+=copy(cq2->Lines[cq2->cur].Lstring,i + 5*tabs,length(cq2->Lines[cq2->cur].Lstring)- i - 5*tabs);
 657       cq2->Lines[cq2->cur].Lstring=s;
 658       }
 659  return true;
 660}
 661
 662
 663static bool Fix1SectionStr(char *aline, const char *opt)
 664{
 665char *str, *str2;
 666int optlen;
 667int r;
 668
 669  if((str=StrStr(aline, opt)) == NULL) return false;
 670  optlen = strlen(opt);
 671	
 672  str2 = str+1;
 673  for(r=0;r<optlen-1;r++)
 674    {
 675    *str2++=' ';
 676    }
 677
 678  str2 = str + optlen;
 679  r = 0;
 680  while(*str2!=0)
 681    {
 682    if(*str2=='{') r++;
 683    if(*str2=='}')
 684      if(r==0)
 685        {
 686        *str2=' ';
 687        strcpy(str,str+optlen);		// Overlapping regions
 688        //i = strlen(aline) - optlen;
 689        //memmove(str,str+7,strlen(str+7));str[i]=0; // Overlapping regions, but terminating 0 must be added for memmove.	
 690	return true;
 691	}
 692      else r--;
 693    str2++;
 694    }
 695  return false;
 696}
 697
 698
 699static void OptimSectionStr(char *aline)
 700{
 701boolean optimized;
 702int i;
 703
 704  do {     
 705     if(aline == NULL) return;
 706
 707
 708     i = strlen(aline);
 709     while(aline[i]==' ')
 710	{
 711	aline[i--] = 0;
 712	}
 713     if(*aline == 0) return;
 714
 715     //i still contains strlen(aline)
 716     if(aline[i-1] == '\\' && aline[i-2] == '\\')
 717	{
 718	aline[i-2] = '\0';
 719	i -= 2;
 720	}
 721
 722     optimized =  Fix1SectionStr(aline, "{\\bfseries");
 723     optimized |= Fix1SectionStr(aline, "{\\bf");
 724     optimized |= Fix1SectionStr(aline, "{\\large");
 725     optimized |= Fix1SectionStr(aline, "{\\Large");
 726     optimized |= Fix1SectionStr(aline, "{\\LARGE");
 727  } while(optimized);
 728}
 729
 730
 731static int FixBracket(string & Line)
 732{
 733  if (Line == "") return 0;
 734
 735  Line="{}"+Line;
 736
 737  return length(Line);
 738}
 739
 740
 741static char *TryToRemoveGeneric(char *Helps, const char *Generic)
 742{
 743  int i = 0, j;
 744
 745  if (Helps == NULL) return NULL;
 746  if (Generic == NULL) return NULL;
 747  if (*Helps == 0) return NULL;
 748  if (*Generic == 0) return NULL;
 749
 750  Helps = StrStr(Helps, Generic);
 751  if(Helps == NULL) return NULL;
 752
 753  j = strlen(Generic);
 754
 755  while (Helps[j] == ' ')
 756  	{
 757        j++;
 758        }
 759  if (Helps[j++] != '}') return Helps+1;
 760
 761  while (Helps[j] != '\0')
 762         {
 763	 Helps[i] = Helps[j];
 764	 i++;
 765	 j++;
 766	 } 
 767  Helps[i] = '\0';
 768  return Helps;
 769}
 770
 771
 772static char *TryToRemoveSelectLanguage(char * Helps)
 773{
 774  int i = 0, j, k;
 775
 776  if (Helps == NULL) return NULL;
 777  if (*Helps == 0) return NULL;
 778  Helps = StrStr(Helps, "\\selectlanguage{");
 779  if (Helps == NULL) return NULL;
 780
 781  j = 16;				// strlen("\\selectlanguage{");
 782  while (Helps[j] != '}')
 783  	{
 784	if(Helps[j]==0) return Helps+1;
 785        j++;
 786        }
 787  if (Helps[j++] != '}') return Helps+1;
 788
 789  k = j;
 790  while (Helps[j] == '~' || Helps[j] == ' ')
 791  	{
 792        j++;
 793        }
 794
 795  if (Helps[j++] != '\\') return Helps+1;
 796  if (Helps[j++] != 's') return Helps+1;
 797  if (Helps[j++] != 'e') return Helps+1;
 798  if (Helps[j++] != 'l') return Helps+1;
 799  if (Helps[j++] != 'e') return Helps+1;
 800  if (Helps[j++] != 'c') return Helps+1;
 801  if (Helps[j++] != 't') return Helps+1;
 802  if (Helps[j++] != 'l') return Helps+1;
 803  if (Helps[j++] != 'a') return Helps+1;
 804  if (Helps[j++] != 'n') return Helps+1;
 805  if (Helps[j++] != 'g') return Helps+1;
 806  if (Helps[j++] != 'u') return Helps+1;
 807  if (Helps[j++] != 'a') return Helps+1;
 808  if (Helps[j++] != 'g') return Helps+1;
 809  if (Helps[j++] != 'e') return Helps+1;
 810  if (Helps[j++] != '{') return Helps+1;
 811
 812  while (Helps[k] != '\0')
 813         {
 814	 Helps[i] = Helps[k];
 815	 k++;
 816	 i++;
 817	 } 
 818  Helps[i] = '\0';
 819  return Helps;		//one command removed, try again next command
 820}
 821
 822
 823static char *TryToRemoveLineNumbering(char * Helps)
 824{
 825  int i = 0, j, k;
 826
 827  if (Helps == NULL) return NULL;
 828  if (*Helps == 0) return NULL;
 829  Helps = StrStr(Helps, "\\begin{linenumbers}");
 830  if (Helps == NULL) return NULL;
 831
 832  j = 19;				// strlen("\\begin{linenumbers}");
 833  k = j;  
 834
 835  while (Helps[j]==' ' || Helps[j]=='\t')
 836  	{
 837        j++;
 838        }
 839  
 840  if (Helps[j++] != '\\') return Helps+1;
 841  if (Helps[j++] != 'e') return Helps+1;
 842  if (Helps[j++] != 'n') return Helps+1;
 843  if (Helps[j++] != 'd') return Helps+1;
 844  if (Helps[j++] != '{') return Helps+1;
 845  if (Helps[j++] != 'l') return Helps+1;
 846  if (Helps[j++] != 'i') return Helps+1;
 847  if (Helps[j++] != 'n') return Helps+1;
 848  if (Helps[j++] != 'e') return Helps+1;
 849  if (Helps[j++] != 'n') return Helps+1;
 850  if (Helps[j++] != 'u') return Helps+1;
 851  if (Helps[j++] != 'm') return Helps+1;
 852  if (Helps[j++] != 'b') return Helps+1;
 853  if (Helps[j++] != 'e') return Helps+1;
 854  if (Helps[j++] != 'r') return Helps+1;
 855  if (Helps[j++] != 's') return Helps+1;
 856  if (Helps[j++] != '}') return Helps+1;
 857
 858	/* Copy spaces among linenum commands */
 859  while (Helps[k]!='\0' && Helps[k]!='\\')  
 860	{
 861	Helps[i] = Helps[k];
 862	i++; k++;
 863	}    
 864  
 865	/* Copy rest of a text */
 866  while (Helps[j] != '\0')
 867         {
 868	 Helps[i] = Helps[j];
 869	 i++;
 870	 j++;
 871	 } 
 872  Helps[i] = '\0';
 873  return Helps;		//one command removed, try again next command
 874}
 875
 876
 877/** Check whether line contains any user printable text, or control sequences only.
 878 * @return	1 when line contains sequences only; 0 printable text is present. */
 879int EmptyLine(const string & s)
 880{
 881int i;
 882char ch;
 883
 884i=0;
 885while(i<length(s))
 886	{
 887        ch=s[i++];
 888        if(ch==' ') continue;
 889        if(ch=='\t') continue;
 890	if(ch=='}') continue;
 891	if(ch=='{') continue;
 892	if(ch=='\\')
 893	   {
 894	   if(s[i]=='/')	 //ignore \/
 895		 {
 896		 i++;
 897		 continue;
 898		 }
 899           if(s[i]=='>')	 //ignore \>
 900		 {
 901		 i++;
 902		 continue;
 903		 }
 904
 905	   if(s[i]=='b')	 //ignore \bf
 906		 {
 907		 i++;
 908		 if(s[i++]!='f') return(0);
 909		 continue;
 910		 }
 911
 912	   if(s[i]=='c')
 913		 {
 914		 i++;
 915		 if(s[i]=='l')	//ignore \clubpenalty number
 916		    {
 917		    i++;
 918		    if(s[i++]!='u') return(0);
 919		    if(s[i++]!='b') return(0);
 920		    if(s[i++]!='p') return(0);
 921		    if(s[i++]!='e') return(0);
 922		    if(s[i++]!='n') return(0);
 923		    if(s[i++]!='a') return(0);
 924		    if(s[i++]!='l') return(0);
 925		    if(s[i++]!='t') return(0);
 926		    if(s[i++]!='y') return(0);
 927		    while(s[i]==' ') i++;
 928		    while(isdigit(s[i])) i++;
 929		    continue;
 930		    }
 931		 if(s[i++]!='o') return(0); //ignore \color{\anything}
 932		 if(s[i++]!='l') return(0);
 933		 if(s[i++]!='o') return(0);
 934		 if(s[i++]!='r') return(0);
 935
 936		 if(s[i++]!='{') return(0);
 937		 while(s[i++]!='}')
 938			 {
 939			 if(i>=length(s)) return(1);
 940			 };
 941		 continue;
 942		 }
 943
 944	   if(s[i]=='f')	 //ignore \foottext{\anything}
 945		 {
 946		 i++;
 947		 if(s[i++]!='o') return(0);
 948		 if(s[i++]!='o') return(0);
 949		 if(s[i++]!='t') return(0);
 950		 if(s[i++]!='t') return(0);
 951		 if(s[i++]!='e') return(0);
 952		 if(s[i++]!='x') return(0);
 953		 if(s[i++]!='t') return(0);
 954
 955		 if(s[i++]!='{') return(0);
 956		 while(s[i++]!='}')
 957			 {
 958			 if(i>=length(s)) return(1);
 959			 };
 960		 continue;
 961		 }
 962
 963
 964	   if(s[i]=='h')	 //ignore \headtext{\anything}
 965		 {
 966		 i++;
 967		 if(s[i++]!='e') return(0);
 968		 if(s[i++]!='a') return(0);
 969		 if(s[i++]!='d') return(0);
 970		 if(s[i++]!='t') return(0);
 971		 if(s[i++]!='e') return(0);
 972		 if(s[i++]!='x') return(0);
 973		 if(s[i++]!='t') return(0);
 974
 975		 if(s[i++]!='{') return(0);
 976		 while(s[i++]!='}')
 977			 {
 978			 if(i>=length(s)) return(1);
 979			 };
 980		 continue;
 981		 }
 982
 983	   if(s[i]=='i')	 //ignore \it
 984		 {
 985		 i++;
 986		 if(s[i++]!='t') return(0);
 987		 continue;
 988		 }
 989
 990	   if(s[i]=='l')	 //ignore \label{anything}
 991		 {
 992		 i++;
 993		 if(s[i++]!='a') return(0);
 994		 if(s[i++]!='b') goto TryLanguage;
 995		 if(s[i++]!='e') return(0);
 996		 if(s[i++]!='l') return(0);
 997		 if(s[i++]!='{') return(0);
 998		 while(s[i++]!='}')
 999			 {
1000			 if(i>=length(s)) return(1);
1001			 };
1002		 continue;
1003
1004TryLanguage:            	//ignore \language anything
1005		 i--;
1006		 if(s[i++]!='n') return(0);
1007		 if(s[i++]!='g') return(0);
1008		 if(s[i++]!='u') return(0);
1009		 if(s[i++]!='a') return(0);
1010		 if(s[i++]!='g') return(0);
1011		 if(s[i++]!='e') return(0);
1012		 if(s[i++]!='=') return(0);
1013		 if(s[i++]!='\\') return(0);
1014
1015		 while(isalpha(s[i]))
1016			 {
1017			 i++;
1018			 }
1019		 continue;
1020		 };
1021
1022	   if(s[i]=='o')	 //ignore  \onecolumn
1023		 {
1024		 i++;
1025		 if(s[i++]!='n') return(0);
1026		 if(s[i++]!='e') return(0);
1027		 goto ColumnText;
1028		 }
1029
1030	   if(s[i]=='p')
1031		 {
1032		 i++;
1033                 if(s[i]=='a')		//ignore  \pagenumpos{...}
1034                   {
1035                   i++;
1036                   if(s[i++]!='g') return(0);
1037		   if(s[i++]!='e') return(0);
1038		   if(s[i++]!='n') return(0);
1039                   if(s[i++]!='u') return(0);
1040		   if(s[i++]!='m') return(0);
1041                   if(s[i++]!='p') return(0);
1042                   if(s[i++]!='o') return(0);
1043                   if(s[i++]!='s') return(0);
1044                   if(s[i++]!='{') return(0);
1045 		   while(s[i]!='}' && s[i]!=0)
1046                     {i++;}
1047 		   continue;
1048                   }
1049		 if(s[i++]!='e') return(0);	//ignore  \penalty NUM
1050		 if(s[i++]!='n') return(0);
1051		 if(s[i++]!='a') return(0);
1052                 if(s[i++]!='l') return(0);
1053		 if(s[i++]!='t') return(0);
1054                 if(s[i++]!='y') return(0);
1055	         while(s[i]==' ') i++;
1056	         while(isdigit(s[i])) i++;
1057                 continue;
1058	         };
1059
1060	   if(s[i]=='s')
1061		 {
1062		 i++;
1063		 if(s[i]=='c') continue;	//ignore \sc
1064
1065		 if(s[i++]!='e') return(0);  
1066                 if(s[i]=='l')
1067		   {				//ignore  \selectlanguage{lang}
1068		   i++;
1069		   if(s[i++]!='e') return(0);
1070                   if(s[i++]!='c') return(0);
1071  		   if(s[i++]!='t') return(0);
1072		   if(s[i++]!='l') return(0);
1073		   if(s[i++]!='a') return(0);
1074                   if(s[i++]!='n') return(0);
1075                   if(s[i++]!='g') return(0);
1076                   if(s[i++]!='u') return(0);
1077                   if(s[i++]!='a') return(0);
1078                   if(s[i++]!='g') return(0);
1079                   if(s[i++]!='e') return(0);
1080                   if(s[i++]!='{') return(0);
1081 		   while(s[i]!='}' && s[i]!=0) i++;
1082 		   continue;
1083		   }
1084		 
1085		 if(s[i++]!='t') return(0);	//ignore  \setcounter{counter}{number}
1086                 if(s[i++]!='c') return(0);
1087		 if(s[i++]!='o') return(0);
1088		 if(s[i++]!='u') return(0);
1089		 if(s[i++]!='n') return(0);
1090                 if(s[i++]!='t') return(0);
1091                 if(s[i++]!='e') return(0);
1092                 if(s[i++]!='r') return(0);
1093
1094                 if(s[i++]!='{') return(0);
1095                 while(s[i]!='}' && s[i]!=0) i++;
1096                 if(s[++i]!='{') return(0);
1097                 while(s[i]!='}' && s[i]!=0) i++;
1098                 i++;
1099
1100		 continue;
1101		 };
1102
1103	   if(s[i]=='T')	 //ignore  \TAB
1104		 {
1105		 i++;
1106		 if(s[i++]!='A') return(0);
1107		 if(s[i++]!='B') return(0);
1108		 continue;
1109		 }
1110
1111	   if(s[i]=='t')	 //ignore  \twocolumn
1112		 {
1113		 i++;
1114		 if(s[i]!='w') goto ThisPageStyle;
1115		 i++;
1116ColumnText:	 if(s[i++]!='o') return(0);
1117		 if(s[i++]!='c') return(0);
1118		 if(s[i++]!='o') return(0);
1119		 if(s[i++]!='l') return(0);
1120		 if(s[i++]!='u') return(0);
1121		 if(s[i++]!='m') return(0);
1122		 if(s[i++]!='n') return(0);
1123		 if(s[i]==0) return(1);
1124		 if(s[i++]!=' ') return(0);
1125		 continue;
1126
1127ThisPageStyle:   i++;
1128		 if(s[i++]!='h') return(0);
1129		 if(s[i++]!='i') return(0);
1130		 if(s[i++]!='s') return(0);
1131		 if(s[i++]!='p') return(0);
1132		 if(s[i++]!='a') return(0);
1133		 if(s[i++]!='g') return(0);
1134		 if(s[i++]!='e') return(0);
1135		 if(s[i++]!='s') return(0);
1136		 if(s[i++]!='t') return(0);
1137		 if(s[i++]!='y') return(0);
1138		 if(s[i++]!='l') return(0);
1139		 if(s[i++]!='e') return(0);
1140		 if(s[i++]!='{') return(0);
1141
1142		 while(isalpha(s[i]))
1143		       {
1144		       i++;
1145		       }
1146		 if(s[i++]!='}') return(0);
1147		 continue;
1148		 }
1149
1150	   if(s[i]=='v')
1151	         {
1152                 i++;
1153                 if(s[i++]!='s') return(0);
1154		 switch(s[i++])
1155                   {
1156				//ignore  \vskip xxcm
1157		     case 'k': if(s[i++]!='i') return(0);
1158                               if(s[i++]!='p') return(0);
1159                               if(s[i++]!=' ') return(0);
1160                               while(s[i]==' ') i++;
1161                               while(isdigit(s[i]) || (s[i]=='-') || (s[i]=='.')) i++;
1162		               if(s[i]!='c') continue;
1163		               i++;
1164		               if(s[i]!='m') continue;
1165		               i++;
1166			       break;
1167				//ignore  \vspace {xx cm}
1168                     case 'p': if(s[i++]!='a') return(0);
1169                               if(s[i++]!='c') return(0);
1170			       if(s[i++]!='e') return(0);
1171			       while(s[i]==' ') i++;
1172			       if(s[i++]!='{') return(0);
1173			       while(s[i]!='}')
1174			         {
1175				 if(s[i]==0) return(1);
1176				 i++;
1177                                 }
1178			       break;
1179                     default:  return(0); 
1180                   }
1181                 continue;
1182	         };
1183	  if(s[i]=='w')	//ignore \widowpenalty number
1184		{
1185		i++;
1186		if(s[i++]!='i') return(0);
1187		if(s[i++]!='d') return(0);
1188		if(s[i++]!='o') return(0);
1189		if(s[i++]!='w') return(0);
1190 		if(s[i++]!='p') return(0);
1191 		if(s[i++]!='e') return(0);
1192 		if(s[i++]!='n') return(0);
1193 		if(s[i++]!='a') return(0);
1194 		if(s[i++]!='l') return(0);
1195 		if(s[i++]!='t') return(0);
1196 		if(s[i++]!='y') return(0);
1197 		while(s[i]==' ') i++;
1198 		while(isdigit(s[i])) i++;
1199 		continue;
1200		}
1201           }
1202        return(0);		//Line is not Empty
1203        }
1204return(1);			//Line is Empty
1205}
1206
1207
1208/** This function groups multiple rows inside one table cell into a \shortstack*/
1209static int OptimizeMultiRows(string & aLine)
1210{
1211string NewLine,Cell;
1212int i;
1213char *HelpS,*aLinePtr,OldChar;
1214int shortstack;
1215
1216HelpS=StrStr(aLine(), "\\penalty-10001");
1217shortstack=false;
1218aLinePtr=aLine();
1219OldChar=0;
1220while(*aLinePtr!=0)
1221	{
1222	if(aLinePtr==HelpS)
1223	     {
1224	     i=0;
1225	     HelpS=StrStr(++HelpS, "\\penalty-10001");
1226	     aLinePtr+=strlen("\\penalty-10001");
1227	     while(aLinePtr[i]==' ')
1228		 {
1229		 if(aLinePtr[i]==0)   goto Reject;
1230		 if(aLinePtr[i]=='&') goto Reject;
1231		 if(aLinePtr[i]=='\\')
1232		   {
1233		   if(aLinePtr[++i]=='\\') goto Reject;
1234		   }
1235
1236		 i++;
1237		 }
1238
1239	     if(!shortstack) Cell="\\shortstack{"+Cell;
1240	     Cell+="\\\\";
1241	     if(aLinePtr[i]=='[') Cell+="{}";
1242			     else if(*aLinePtr!=' ') Cell+=' ';
1243	     shortstack=3;
1244	     }
1245
1246Reject:	if(OldChar!='\\')
1247	  if(*aLinePtr==0 || *aLinePtr=='&' || (*aLinePtr=='\\' && aLinePtr[1]=='\\'))
1248	     {
1249	     NewLine+=Cell;
1250	     if(shortstack)
1251		 {
1252		 if(shortstack>1) NewLine+="\\strut";
1253		 NewLine+='}';
1254		 }
1255
1256	     NewLine+=OldChar=*aLinePtr++;
1257	     Cell="";
1258	     shortstack=0;
1259	     continue;
1260	     }
1261
1262	if(*aLinePtr!=' ') shortstack&=~2;
1263	Cell+=OldChar=*aLinePtr++;
1264	}
1265
1266NewLine+=Cell;
1267if(shortstack)
1268   {
1269   if(shortstack>1) NewLine+="\\strut";
1270   NewLine+='}';
1271   }
1272
1273aLine=NewLine;
1274return(shortstack);
1275}
1276
1277
1278/** fix occurence \/ in the vertical mode - remove it */
1279static void FixItallicAlignment(TconvertedPass2 & cq2, string *aLineStr)
1280{
1281  if( (cq2.Lines[cq2.pre].Lstring=="")&&(length(*aLineStr)>=2) )
1282    if (  (*aLineStr)[0]=='\\' &&  (*aLineStr)[1]=='/' )
1283	*aLineStr=copy(*aLineStr,2,length(*aLineStr)-2);
1284
1285  if( (length(cq2.Lines[cq2.next].Lstring)>=2) &&
1286     (*aLineStr=="" ||
1287       cq2.Lines[cq2.cur].line_term=='h' || cq2.Lines[cq2.cur].line_term=='p') )
1288    if( (cq2.Lines[cq2.next].Lstring)[0]=='\\' &&  (cq2.Lines[cq2.next].Lstring)[1]=='/' )
1289	cq2.Lines[cq2.next].Lstring=copy(cq2.Lines[cq2.next].Lstring,2,length(cq2.Lines[cq2.next].Lstring)-2);
1290}
1291
1292
1293/** move } from the beginning of next line to the current line, only when some attribute is opened. */
1294static void MoveCurlyBrace(TconvertedPass2 & cq2)
1295{
1296const char *CHelpS;
1297TLinePass2 *NextLine = &cq2.Lines[cq2.next];
1298TLinePass2 *CurLine = &cq2.Lines[cq2.cur];
1299
1300  while(NextLine->attr.Opened_Depth>0)
1301  {
1302    CHelpS = NULL;
1303    
1304		// check whether curly brace belongs to a style opened
1305    if(NextLine->attr.Closed_Depth>0)
1306    {
1307      if(NextLine->attr.Opened_Depth >= NextLine->attr.Closed_Depth)
1308        {		// try to remove all string belonging to the attr
1309        CHelpS = StyleOpCl[NextLine->attr.stack[NextLine->attr.Opened_Depth-1]].Close;
1310MatchAgain:
1311        if(StrNCmp(NextLine->Lstring(), CHelpS, strlen(CHelpS)))
1312	  {
1313	  if(CHelpS[0]=='\\' && CHelpS[1]=='/') // give a last chance to match without \/
1314	    {
1315	    CHelpS += 2;
1316	    if(*CHelpS!=0) goto MatchAgain;
1317	    }
1318	  break;		// close command differs, break the loop
1319          }
1320        NextLine->attr.Opened_Depth--;
1321        }
1322      NextLine->attr.Closed_Depth--;
1323    }
1324
1325    if(CHelpS==NULL)
1326    {
1327      if(NextLine->Lstring[0]!='}') break;
1328      CHelpS = "}";
1329    }
1330  
1331		// remove string from the next line
1332    NextLine->Lstring = copy(NextLine->Lstring,strlen(CHelpS),length(NextLine->Lstring)-strlen(CHelpS));
1333
1334		// and append it to a current line    
1335    if(CurLine->Lstring=="" && cq2.Lines[cq2.pre].Lstring!="")
1336        {	// When a current line is empty, add \n	
1337	CurLine->Lstring += CHelpS;
1338	CurLine->Lstring += "\n";
1339	}
1340    else
1341        CurLine->Lstring += CHelpS;
1342    }
1343}
1344
1345
1346
1347static const char *GenericStr[] = 
1348	{"{\\bf", "{\\footnotesize", "{\\it",
1349	 "{\\large", "{\\Large", "{\\LARGE", "{\\rm", 
1350	 "{\\sc", "{\\small","{\\tt"};
1351
1352
1353/*******************---PASS2---******************/
1354void Convert_second_pass(FILE *Strip, FILE *table, FILE *FileOut, FILE *log,FILE *ErrorFile)
1355{
1356#ifdef DEBUG
1357  fprintf(log,"\n#Convert_second_pass() ");fflush(log);
1358#endif
1359int i, len_reg;
1360string *aLineStr, s;
1361char *HelpS;
1362TconvertedPass2 cq2;
1363
1364  if(FileOut==NULL) return;
1365
1366  cq2.table = table;
1367  cq2.Strip = Strip;
1368  cq2.LaTeX = FileOut;
1369  cq2.log   = log;
1370  cq2.err   = ErrorFile;
1371
1372  cq2.pre = 0;
1373  cq2.cur = 1;
1374  cq2.next = 2;
1375  cq2.next2 = 3;
1376  cq2.LangCount = 0;
1377
1378  cq2.Lines[cq2.pre].envir = ' ';
1379  cq2.Lines[cq2.pre].new_tabset = false;
1380
1381  cq2.just_envir_closed = true;
1382  cq2.LineSpacing=0;
1383  cq2.Col2Break=1;
1384
1385  for(i=0; i<=3; i++)
1386      {
1387      cq2.Lines[i].Lstring = "";
1388      cq2.Lines[i].Empty   = true;
1389      cq2.Lines[i].Columns = 1;
1390      cq2.Lines[i].InhibitBsBslash = false;
1391      InitAttr(cq2.Lines[i].attr);
1392      }
1393
1394
1395  cq2.rownum = 1;
1396  cq2.perc.Init(0, num_of_lines_stripfile, _("Second pass:"));
1397
1398  Latex_head(&cq2);
1399			/*read current row from strip file*/
1400  Read_TableEntry(&cq2, cq2.cur);
1401  fGets2(Strip, cq2.Lines[cq2.cur].Lstring );
1402  cq2.Lines[cq2.cur].Empty = EmptyLine(cq2.Lines[cq2.cur].Lstring);
1403			/*read next row from strip file*/
1404  fGets2(Strip, cq2.Lines[cq2.next].Lstring);
1405  Read_TableEntry(&cq2, cq2.next);
1406  cq2.Lines[cq2.next].Empty = EmptyLine(cq2.Lines[cq2.next].Lstring);
1407				/*read row after next row from strip file*/
1408  fGets2(Strip, cq2.Lines[cq2.next2].Lstring);
1409  Read_TableEntry(&cq2, cq2.next2);
1410  cq2.Lines[cq2.next2].Empty = EmptyLine(cq2.Lines[cq2.next2].Lstring);
1411
1412
1413  while((!feof(Strip) || cq2.Lines[cq2.cur].Lstring != "" || cq2.Lines[cq2.next].Lstring != "" || cq2.Lines[cq2.next2].Lstring != ""))
1414     {
1415     Update_global_information(&cq2);
1416
1417     if(Verbosing >= 1)		//actualise a procentage counter
1418	      cq2.perc.Actualise(cq2.rownum);
1419
1420     aLineStr = &cq2.Lines[cq2.cur].Lstring;
1421
1422     if(TIPA>=2)	// Unsafe Tipa
1423       {
1424       *aLineStr = replacesubstring(*aLineStr,"\\!","\\!{}");
1425       }
1426
1427     len_reg = length(*aLineStr);
1428
1429	/* Remove all language mess if only one language is present in a document. */
1430     if(cq2.LangCount<2)
1431       {
1432       HelpS = StrStr((*aLineStr)(), "\\selectlanguage{");
1433       if(HelpS!=NULL)
1434         {
1435	 i=*HelpS;
1436	 *HelpS = NULL;
1437	 s = (*aLineStr)();
1438	 *HelpS = i;
1439
1440	 HelpS+=16;
1441
1442	 for(i=0; i<strlen(HelpS); i++)
1443	   {
1444	   if(HelpS[i]==0) break;
1445	   if(HelpS[i]=='}')		// remove everything till closing brace
1446	     {
1447	     s += HelpS+i+1;
1448	     *aLineStr = s;
1449             break;
1450	     }
1451	   }	         
1452	 }
1453       }
1454
1455        /* Try to find and remove useless trailing TAB */
1456    if(cq2.Lines[cq2.next].line_term=='p' || cq2.Lines[cq2.next].line_term=='h')
1457        {
1458        int pos = -1;
1459        for(i=length(cq2.Lines[cq2.next].Lstring)-1; i>=1; i--)
1460            {
1461            char ch = (cq2.Lines[cq2.next].Lstring)[i];
1462            if(isspace(ch))
1463                {
1464                pos = i;
1465                continue;
1466                }
1467            if(ch=='>' && (cq2.Lines[cq2.next].Lstring)[i-1]=='\\')
1468                {
1469                pos = i - 1;
1470                i--;
1471                continue;
1472                }
1473            break;
1474            }
1475        if(pos>=0)
1476            {
1477            cq2.Lines[cq2.next].Lstring = copy(cq2.Lines[cq2.next].Lstring, 0, pos);
1478            }
1479        }
1480
1481	/* Fix an empty environments C and L. */
1482     if(((cq2.Lines[cq2.cur].envir==' ')||(cq2.Lines[cq2.cur].envir=='Q')||(cq2.Lines[cq2.cur].envir=='B')) &&
1483	 (cq2.Lines[cq2.next].Empty>0) && (cq2.Lines[cq2.next2].envir!='!') )
1484	   {
1485	   if(cq2.Lines[cq2.next].envir == 'C' || cq2.Lines[cq2.next].envir == 'L')
1486		{
1487		cq2.Lines[cq2.next].envir = ' ';
1488		}
1489	   }
1490
1491	/* Fix tabs, which are not in the tabbing environment */
1492    HelpS = StrStr((*aLineStr)(), "\\TAB");
1493    if(HelpS!=NULL)
1494      {
1495      if(HelpS[4]==' ' || HelpS[4]==0)
1496        {
1497	FixTabs(&cq2,HelpS); /* Fix tabs must be called first because it can change environment */
1498	check(*aLineStr);
1499	}
1500      }
1501    if(cq2.Lines[cq2.cur].envir == 'T')  /* fix wrongly accented chars in Tabbing enviroment */
1502	{
1503	if(StrStr((*aLineStr)(), "\\'{")!=NULL)
1504	   *aLineStr=replacesubstring(*aLineStr,"\\'{","\\a'{");
1505	if(StrStr((*aLineStr)(), "\\`{")!=NULL)
1506	   *aLineStr=replacesubstring(*aLineStr,"\\`{","\\a`{");
1507	}
1508
1509
1510    if(FixSpaces) {   /* More than two spaces must be fixed. */
1511      if(toupper(cq2.Lines[cq2.cur].envir) != 'Q') {
1512	for(i = 1; i < len_reg; i++)
1513	  {
1514	  if ((*aLineStr)[i] == ' ' && (*aLineStr)[i+1] == ' ')
1515	    {
1516	    (*aLineStr)[i+1] = '~';
1517	    }
1518	  }
1519      }
1520    }
1521
1522    /* Correct illegal argument which begins '['. */
1523    if(len_reg >= 1 && (*aLineStr)[1] == '[' ||
1524	len_reg >= 2 && (*aLineStr)[1] == ' ' && (*aLineStr)[2] == '[') {
1525      len_reg = FixBracket(*aLineStr);
1526    }
1527
1528
1529	/* Try to repair \section{ */
1530    if(OptimizeSection)
1531      {
1532      if (StrStr((*aLineStr)(), "\\part{") != NULL)
1533          {
1534	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
1535//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
1536	  OptimSectionStr(strstr((*aLineStr)(), "\\part{") + 6L);
1537	  check(*aLineStr);
1538	  }
1539      if (StrStr((*aLineStr)(), "\\chapter{") != NULL)
1540	  {
1541	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
1542//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
1543	  OptimSectionStr(strstr((*aLineStr)(), "\\chapter{") + 9L);
1544	  check(*aLineStr);
1545	  }
1546      if (StrStr((*aLineStr)(), "\\section{") != NULL)
1547	  {
1548	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
1549//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
1550	  OptimSectionStr(strstr((*aLineStr)(), "\\section{") + 9L);
1551	  check(*aLineStr);
1552	  }
1553      if (StrStr((*aLineStr)(), "\\subsection{") != NULL)
1554	  {
1555	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
1556//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
1557	  OptimSectionStr(strstr((*aLineStr)(), "\\subsection{") + 12L);
1558	  check(*aLineStr);
1559	  }
1560      if (StrStr((*aLineStr)(), "\\subsubsection{") != NULL)
1561	  {
1562	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
1563//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
1564	  OptimSectionStr(strstr( (*aLineStr)(), "\\subsubsection{") + 15L);
1565	  check(*aLineStr);
1566	  }
1567      if (StrStr((*aLineStr)(), "\\paragraph{") != NULL)
1568	  {
1569	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
1570//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
1571	  OptimSectionStr(strstr( (*aLineStr)(), "\\paragraph{") + 11L);
1572	  check(*aLineStr);
1573	  }
1574      if (StrStr((*aLineStr)(), "\\subparagraph{") != NULL)
1575	  {
1576	  cq2.Lines[cq2.cur].InhibitBsBslash = true;
1577//	  cq2.Lines[cq2.next].InhibitBsBslash = true;
1578	  OptimSectionStr(strstr((*aLineStr)(), "\\subparagraph{") + 14L);
1579	  check(*aLineStr);
1580	  }
1581       }
1582
1583
1584	/* Some optimizations of text on current line */
1585
1586			//fix beginning paragraph with \raise command
1587    if(cq2.Lines[cq2.pre].Lstring=="" && length(*aLineStr)>=6)
1588	{
1589	if(!strncmp((*aLineStr),"\\raise",6))
1590		*aLineStr="\\strut"+*aLineStr;
1591	}
1592
1593          // fix occurence \/ in the vertical mode - remove it
1594    FixItallicAlignment(cq2,aLineStr);
1595
1596	  // move } from the beginning of next line to the current line, only when some attribute is opened.
1597    MoveCurlyBrace(cq2);
1598
1599	//fix \/ again - moving } could free \/
1600    FixItallicAlignment(cq2,aLineStr);    
1601
1602    if(Open_environment(&cq2))    //this procedure tests change of the environment
1603	{
1604	i=cq2.cur;	//opening enviroment rejected for an empty line
1605	cq2.cur=cq2.next;
1606	cq2.next=cq2.next2;
1607	cq2.next2=i;
1608
1609	fGets2(Strip, cq2.Lines[cq2.next2].Lstring);
1610	cq2.Lines[cq2.next2].Columns = cq2.Lines[cq2.next].Columns;
1611	Read_TableEntry(&cq2, cq2.next2);
1612
1613	if((cq2.Lines[cq2.cur].envir=='i')&&(cq2.Lines[cq2.pre].envir=='i'))
1614			cq2.Lines[cq2.pre].envir='I';
1615        if((cq2.Lines[cq2.cur].envir=='I')&&(cq2.Lines[cq2.pre].envir=='I'))
1616			cq2.Lines[cq2.pre].envir='i';
1617
1618        goto SkipThisLine;
1619        }
1620
1621
1622		//fix closed attributes problem
1623    if(ClosedAttr(cq2.Lines[cq2.cur].attr)) /* Are attributes closed? */
1624      if(*aLineStr == "")
1625	 {
1626	 if(cq2.Lines[cq2.next].attr.Closed_Depth==cq2.Lines[cq2.cur].attr.Closed_Depth)
1627		{
1628		for(i=0;i<cq2.Lines[cq2.next].attr.Closed_Depth;i++)
1629                	{
1630                        if(cq2.Lines[cq2.next].attr.stack[i]!=cq2.Lines[cq2.cur].attr.stack[i])
1631				{	//attributes are not same for next line
1632                                goto FixOpen;
1633				}
1634			}
1635		cq2.Lines[cq2.next].attr.Opened_Depth=cq2.Lines[cq2.cur].attr.Opened_Depth;
1636		}
1637	     else {
1638FixOpen:	  Open_All_Attr(cq2.Lines[cq2.cur].attr,*aLineStr);
1639		  }
1640         }
1641
1642
1643  if (*aLineStr != "" || cq2.Lines[cq2.next].envir=='!')
1644	 {		/* Attributes are closed */
1645	 if(cq2.Lines[cq2.cur].LineFlag & 1  && (*aLineStr == '%'||*aLineStr == ""))
1646		 {
1647		 if (Change_envir_EOL(&cq2))
1648		   if(!cq2.just_envir_closed) Close_environment(&cq2);
1649		 goto EmptyThisLine; /* Remove empty line added by wp2latex */
1650		 }
1651
1652	 if(cq2.Lines[cq2.cur].attr.Closed_Depth > cq2.Lines[cq2.cur].attr.Opened_Depth)
1653		{
1654		Open_All_Attr(cq2.Lines[cq2.cur].attr,s);
1655		*aLineStr=s+*aLineStr;
1656		}
1657
1658	 HelpS = StrStr((*aLineStr)(), "@{\\");   /*ignore tabular formater @{...}*/
1659	 if(HelpS==NULL)
1660	   {
1661	   for(i=0;i<sizeof(GenericStr)/sizeof(char*);i++)
1662	     {
1663	     HelpS = (*aLineStr)();   /**/
1664	     do {
1665	        HelpS = TryToRemoveGeneric(HelpS,GenericStr[i]);
1666	        } while(HelpS!=NULL);
1667             }
1668	   }
1669
1670		/* remove duplicit items \selectlanguage */
1671	 HelpS = (*aLineStr)();
1672	 do {
1673	    HelpS = TryToRemoveSelectLanguage(HelpS);
1674	    } while(HelpS);
1675
1676	 HelpS = (*aLineStr)();
1677	 do {
1678	    HelpS = TryToRemoveLineNumbering(HelpS);
1679	    } while(HelpS);
1680	   
1681	 check(*aLineStr);
1682
1683	 if(cq2.Lines[cq2.cur].envir=='B')
1684		{
1685		HelpS=StrStr((*aLineStr)(), "\\penalty-10001");
1686		if(HelpS!=NULL)
1687		  {
1688		  if(OptimizeMultiRows(*aLineStr))
1689		    if(cq2.Lines[cq2.next].envir=='!' && cq2.Lines[cq2.next].Lstring=="%")
1690		       *aLineStr+="\\\\";
1691		  }
1692		}
1693
1694	 if(length(*aLineStr)>0)
1695	   if((i=fputs(*aLineStr,cq2.LaTeX))==EOF) /*here is written current line*/
1696			{
1697			RunError(0x20,"");
1698			}
1699	 }
1700
1701			   /*Is it possible to expand the tabbing enviroment? */
1702    HelpS = StrStr(cq2.Lines[cq2.next].Lstring(), "\\TAB ");
1703    if((HelpS!=NULL)&&(cq2.Lines[cq2.cur].envir=='T')&&(cq2.Lines[cq2.next].envir==' '))
1704	{
1705	cq2.Lines[cq2.next].envir='T';  /* Tabbing expanded for next line */
1706	}
1707
1708
1709    switch (cq2.Lines[cq2.cur].line_term)
1710      {
1711      case 's':
1712      case 'p':if(Change_envir_EOL(&cq2))
1713		   {
1714		   if (cq2.Lines[cq2.next].attr.Opened_Depth>0) /* Attributes are opened */
1715		     {
1716		     Close_All_Attr(cq2.Lines[cq2.next].attr,s); /* close attributes on EOL */
1717		     if((cq2.Lines[cq2.pre].Lstring=="") && cq2.Lines[cq2.cur].Empty)
1718			s=replacesubstring(s,"\\/","");  //remove \/ in vertical mode
1719		     fprintf(cq2.LaTeX,s());
1720		     }
1721		   putc('\n', cq2.LaTeX);
1722		   if(!cq2.just_envir_closed) Close_environment(&cq2);
1723		   }
1724	       else putc('\n', cq2.LaTeX);
1725	       break;
1726
1727      case 'h':if(toupper(cq2.Lines[cq2.cur].envir) == 'I')
1728		  {                  
1729		  if (cq2.Lines[cq2.next].attr.Opened_Depth>0) /* Attributes are opened */
1730		     {
1731		     Close_All_Attr(cq2.Lines[cq2.next].attr,cq2.LaTeX); /* close attributes on EOL */
1732		     }
1733		  putc('\n', cq2.LaTeX);
1734		  if(!cq2.just_envir_closed) Close_environment(&cq2);
1735		  cq2.Lines[cq2.cur].envir = ' ';
1736		  }
1737
1738	       else {
1739		    cq2.underline = false;
1740		    for (i = 0; i < cq2.Lines[cq2.next].attr.Closed_Depth; i++)
1741		      cq2.underline = (cq2.underline ||
1742				       cq2.Lines[cq2.next].attr.stack[i] == 0xb || //DblUnd
1743				       cq2.Lines[cq2.next].attr.stack[i] == 0xd || //StrikeOut
1744				       cq2.Lines[cq2.next].attr.stack[i] == 0xe);  //Underline
1745
1746		    if (cq2.underline && (cq2.Lines[cq2.next].attr.Opened_Depth>0) &&
1747			  !ClosedAttr(cq2.Lines[cq2.cur].attr) )
1748		      {
1749		      Close_All_Attr(cq2.Lines[cq2.next].attr,cq2.LaTeX); /* close attributes on EOL */
1750		      }
1751
1752	/* Elke Indent-environment moet na one harde Return*/
1753	/* Afgesloten worden.*/
1754
1755		   if (Change_envir_EOL(&cq2))
1756			{
1757			if (cq2.just_envir_closed) fprintf(cq2.LaTeX, "\\nwln\n");
1758					      else putc('\n', cq2.LaTeX);
1759			if (cq2.Lines[cq2.next].attr.Opened_Depth>0) /* Attributes are opened */
1760				 {
1761				 Close_All_Attr(cq2.Lines[cq2.next].attr,cq2.LaTeX); /* close attributes on EOL */
1762				 }
1763			if(!cq2.just_envir_closed) Close_environment(&cq2);
1764			}
1765		    else {
1766			 if(cq2.Lines[cq2.next].envir=='^'); // do not solve anything at the end of the minipage
1767			 else if (*aLineStr == "" &&
1768				cq2.Lines[cq2.pre].Lstring == "")
1769				   {
1770				   fprintf(cq2.LaTeX, "\\bigskip");
1771				   }
1772			 else if (cq2.Lines[cq2.next].Empty>0)
1773				{
1774				cq2.Lines[cq2.next].InhibitBsBslash = true;
1775				}
1776			 else if (!cq2.Lines[cq2.cur].InhibitBsBslash)
1777				{
1778/*				if (!cq2.just_envir_closed && (cq2.Lines[cq2.cur].envir=='L' || cq2.Lines[cq2.cur].envir=='R'))
1779					 fprintf(cq2.LaTeX, "\\nwln");
1780				   else*/ {
1781					if(cq2.Lines[cq2.cur].Empty>0)
1782						 {
1783						 if(cq2.Lines[cq2.pre].Lstring!="")
1784							fputc('\n',cq2.LaTeX);
1785						 fprintf(cq2.LaTeX, " \\bigskip");
1786						 }
1787					    else fprintf(cq2.LaTeX, "\\\\");
1788					}
1789
1790				if (cq2.Lines[cq2.next].Lstring[0] == '[')
1791					  {
1792				

Large files files are truncated, but you can click here to view the full file