/* This file is part of
* ======================================================
* 
*           LyX, the High Level Word Processor
* 	 
*	    Copyright (C) 1995 Matthias Ettrich
*
*======================================================*/

#include "config.h"

#include <time.h>
#include <stdlib.h>

#include "file.h"
#include "symgen.h"


char SimpleTeXOnePar(FILE *file, LyXFont &font1, LyXParagraph *par);
void TeXOnePar(FILE* file, LyXParagraph* &par, LyXParagraph* &prevpar);
void TeXDeeper(FILE* file, LyXParagraph* &par, LyXParagraph* &prevpar);
void TeXEnvironment(FILE* file, LyXParagraph* &par,
		     LyXParagraph* &prevpar);
void TeXFootnote(FILE* file, LyXParagraph* &par,
		 LyXParagraph* &prevpar);


// these three will not be static for some time... Lgb.
FILE *myfile;
char token_end_character;
char* stringtoken = new char[100];
char* float_placement;


struct TexRow {
  //  LyXParagraph *par;
  int id;
  int pos;
  TexRow *next;
};


int tex_code_break_column;

char textclass = 0; // what is this used for? (...)
// someof these functions need the document's textclass.
// THis isn't stored in LyXParagraph, but in parameters.
// Since the parameters are not known here, we set this
// variable in lyxparameters.C to the current textclass.

static TexRow *texrow = NULL;


char* date() 
{
   time_t tid;
   if ((tid=time(NULL)) == -1)
      return (char*)NULL;
   else
      return (ctime(&tid));
}


void ResetTexRow()
{
  TexRow *tmp=texrow;
  while (texrow) {
    tmp = texrow;
    texrow = texrow->next;
    delete tmp;
  }
}



void IncTexRow(LyXParagraph *par, int pos)
{
  TexRow *tmp;
  tmp = new TexRow;
  tmp->pos = pos;
  //tmp->par = par;
  if (par)
    tmp->id = par->GetID();
  else
    tmp->id = -1;
  tmp->next = texrow;
  texrow = tmp;
}


LyXFont GetFont(LyXParagraph* par, int pos)
{
   LyXFont layoutfont, tmpfont;
   int main_body;
   
   LyXLayout *layout = lyxstyle.Style(textclass, par->GetLayout());
   
   if (layout->labeltype != LABEL_MANUAL)
     main_body = 0;
   else
     main_body = par->BeginningOfMainBody();
   
   if (pos >= 0){
     if (pos < main_body)
       layoutfont = layout->labelfont;
     else
       layoutfont = layout->font;
     tmpfont = par->GetFontSettings(pos);
     if (tmpfont.family == LYX_LAYOUT_DEFAULT)
       tmpfont.family = layoutfont.family;
     if (tmpfont.series == LYX_LAYOUT_DEFAULT)
       tmpfont.series = layoutfont.series;
     if (tmpfont.shape == LYX_LAYOUT_DEFAULT)
       tmpfont.shape = layoutfont.shape;
     if (tmpfont.size == LYX_LAYOUT_DEFAULT)
       tmpfont.size = layoutfont.size;
     if (tmpfont.bar == LYX_LAYOUT_DEFAULT)
       tmpfont.bar = layoutfont.bar;
     if (tmpfont.latex == LYX_LAYOUT_DEFAULT)
       tmpfont.latex = layoutfont.latex;
   }
   else{
     // process layoutfont for pos == -1 and labelfont for pos < -1
     if (pos == -1)
       tmpfont = layout->font;
     else
       tmpfont = layout->labelfont;
   }
   
   // check for environment font information
   if (par->GetDepth()){
     if (tmpfont.family == LYX_ENVIRONMENT_DEFAULT){
       while (par && par->GetDepth()
	      && lyxstyle.Style(textclass,
				par->GetLayout())->font.family == LYX_ENVIRONMENT_DEFAULT)
	 par = par->DepthHook(par->GetDepth()-1);
       if (par)
	 tmpfont.family =  lyxstyle.Style(textclass,
					  par->GetLayout())->font.family;       
     }
     if (tmpfont.series == LYX_ENVIRONMENT_DEFAULT){
       while (par && par->GetDepth()
	      && lyxstyle.Style(textclass,
				par->GetLayout())->font.series == LYX_ENVIRONMENT_DEFAULT)
	 par = par->DepthHook(par->GetDepth()-1);
       if (par)
	 tmpfont.series =  lyxstyle.Style(textclass,
					  par->GetLayout())->font.series;       
     }
     if (tmpfont.shape == LYX_ENVIRONMENT_DEFAULT){
       while (par && par->GetDepth()
	      && lyxstyle.Style(textclass,
				par->GetLayout())->font.shape == LYX_ENVIRONMENT_DEFAULT)
	 par = par->DepthHook(par->GetDepth()-1);
       if (par)
	 tmpfont.shape =  lyxstyle.Style(textclass,
					 par->GetLayout())->font.shape;       
     }
     if (tmpfont.size == LYX_ENVIRONMENT_DEFAULT){
       while (par && par->GetDepth()
	      && lyxstyle.Style(textclass,
				par->GetLayout())->font.size == LYX_ENVIRONMENT_DEFAULT)
	 par = par->DepthHook(par->GetDepth()-1);
       if (par)
	 tmpfont.size =  lyxstyle.Style(textclass,
					par->GetLayout())->font.size;       
     }
   }
   
   if (tmpfont.family == LYX_ENVIRONMENT_DEFAULT)
     tmpfont.family =  lyxstyle.TextClass(textclass)->defaultfamily;
   if (tmpfont.series == LYX_ENVIRONMENT_DEFAULT)
     tmpfont.series =  lyxstyle.TextClass(textclass)->defaultseries;
   if (tmpfont.shape == LYX_ENVIRONMENT_DEFAULT)
     tmpfont.shape =  lyxstyle.TextClass(textclass)->defaultshape;
   if (tmpfont.size == LYX_ENVIRONMENT_DEFAULT)
     tmpfont.size =  lyxstyle.TextClass(textclass)->defaultsize;
   
   
   
   return tmpfont;
}


char IsLyXFilename(const char* filename)
{
  int i;
  for (i=0; filename[i]; i++);
  return (
	  (i>4
	   && filename[i-4]=='.' 
	   && filename[i-3]=='l' 	
	   && filename[i-2]=='y' 	
	   && filename[i-1]=='x'
	   )
	  ||
	  (i>5
	   && filename[i-5]=='.' 
	   && filename[i-4]=='l' 	
	   && filename[i-3]=='y' 	
	   && filename[i-2]=='x'
	   && filename[i-1]=='#'
	   )
	  );
}


char IsSGMLFilename(const char* filename)
{
  int i;
  for (i=0; filename[i]; i++);
  return (
	  (i>5
	   && filename[i-5]=='.' 
	   && filename[i-4]=='s' 	
	   && filename[i-3]=='g' 	
	   && filename[i-2]=='m'
           && filename[i-1]=='l'
	   )
	  ||
	  (i>6
	   && filename[i-6]=='.' 
	   && filename[i-5]=='s' 	
	   && filename[i-4]=='g' 	
	   && filename[i-3]=='m'
	   && filename[i-2]=='l'
	   && filename[i-1]=='#'
	   )
	  );
}


int OpenFile(const char *filename)
{
  myfile = NULL;
  if (IsLyXFilename(filename))
    myfile = fopen(filename, "r");
  
  return (myfile != NULL);
}


int OpenAllFile(const char *filename)
{
  myfile = fopen(filename, "r");
  return (myfile != NULL);
}


void CloseFile()
{
   fclose(myfile);
}




void Obsolete(LyXLexClass *lex)
{
	char *tmptok = lex->text();
	fprintf(stderr,"Obsolete command: `\\%s'\n", tmptok);
	fprintf(stderr,"\tIt will be ignored.\n");
	if (lex->next()) {
		tmptok = lex->GetString();
		delete tmptok;
	}
}


	       

char SimpleTeXOnePar(FILE *file, LyXFont &font1, LyXParagraph *par)
{
   LyXFont font2;
   char c;
   Inset *inset;
   int main_body;
   int column;
   
   char return_value = 0;
   char underbar = 0;
   /* table stuff -- begin*/ 
   int current_cell_number = -1;
   /* table stuff -- end*/ 

   IncTexRow(par,0);

   /* maybe we have to create a optional argument */ 
   if (lyxstyle.Style(textclass,
		      par->GetLayout())->labeltype != LABEL_MANUAL)
     main_body = 0;
   else
     main_body = par->BeginningOfMainBody();
   
   if (main_body > 0) {
      fprintf(file, "[");
      font1 =  GetFont(par, -2);
   }
   else
      font1 = GetFont(par, -1);

   column = 0;
   
   if (main_body >= 0 && !par->last && !par->IsDummy()){
 
     if (lyxstyle.Style(textclass,
			par->GetLayout())->latextype == LATEX_COMMAND)
       fprintf(file,"{");
     else if (par->GetFontSettings(par->Last()-1).size != LYX_LAYOUT_DEFAULT
	      ||
	      par->align != LYX_ALIGN_LAYOUT)
       {
	 fprintf(file, "{");
	 return_value = 1;
       }
     
   }
   
   for (int i = 0; i < par->last; i++) {
     column++;
     if (i == main_body && !par->IsDummy()) {
	 if (main_body > 0) {
	    if (font1.latex == LYX_FORMULA_LATEX)
	       fprintf(file, "\\)");
	    fprintf(file, "]");
	    font1 = GetFont(par, -1);
	 }
	 if (lyxstyle.Style(textclass,
			    par->GetLayout())->latextype == LATEX_COMMAND)
	   fprintf(file,"{");
	 else if(par->GetFontSettings(par->Last()-1).size != LYX_LAYOUT_DEFAULT
		  || par->align != LYX_ALIGN_LAYOUT)
	   {
	     fprintf(file, "{");
	     return_value = 1;
	   }

	 if (par->noindent)
	   fprintf(file, "\\noindent ");
	 switch (par->align) {
	  case LYX_ALIGN_LEFT:
	    fprintf(file, "\\raggedright ");
	    column+=13;
	    break;
	  case LYX_ALIGN_RIGHT:
	    fprintf(file, "\\raggedleft ");
	    column+=13;
	    break;
	  case LYX_ALIGN_CENTER:
	    fprintf(file, "\\centering ");
	    column+=13;
	    break;
	 }	 

	 /* table stuff -- begin*/ 
	 current_cell_number = -1;
	 if (par->table){
	   int tmp = par->table->TexEndOfCell(file, current_cell_number);
	   for (;tmp>0;tmp--)
	     IncTexRow(par, 0);
	 } 
	 /* table stuff -- end*/ 
	 
      }

      c = par->GetChar(i);
      
      /* blanks are printed before any fontswitch. With this
	 the brackets after a fontswitch can be removed */

      font2 = GetFont(par, i);      
      
      if (c==' '){
	/* do not print the separation of the optional argument */ 
	if (i != main_body - 1) {
	  if (column > tex_code_break_column
	      && i && par->GetChar(i-1) != ' ') {
	    column = 0;
	    fprintf(file, "\n");
	    IncTexRow(par, i+1);
	    column = 0;
	  }
	  else if (font2.latex == LYX_NO_LATEX)
	    fprintf(file, " ");
	}
      }

      if (font1.family != font2.family) {
	 switch (font2.family) {
	  case LYX_ROMAN_FAMILY:
	    fprintf(file, "\\rmfamily ");
	    column+=13;
	    break;
	  case LYX_SANS_FAMILY:
	    fprintf(file, "\\sffamily ");
	    column+=13;
	    break;
	  case LYX_TYPEWRITER_FAMILY:
	    fprintf(file, "\\ttfamily ");
	    column+=13;
	    break;
	 }
      }
      if (font1.series != font2.series) {
	 switch (font2.series) {
	  case LYX_MEDIUM_SERIES:
	    fprintf(file, "\\mdseries ");
	    column+=13;
	    break;
	  case LYX_BOLD_SERIES:
	    fprintf(file, "\\bfseries ");
	    column+=13;
	    break;
	 }
      }
      if (font1.shape != font2.shape) {
	 switch (font2.shape) {
	 case LYX_ITALIC_SHAPE:
	   fprintf(file, "\\em ");
	   column+=4;
	   break;
	 case LYX_UP_SHAPE:
	   if (font1.shape == LYX_ITALIC_SHAPE){
	     fprintf(file, "\\em ");
	     column+=4;
	   }
	   else {
	     fprintf(file, "\\upshape ");
	     column+=10;
	   }
	   break;
	  case LYX_SMALLCAPS_SHAPE:
	    if (font1.shape == LYX_ITALIC_SHAPE){
	      fprintf(file, "\\em ");
	      column+=4;
	    // fprintf(file, "\\/");     /* italic correction  */
	    }
	    fprintf(file, "\\scshape ");
	    column+=13;
	    break;
	 }
      }
      if (font1.size != font2.size) {
	 switch (font2.size) {
	  case LYX_SIZE_TINY:
	    fprintf(file, "\\tiny ");
	    column+=7;
	    break;
	  case LYX_SIZE_SMALL:
	    fprintf(file, "\\small ");
	    column+=8;
	    break;
	  case LYX_SIZE_NORMAL:
	    fprintf(file, "\\normalsize ");
	    column+=13;
	    break;
	  case LYX_SIZE_LARGE:
	    fprintf(file, "\\large ");
	    column+=8;
	    break;
	  case LYX_SIZE_LARGER:
	    fprintf(file, "\\Large ");
	    column+=8;
	    break;
	  case LYX_SIZE_LARGEST:
	    fprintf(file, "\\LARGE ");
	    column+=8;
	    break;
	  case LYX_SIZE_HUGE:
	    fprintf(file, "\\huge ");
	    column+=8;
	    break;
	  case LYX_SIZE_GIANT:
	    fprintf(file, "\\Huge ");
	    column+=8;
	    break;
	 }
      }

      if (font1.latex != font2.latex) {
	if (font2.latex != LYX_NO_LATEX
	    && lyxstyle.Style(textclass,
			      par->GetLayout())->latextype == LATEX_COMMAND) {
		fprintf(file, "\\protect ");
		column += 8;
	}
	switch (font2.latex) {
	case LYX_FORMULA_LATEX:
	  if (GetFont(par, -1).latex != LYX_FORMULA_LATEX) {
	       fprintf(file, "\\(");
	    }
	    break;
	  default: 
	    if (font1.latex == LYX_FORMULA_LATEX) {
	       if (GetFont(par, -1).latex != LYX_FORMULA_LATEX)
	       	  fprintf(file, "\\)");
	    }
	    break;
	 }
      }
      
      if (c == LYX_META_INSET) {
	inset = par->GetInset(i);
	if (inset) {
	  int tmp = inset->Latex(file,
				 lyxstyle.Style(textclass,
						par->GetLayout())->latextype == LATEX_COMMAND
				 );	     
	  for (;tmp>0;tmp--)
	    IncTexRow(par, i);
	}
      }
      else {
	 
	 if (font2.latex != LYX_NO_LATEX) {
	   switch (c) {
	   case LYX_META_NEWLINE: 
	     /* table stuff -- begin*/ 
	     if (par->table){
	       current_cell_number++;
	       int tmp = par->table->TexEndOfCell(file, current_cell_number);
	       for (;tmp>0;tmp--)
		 IncTexRow(par, i+1);
	       if (tmp)
		 column = 0;
	       font2 = GetFont(par, -1);
	     } else 
	       /* table stuff -- end*/ 
	       {
		 if (font2.latex == LYX_LATEX
		     || !lyxstyle.Style(textclass,
					par->GetLayout())->newline_allowed)
		   fprintf(file, "\n");
		 else
		   fprintf(file, "\\\\\n");
		 IncTexRow(par, i+1);
		 column = 0;
	       }
	     break;  
	   case LYX_META_HFILL: 
	     fprintf(file, "\\hfill{}");
	     column+=8;
	     break;
	     case LYX_META_PROTECTED_SEPARATOR: 
	       fprintf(file, "~");
	       break;
	   default:
		   // make sure that we will not print
		   // error generating chars to the tex file.
		   // this test would not be needed if it were
		   // done in the buffer itself.
		   if (c != '\0')
			   fprintf(file, "%c", c);
		   break;
	    }
	 }
	 else {
	   if (font2.bar == LYX_UNDER_BAR
	       && c != ' ' 
	       && c != LYX_META_NEWLINE
	       && c != LYX_META_HFILL){
	     fprintf(file, "\\underbar{");
	     column += 11;
	     underbar = 1;
	   }
	   else 
	     underbar = 0;

	   switch (c) {
	   case LYX_META_NEWLINE: 
	     /* table stuff -- begin*/ 
	     if (par->table){
	       current_cell_number++;
	       int tmp = par->table->TexEndOfCell(file, current_cell_number);
	       for (;tmp>0;tmp--)
		 IncTexRow(par, i+1);
	       if (tmp)
		 column = 0;
	       font2 = GetFont(par, -1);
	     } else 
	       /* table stuff -- end*/ 
	       {
		 if (!lyxstyle.Style(textclass, par->GetLayout())->newline_allowed)
		   fprintf(file, "\n");
		 else
		   fprintf(file, "\\\\\n");
		 IncTexRow(par, i+1);
		 column = 0;
	       }
	     break;
	   case LYX_META_HFILL: 
	     fprintf(file, "\\hfill{}");
	     column+=8;
	     break;
	   case LYX_META_PROTECTED_SEPARATOR: 
	       fprintf(file, "~");
	       break;
	     case '\\': 
	       if (lyxstyle.Style(textclass,
				  par->GetLayout())->latextype == LATEX_COMMAND) {
		  fprintf(file, "\\protect\\(\\backslash\\protect\\)");
		  column+=32;
	       }
	       else {
		  fprintf(file, "\\(\\backslash\\)");
		  column+=13;
	       }
	       break;
	   case '°': case '±': case '²': case '³': case 'µ': 
	   case '·': case '×': case '÷': case '¹': case 'ª':
	   case 'º': case '¬': case '|': case '<': case '>':
	       if (lyxstyle.Style(textclass,
				  par->GetLayout())->latextype == LATEX_COMMAND) {
		  fprintf(file, "\\protect\\(%c\\protect\\)", c);
		  column+=26;
	       }
	       else {
		  fprintf(file, "\\(%c\\)", c);
		  column+=6;
	       }
	       break;
	   case '\"':
	     fprintf(file, "\\lxq{}");
	     column+=6;
	     break;
	   case '$': case '&': 
	   case '%': case '#': case '{':   
	   case '}': case '_': 
	     fprintf(file, "\\%c", c);
	     column +=1;
	     break;
	   case '^': case '~':
	     fprintf(file, "\\%c{}", c);
	     break;
	   case ' ':
	       /* blanks are printed bevor font switching */
	       /* with the following exception :-) */
	       if (font2.latex != LYX_FORMULA_LATEX
		   && font1.latex == LYX_FORMULA_LATEX)
		 fprintf(file, " ");
	       break;
	   default:
		     /* idea for labels --- begin*/ 
 
		     /* check for LyX */ 
		     if (c ==  'L' && i <= par->last-3 
			 && par->GetChar(i+1) == 'y'
			 && par->GetChar(i+2) == 'X'){
			     fprintf(file, "\\LyX{}");
			     i+=2;
		     }
		     /* check for TeX */ 
		     else if (c ==  'T' && i <= par->last-3 
			      && par->GetChar(i+1) == 'e'
			      && par->GetChar(i+2) == 'X'){
			     fprintf(file, "\\TeX{}");
			     i+=2;
		     }
		     /* check for LaTeX2e */ 
		     else if (c ==  'L' && i <= par->last-7 
			      && par->GetChar(i+1) == 'a'
			      && par->GetChar(i+2) == 'T'
			      && par->GetChar(i+3) == 'e'
			      && par->GetChar(i+4) == 'X'
			      && par->GetChar(i+5) == '2'
			      && par->GetChar(i+6) == 'e'){
			     fprintf(file, "\\LaTeXe{}");
			     i+=6;
		     }
		     /* check for LaTeX */ 
		     else if (c ==  'L' && i <= par->last-5 
			      && par->GetChar(i+1) == 'a'
			      && par->GetChar(i+2) == 'T'
			      && par->GetChar(i+3) == 'e'
			      && par->GetChar(i+4) == 'X'){
			     fprintf(file, "\\LaTeX{}");
			     i+=4;
		     }
		     else
			     /* idea for labels --- end*/ 
			     // same test as above
			     if (c != '\0')
				     fprintf(file, "%c", c);
		     break;
	   }
	   
	   if (underbar){
	     fprintf(file, "}");
	     column += 1;
	     underbar = 0;
	   }
	 }
      } 
      
      font1 = font2;
   }
   
   /* needed if there is an optional argument but no contents */ 
   if (main_body > 0 && main_body == par->last) {
      if (font1.latex == LYX_FORMULA_LATEX)
      	 fprintf(file, "\\)");
      fprintf(file, "]~");
      font1 = GetFont(par, -1);
      return_value = 0;
   }
   
   if (font1.latex == LYX_FORMULA_LATEX
       && GetFont(par, -1).latex != LYX_FORMULA_LATEX) {
      fprintf(file, "\\)");
      font1.latex = LYX_NO_LATEX;
   }
   
   /* table stuff -- begin*/ 
   if (par->table){
     current_cell_number++;
     int tmp = par->table->TexEndOfCell(file, current_cell_number);
     for (;tmp>0;tmp--)
       IncTexRow(par, par->last);
   } 
   /* table stuff -- end*/ 

   /* restore the font if necessary */
   /* it is not necessary if the return_value is >0, since then
      the paragraph will be put into brackets.
      This is for example the case, if there are different font sizes
      at the end or another alignment */
   if (!return_value) {
     font2 = GetFont(par, -1);
      
     if (font1.family != font2.family) {
       switch (font2.family) {
       case LYX_ROMAN_FAMILY:
	 fprintf(file, "\\rmfamily ");
	 column+=13;
	 break;
       case LYX_SANS_FAMILY:
	 fprintf(file, "\\sffamily ");
	 column+=13;
	 break;
       case LYX_TYPEWRITER_FAMILY:
	 fprintf(file, "\\ttfamily ");
	 column+=13;
	 break;
       }
     }
     if (font1.series != font2.series) {
       switch (font2.series) {
       case LYX_MEDIUM_SERIES:
	 fprintf(file, "\\mdseries ");
	 column+=13;
	 break;
       case LYX_BOLD_SERIES:
	 fprintf(file, "\\bfseries ");
	 column+=13;
	 break;
       }
     }
     if (font1.shape != font2.shape) {
       switch (font2.shape) {
       case LYX_ITALIC_SHAPE:
	 fprintf(file, "\\em ");
	 column+=4;
	 break;
       case LYX_UP_SHAPE:
	 if (font1.shape == LYX_ITALIC_SHAPE){
	   fprintf(file, "\\em ");
	   column+=4;
	 }
	 else {
	   fprintf(file, "\\upshape ");
	   column+=10;
	 }
	 break;
       case LYX_SMALLCAPS_SHAPE:
	 if (font1.shape == LYX_ITALIC_SHAPE){
	   fprintf(file, "\\em ");
	   column+=4;
	   // fprintf(file, "\\/");     /* italic correction  */
	 }
	 fprintf(file, "\\scshape ");
	 column+=13;
	 break;
       }
      }
   }
   return return_value;
}



void TeXOnePar(FILE* file, LyXParagraph* &par, LyXParagraph* &prevpar) {
   LyXFont font;
   
   LyXParagraph *thispar = par;
   LyXParagraph *tmppar;
   char further_blank_line = 0;
   if (par->IsDummy())
	   fprintf(stderr, "Error in TeXOnePar  \n");

   if (tex_code_break_column &&
       lyxstyle.Style(textclass, par->layout)->latextype == LATEX_COMMAND){
     fprintf(file, "\n");
     IncTexRow(par, 0);
   }

   if (thispar->pagebreak_top) {
     fprintf(file, "\\newpage");
     further_blank_line = 1;
   }

   if (thispar->fill_top) {
     fprintf(file, "\\vspace*{\\fill}");
     further_blank_line = 1;
   }
      
   if (thispar->added_space_top) {
     fprintf(file, "\\vspace{%.2fcm}", thispar->added_space_top);
     further_blank_line = 1;
   }
      
   if (thispar->line_top) {
     switch (GetFont(thispar, 0).size) {
     case LYX_SIZE_TINY:
       fprintf(file, "\\lyxline{\\tiny}");
       break;
     case LYX_SIZE_SMALL:
       fprintf(file, "\\lyxline{\\small}");
       break;
     case LYX_SIZE_NORMAL:
       fprintf(file, "\\lyxline{\\normalsize}");
       break;
     case LYX_SIZE_LARGE:
       fprintf(file, "\\lyxline{\\large}");
       break;
     case LYX_SIZE_LARGER:
       fprintf(file, "\\lyxline{\\Large}");
       break;
     case LYX_SIZE_LARGEST:
       fprintf(file, "\\lyxline{\\LARGE}");
       break;
     case LYX_SIZE_HUGE:
       fprintf(file, "\\lyxline{\\huge}");
       break;
     case LYX_SIZE_GIANT:
       fprintf(file, "\\lyxline{\\Huge}");
       break;
      }
     fprintf(file, "\\vspace{-1\\parskip}");
     further_blank_line = 1;
   }
   if (further_blank_line){
     fprintf(file, "\n");
     IncTexRow(thispar, 0);
   }

   switch (lyxstyle.Style(textclass, par->layout)->latextype) {
   case LATEX_COMMAND:
     fprintf(file, "\\%s", lyxstyle.Style(textclass, par->layout)->latexname);
     break;
   case LATEX_ITEM_ENVIRONMENT:
     fprintf(file, "\\item ");
     break;
   case LATEX_LIST_ENVIRONMENT:
     fprintf(file, "\\item ");
     break;
   }
   
   font = GetFont(par, -1);;
   
   char need_par = SimpleTeXOnePar(file, font, par);
   tmppar = par;
   prevpar = par;
   par = par->next;
   
   while (par && par->footnoteflag != LYX_NO_FOOTNOTE
	  && par->footnoteflag != thispar->footnoteflag) {
	     TeXFootnote(file, par, prevpar);
	     SimpleTeXOnePar(file, font, par);
	     prevpar = par;
	     par = par->next;
	  }
   
   if (need_par)
     fprintf(file, "\\par}");
   else if (lyxstyle.Style(textclass,
			   thispar->GetLayout())->latextype == LATEX_COMMAND)
     fprintf(file, "}");

   fprintf(file, "\n");
   further_blank_line = 0;
   if (thispar->line_bottom) {
      switch (GetFont(tmppar, tmppar->Last() - 1).size) {
       case LYX_SIZE_SMALL:
	 fprintf(file, "\\lyxline{\\small}");
	 break;
       case LYX_SIZE_NORMAL:
	 fprintf(file, "\\lyxline{\\normalsize}");
	 break;
       case LYX_SIZE_LARGE:
	 fprintf(file, "\\lyxline{\\large}");
	 break;
       case LYX_SIZE_LARGER:
	 fprintf(file, "\\lyxline{\\Large}");
	 break;
       case LYX_SIZE_LARGEST:
	 fprintf(file, "\\lyxline{\\LARGE}");
	 break;
       case LYX_SIZE_HUGE:
	 fprintf(file, "\\lyxline{\\huge}");
	 break;
       case LYX_SIZE_GIANT:
	 fprintf(file, "\\lyxline{\\Huge}");
	 break;
      }
      further_blank_line = 1;
   }

   if (thispar->added_space_bottom) {
     fprintf(file, "\\vspace{%.2fcm}", thispar->added_space_bottom);
      further_blank_line = 1;
   }
      
   if (thispar->fill_bottom) {
     fprintf(file, "\\vspace*{\\fill}");
      further_blank_line = 1;
   }

   if (thispar->pagebreak_bottom) {
     fprintf(file, "\\newpage");
      further_blank_line = 1;
   }

   if (further_blank_line){
     fprintf(file, "\n");
     IncTexRow(thispar, thispar->Last());
   }
   
   if (thispar->footnoteflag != LYX_NO_FOOTNOTE
       && par && par->footnoteflag == LYX_NO_FOOTNOTE) {
   }
   else {
     fprintf(file, "\n");
     IncTexRow(thispar, thispar->Last());
   }
}


void TeXDeeper(FILE* file, LyXParagraph* &par, LyXParagraph* &prevpar)
{
   LyXParagraph *thispar = par;
   prevpar = par;
   while (par && par->depth == thispar->depth) {
      if (par->IsDummy())
	      fprintf(stderr, "Error in TeXDeeper \n");
      if (lyxstyle.Style(textclass,
			 par->layout)->latextype == LATEX_ENVIRONMENT
	  || lyxstyle.Style(textclass,
			    par->layout)->latextype == LATEX_ITEM_ENVIRONMENT
	  || lyxstyle.Style(textclass,
			    par->layout)->latextype == LATEX_LIST_ENVIRONMENT
	  )
	      TeXEnvironment(file, par, prevpar);
      else
	      TeXOnePar(file, par, prevpar);
      
   }
}


void TeXEnvironment(FILE* file, LyXParagraph* &par,
			    LyXParagraph* &prevpar)
{
   LyXParagraph *thispar = par;
   prevpar = par;
   if (par->IsDummy())
     fprintf(stderr, "Error in TeXEnvironment \n");
   
   if (lyxstyle.Style(textclass,
		      par->layout)->latextype == LATEX_LIST_ENVIRONMENT)
	   fprintf(file, "\\begin{%s}{%s}\n", 
		   lyxstyle.Style(textclass, par->layout)->latexname,
		   par->labelwidthstring
		   );
   else
     fprintf(file, "\\begin{%s}\n",
	     lyxstyle.Style(textclass, par->layout)->latexname);
   IncTexRow(par, 0);
   if (tex_code_break_column){
     fprintf(file, "\n");
     IncTexRow(par, 0);
   }

   do {
      TeXOnePar(file, par, prevpar);
      if (par && par->depth > thispar->depth)
      	TeXDeeper(file, par, prevpar);    
   } while (par && par->layout == thispar->layout
	    && par->depth == thispar->depth); 
   
   fprintf(file, "\\end{%s}\n",
	   lyxstyle.Style(textclass, thispar->layout)->latexname);
   IncTexRow(prevpar, prevpar->Last());
   if (tex_code_break_column){
     fprintf(file, "\n");
     IncTexRow(prevpar, prevpar->Last());
   }
}


void TeXFootnote(FILE* file, LyXParagraph* &par, LyXParagraph* &prevpar)
{
   LyXParagraph *thispar = par;
   prevpar = par;
   if (par->footnoteflag == LYX_NO_FOOTNOTE)
     fprintf(stderr, "Error in TeXFootnote \n");
   
   if (lyxstyle.Style(textclass,
		      thispar->previous->GetLayout())->latextype == LATEX_COMMAND) {
     if (thispar->footnoteflag == LYX_FOOTNOTE){
       fprintf(file, "\\protect");
     }
     else {
       fprintf(stderr, "LyX Warning: Float other than"
	       " footnote in command will be ignored \n");
       while (par->footnoteflag != LYX_NO_FOOTNOTE) {
        par = par->next;
       }
       return;
   }
  }
   
   switch (thispar->footnotekind) {
    case LYX_FOOTNOTE:
      fprintf(file, "\\footnote{\n");
      break;
    case LYX_MARGIN:
      fprintf(file, "\\marginpar{\n");
      break;
    case LYX_FIG:
      fprintf(file, "\\begin{figure}");
      if (float_placement) {
	      fprintf(file, "[%s]\n", float_placement);
      } else {
	      fprintf(file, "\n");
      }
      break;
    case LYX_TAB:
      fprintf(file, "\\begin{table}");
      if (float_placement) {
	      fprintf(file, "[%s]\n", float_placement);
      } else {
	      fprintf(file, "\n");
      }
      break;
   }
   
   do {
	   if (par->IsDummy())
		   fprintf(stderr, "Error in TeXFootnote \n");
	   if (lyxstyle.Style(textclass,
			      par->layout)->latextype == LATEX_ENVIRONMENT
	       || lyxstyle.Style(textclass,
				 par->layout)->latextype == LATEX_ITEM_ENVIRONMENT
	       || lyxstyle.Style(textclass,
				 par->layout)->latextype == LATEX_LIST_ENVIRONMENT
		   )
		   TeXEnvironment(file, par, prevpar);
	   else
		   TeXOnePar(file, par, prevpar);
	   
	   if (par && par->depth > thispar->depth)
		   TeXDeeper(file, par, prevpar);
   } while (par && par->footnoteflag != LYX_NO_FOOTNOTE);
   
   switch (thispar->footnotekind) {
    case LYX_FOOTNOTE:
      fprintf(file, "}");
      break;
    case LYX_MARGIN:
      fprintf(file, "}");
      break;
    case LYX_FIG:
      fprintf(file, "\\end{figure}");
      break;
    case LYX_TAB:
      fprintf(file, "\\end{table}");
      break;
   }
}


void LyXParagraph::readSimpleWholeFile()
{
  char c;
   long file_size = 0;
   // would it be possible to ask the file for its size?
   // LGB FIX: stat should be used here.
   while (!feof(myfile)) {
      c = fgetc(myfile);
      file_size++;
   }
   /* it is horrible, I know, but faster.
    * I should not use InsertString for that :-( */
   
   /* I will write a better insertion in the future */ 
   Enlarge(0, file_size + 10);
   
   rewind(myfile);
   
   if (!feof(myfile)) {
      do {
	 c = fgetc(myfile);
	 InsertChar(last,c);
      } while (!feof(myfile));
      
   }

}


/* scans the latex-logfile and inserts error insets */
// Lgb: ScanLogFile now returns all status information
//      in the TeXErrors struct errors (pointer.)
void ScanLogFile(const char* filename, LyXText* text, TeXErrors* errors)
{
   FILE *file = fopen(filename, "r");

   if (!file) {
      fprintf(stderr, "LYX_ERROR: Cannot read file `%s' \n", filename);
      errors->status = NO_LOGFILE;
      return;
   }
   
   TexRow *tmp, *tmp2;
   LyXParagraph* texrowpar;

   InsetError *new_inset; 
   int i=0;
   int i2;
   int number_of_tex_rows;
   int row;
   errors->number_of_errors = 0;

   /* store the cursor position */
   LyXCursor cursor = text->cursor;

   LyXParagraph* par = NULL;

   tmp = texrow;
   while (tmp) {
      i++;
      tmp=tmp->next;
   }

   number_of_tex_rows = i;
   
   char *s1 = new char[400];
   char *s2 = new char[200];

   while (!feof(file)) {
      do {
	 readline(file, s1);
      }while (!feof(file) && (s1[0]!='!' || s1[1]!=' '));
      if (s1[0]=='!' && s1[1]==' ') {
	 do {
	    readline(file, s2);
	 }while (!feof(file) && (s2[0]!='l' || s2[1]!='.'));
	 
	 if (s2[0]=='l' && s2[1]=='.') {
	    sscanf(s2, "l.%d", &row);
	    for (i=0; s1[i]; i++);
	    for (i2=0; s2[i2]; i2++) {
	       s1[i+i2]=s2[i2];
	    }
	    s1[i+i2]='\0';
	    
	    /* insert errorstring for row number row */ 
	    tmp = texrow;
	    i = number_of_tex_rows;
	    while (tmp && tmp->next && i > row) {
	      tmp = tmp->next;
	      i--;
	    }
	    
	    errors->number_of_errors++;
	    
	    texrowpar = text->GetParFromID(tmp->id);
	    if (texrowpar) {

	      new_inset = new InsetError(s1);

	      if (texrowpar->footnoteflag == LYX_CLOSED_FOOTNOTE){
		/* open the footnote */
		par = texrowpar;
		while (par->footnoteflag == LYX_CLOSED_FOOTNOTE
		       && par->previous)
		  par = par->previous;
		/* this is possible now, since SetCursor takes
		   care about footnotes */
		text->SetCursor(par, 0);
		text->OpenFootnote();
	      }
	      
	      /* this is possible now, since SetCursor takes
		 care about footnotes */
	      text->SetCursor(texrowpar, tmp->pos);
	      text->InsertInset(new_inset);
	      text->FullRebreak();
	      
	      /* may be necessary */
	      tmp2 = texrow;
	      while (tmp2) {
		if (tmp2 != tmp && tmp2->id == tmp->id && tmp2->pos >= tmp->pos)
		  tmp2->pos++;
		tmp2 = tmp2->next;
	      }
	    }
	 }
      }
   }

   fclose(file);
   delete[] s1;
   delete[] s2;
   
   /* reset the cursor position */
   text->SetCursor(cursor.par, cursor.pos);

   // what about returning a struct in stead?
   errors->status = RUN_OK;
   return;
}
   

/*
 * LinuxDoc SGML support functions.
 *
 * version 0.5
 * written by Pascal Andre (andre@via.ecp.fr)
 *
 */

