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

#include <stdlib.h>

#if defined(sgi) && !defined(__GNUC__)
#include <bstring.h>
#endif

#include "definitions.h"
#include "lyxparameters.h"
#include "lyxlex.h"
#include "tex-defs.h"
#include "symgen.h"
#include "layout.h"
#include "lyxinset.h"
#include "inset.h"
#include "figinset.h"
#include "lyxfont.h"
#include "formula.h"
#include "lyx_sty.h"

static const float LYX_FORMAT = 2.1;

extern FILE *myfile;
extern char token_end_character;
extern char textclass;
extern char* float_placement;
extern int tex_code_break_column;

extern void ResetTexRow();
extern void IncTexRow(LyXParagraph *par, int pos);
extern void TeXEnvironment(FILE* file, LyXParagraph* &par,
			    LyXParagraph* &prevpar);
extern char TeXOnePar(FILE* file, LyXParagraph* &par, LyXParagraph* &prevpar);
extern LyXFont GetFont(LyXParagraph* par, int pos);
extern void WriteAlert(const char* s1, const char* s2, const char* s3);

const char* string_paragraph_separation[3] = {
	"indent", "skip", ""
};
	
const char* string_quotes_language[4] = {
	"german", "english", "french", ""
};	

const char* string_papersize[10] = {
	"a4paper", "a4", "a4wide", "widemarginsa4", "usletter", 
	"a5paper","b5paper","executivepaper","legalpaper",""
};

const char* string_orientation[3] = {
	"portrait", "landscape", ""
};
	
const char* string_pagestyle[5] = {
	"plain", "headings", "fancy", "empty", ""
};


/* constants used for LinuxDoc SGML handling */
enum _linuxdoc_tags {
	LINUXDOC_TITLE, LINUXDOC_AUTHOR, LINUXDOC_DATE,
	LINUXDOC_ABSTRACT, LINUXDOC_SECT, LINUXDOC_SECT1,
	LINUXDOC_SECT2, LINUXDOC_SECT3,	LINUXDOC_SECT4,
	LINUXDOC_PAR, LINUXDOC_CODE, LINUXDOC_VERB, LINUXDOC_ITEM, 
	LINUXDOC_ENUM, LINUXDOC_DESCR, LINUXDOC_NONE 
};
	
	
static const char *linuxdoc_styles[LINUXDOC_NONE] = {
	"Title", "Author", "Date", "Abstract", "Section",
	"Subsection", "Subsubsection", "Paragraph",
	"Subparagraph", "Standard", "Code", 
	"Verbatim", "Itemize", "Enumerate", "Description"
};
	
static const char *linuxdoc_tags[LINUXDOC_NONE] = {
	"title", "author", "date", "abstract", "sect",
	"sect1", "sect2", "sect3", "sect4", "p", "code",
	"verb", "itemize", "enum", "descrip"
};
	
	
enum _special_tags {
	LDS_NONE, LDS_QUOTE, LDS_TSCREEN, LDS_LAST
};

	
static const char *special_tags[LDS_LAST] = {
	"", "\n<quote>", "\n<tscreen>"
};
	
	
static const char *special_close[LDS_LAST] = {
	"" ,"\n</quote>", "\n<tscreen>"
};
	
// shouldn't these be the same sizes that (La)TeX can use? Lgb
static const char* string_size[9] = {
	"tiny", "small", "normal", "large", 
	"larger", "largest", "huge", "giant", ""
};

static const char* string_footnotekinds[5] = {
	"footnote", "margin", "fig", "tab", ""
};

/* the modern is obsolete and there for compartibility */ 
static const char* string_family[5] = {
	"roman", "sans", "typewriter", "modern", ""
};
	
static const char* string_series[3] = {
	"medium", "bold", ""
};

static const char* string_shape[4] = {
	"up", "italic", "smallcaps", ""
};
	
static const char* string_latex[4] = {
	"no_latex", "latex", "formula_latex", ""
};
	
static const char* string_bar[3] = {
	"no", "under", ""
};
	
static const char* string_align[5] = {
	"block", "left", "right", "center", ""
};
	

LyXTextParameters::LyXTextParameters()
{
	//fprintf (stderr, "LyXTextParameters (null) constructor called!\n");
	paragraph_separation = LYX_PARSEP_INDENT;
	/*  quotes_language = GERMAN; */ 
	quotes_language = ENGLISH;
	quotes_times = 2;
	/*  papersize = PAPER_A4PAPER; */ 
	papersize = PAPER_USLETTER;
	fontsize = 10;
	baseline = 1.0;
	secnumdepth = 3;
	tocdepth = 3;
	/*    language = "german"; */ 
	language = StringCopy("default");
	fonts = StringCopy("default");
	inputenc = StringCopy("default");
	preamble = NULL;
	options = new char; 
	options[0] = 0;
	epsfig = StringCopy("none");
	textclass = 0;
	sides = 1;
	columns = 1;
	orientation = ORIENTATION_PORTRAIT;
	pagestyle = PAGESTYLE_PLAIN;
	paragraph = NULL;
	cursor.par = NULL;
	cursor.pos = 0;

	float_placement = NULL;
}


LyXTextParameters::LyXTextParameters(LyXTextParameters &p)
{
	//fprintf (stderr, "LyXTextParameters (copy) constructor called!\n");
	//p = lyxrc.parameters;
	paragraph_separation = p.paragraph_separation;
	quotes_language = p.quotes_language;
	quotes_times = p.quotes_times;
	papersize = p.papersize;
	fontsize = p.fontsize;
	baseline = p.baseline;
	secnumdepth = p.secnumdepth;
	tocdepth = p.tocdepth;
	language = StringCopy(p.language);
	fonts = StringCopy(p.fonts);
	inputenc = StringCopy(p.inputenc);
	preamble = StringCopy(p.preamble);
	options = StringCopy(p.options);
	epsfig = StringCopy(p.epsfig);
	textclass = p.textclass;
	
	orientation = p.orientation;
	pagestyle = p.pagestyle;
	// WARNING destructor will deallocate paragraph!!
	paragraph = p.paragraph;
	cursor.par = p.cursor.par;
	cursor.pos = p.cursor.pos;

	if (p.float_placement != NULL) {
		float_placement = StringCopy(p.float_placement);
	} else {
		float_placement = NULL;
	}
}


LyXTextParameters::~LyXTextParameters()
{
	//fprintf (stderr, "LyXTextParameters destructor called!\n");
	LyXParagraph *par = paragraph;
	LyXParagraph *tmppar = par;
	while (par) {
		tmppar = par->next;
		delete par;
		par = tmppar;
	}
	paragraph = NULL;
	delete language;
	delete epsfig;
	delete fonts;
	delete inputenc;
	delete preamble;
	delete options;
	cursor.par = NULL;
	cursor.pos = 0;

	if (float_placement != NULL) {
		delete float_placement;
	}
}


void LyXTextParameters::Copy(LyXTextParameters &p)
{
	//fprintf (stderr, "LyXTextParameters (copy) constructor called!\n");
	//p = lyxrc.parameters;
	paragraph_separation = p.paragraph_separation;
	quotes_language = p.quotes_language;
	quotes_times = p.quotes_times;
	papersize = p.papersize;
	fontsize = p.fontsize;
	baseline = p.baseline;
	secnumdepth = p.secnumdepth;
	tocdepth = p.tocdepth;
	if (language) delete language;
	language = StringCopy(p.language);
	if (fonts) delete fonts;
	fonts = StringCopy(p.fonts);
	if (inputenc) delete inputenc;
	inputenc = StringCopy(p.inputenc);
	if (preamble) delete preamble;
	preamble = StringCopy(p.preamble);
	if (options) delete options;
	options = StringCopy(p.options);
	if (epsfig) delete epsfig;
	epsfig = StringCopy(p.epsfig);
	textclass = p.textclass;
	
	orientation = p.orientation;
	pagestyle = p.pagestyle;
	// WARNING destructor will deallocate paragraph!!
	paragraph = p.paragraph;
	cursor.par = p.cursor.par;
	cursor.pos = p.cursor.pos;

	if (p.float_placement != NULL) {
		float_placement = StringCopy(p.float_placement);
	} else {
		float_placement = NULL;
	}
}


void LyXTextParameters::readLanguage(LyXLexClass *lex)
{
	char *tmptok;
	char *test;
	int n=0;
	if (!lex->next()) return;
	
	tmptok = lex->GetString();
	// check if tmptok is part of tex_babel in tex-defs.h
	while (true) {
		test = tex_babel[n++];
		
		if (strcmp(test,tmptok)==0) {
			language = tmptok;
			break;
		}
		else if (strcmp(test,"last_item")==0) {
			fprintf(stderr,
				"Warning: language `%s' not recognized!",
				tmptok);
			fprintf(stderr,
				"         Setting language to `default'.\n");
			language = StringCopy("default");
			break;	 
		}      
	}
}


void LyXTextParameters::readLanguage()
{
	char *tmptok;
	char *test;
	int n=0;
	
	tmptok = NextLongToken();
	// check if tmptok is part of tex_babel in tex-defs.h
	while (true) {
		test = tex_babel[n++];
		
		if (strcmp(test,tmptok)==0) {
			language = tmptok;
			break;
		}
		else if (strcmp(test,"last_item")==0) {
			fprintf(stderr,"Warning: language `%s' not recognized!",
				tmptok);
			fprintf(stderr,"         Setting language to `default'.\n");
			language = StringCopy("default");
			break;	 
		}      
	}
}


void LyXTextParameters::readEpsfig(LyXLexClass *lex)
{
	char *tmptok;
	char *test;
	int n=0;
	
	//consistency check
	if (!StringEqual(lex->text(),"\\epsfig"))
		fprintf(stderr,
			"LyXTextParameters:: readEpsfig: Internal Error!\n");
	
	if (lex->next()) { 
		tmptok = lex->GetString();
		// check if tmptok is part of tex_epsfig in tex_defs.h
		while (true) {
			test = tex_epsfig[n++];
			
			if (strcmp(test,tmptok)==0) {	 
				epsfig = tmptok;
				break;
			}      
			else if (strcmp(test, "last_item")==0) {
				fprintf(stderr,"Warning: epsfig driver `%s' not recognized!\n",
					tmptok);
				fprintf(stderr,"         Setting epsfig driver to `none'.\n");
				epsfig = StringCopy("none");
				break;
			}      
		}
	}
}


void LyXTextParameters::readEpsfig()
{
	char *tmptok;
	char *test;
	int n=0;
	
	tmptok = NextLongToken();
	// check if tmptok is part of tex_epsfig in tex_defs.h
	while (true) {
		test = tex_epsfig[n++];
		
		if (strcmp(test,tmptok)==0) {	 
			epsfig = tmptok;
			break;
		}      
		else if (strcmp(test, "last_item")==0) {
			fprintf(stderr,"Warning: epsfig driver `%s' not recognized!\n",
				tmptok);
			fprintf(stderr,"         Setting epsfig driver to `none'.\n");
			epsfig = StringCopy("none");
			break;
		}      
	}
}


void LyXTextParameters::readPreamble(LyXLexClass *lex)
{
	char* token;

	LyXParagraph *par = new LyXParagraph();
	int pos = 0;
	int i;

        if (preamble)
		delete preamble;
	
        while (lex->EatLine()) {
	        token = lex->text();
		
		if (lyx_debug_level & DEBUG_LEX_PARSER)
		        fprintf(stderr,"Preamble: '%s'\n", token);
			
                if (StringEqual(token, "\\end_preamble")) {
			if(pos)               /* if there is some preamble */
				par->InsertChar(pos - 1, '\0'); /* the - 1 deletes the newline
								   * before end_preamble*/
			else
				par->InsertChar(0, '\0');
			
			preamble = par->text;
			par->text = NULL; /* otherwise the destructor will delete it */
			delete par;
			return;
		}
		else {
			//par->InsertChar(pos, '\\');
			//pos++;
			for (i = 0; token[i]; i++) {
				par->InsertChar(pos, token[i]);
				pos++;
			}
			//par->InsertChar(pos, token_end_character);
			par->InsertChar(pos, '\n');
			pos++;
                }
        }
}


void LyXTextParameters::readPreamble()
{
   char* token;
   char c;
   LyXParagraph *par = new LyXParagraph();
   int pos = 0;
   int i;
   if (preamble)
      delete preamble;
   c = fgetc(myfile);
   while (!feof(myfile)) {
      
      /* is it a lyx command? */ 
      if (c=='\\') {
	 token = NextToken();
	 /*printf("Token: %s\n", token);*/
	 if (StringEqual(token, "end_preamble")) {
	   if(pos)                              /* if there is some preamble */
	     par->InsertChar(pos - 1, '\0');   /* the - 1 deletes the newline
						* before end_preamble*/
	   else
	     par->InsertChar(0, '\0');
	   preamble = par->text;
	   par->text = NULL; /* otherwise the destructor will delete it */
	   delete par;
	   return;
	 }
	 else {
	    par->InsertChar(pos, '\\');
	    pos++;
	    for (i = 0; token[i]; i++) {
	       par->InsertChar(pos, token[i]);
	       pos++;
	    }
	    par->InsertChar(pos, token_end_character);
	    pos++;
	 }
	 
	 delete token;
      }
      else {
	 /* simple text */
	 par->InsertChar(pos, c);
	 pos++;
      }
      
      c = fgetc(myfile);
      
   }
}


void LyXTextParameters::readFileOld()
{
   char* token;
   char c;
   char *tmptok;
   int obsolete;
   LyXParagraph *par = new LyXParagraph();
   Inset *inset;
   int pos = 0;
   ::textclass = textclass;
   LyXParagraph *return_par = NULL;
   LyXFont font = GetLyXFont(LYX_LAYOUT_DEFAULT,
			     LYX_LAYOUT_DEFAULT,
			     LYX_LAYOUT_DEFAULT,
			     LYX_LAYOUT_DEFAULT,
			     LYX_LAYOUT_DEFAULT,
			     LYX_LAYOUT_DEFAULT);

   c = fgetc(myfile);
   while (!feof(myfile)) {
      /* is it a lyx command? */ 
      if (c=='\\') {
	 token = NextToken();
	 /*printf("Token: %s\n", token);*/
	 /* this is the old format and this dummy comment is inserted to */
	 /* prevent incorrect patch */
	 if (StringEqual(token, "layout")) {
	    if (!return_par) 
	      return_par = par;
	    else 
	      par = new LyXParagraph(par);
	    pos = 0;
	    tmptok = NextLongToken();
	    par->layout = lyxstyle.NumberOfLayout(textclass, tmptok);
	    delete tmptok;
	    font = GetLyXFont(LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT);
	    
	 }
	 else if (StringEqual(token, "begin_preamble")) {
		 readPreamble();
	 }
	 else if (StringEqual(token, "textclass")) {
	    tmptok = NextLongToken();
	    ::textclass = lyxstyle.NumberOfClass(tmptok);
	    textclass = ::textclass;
	    delete tmptok;
	 }
	 else if (StringEqual(token, "options")) {
	    tmptok = NextLongToken();
	    options = tmptok;
	 }
	 else if (StringEqual(token, "language")) {
	    readLanguage();	    
	 }
	 else if (StringEqual(token, "noindent")) {
	    par->noindent = 1;
	 }
	 else if (StringEqual(token, "fill_top")) {
	    par->fill_top = 1;
	 }
	 else if (StringEqual(token, "fill_bottom")) {
	    par->fill_bottom = 1;
	 }
	 else if (StringEqual(token, "line_top")) {
	    par->line_top = 1;
	 }
	 else if (StringEqual(token, "line_bottom")) {
	    par->line_bottom = 1;
	 }
	 else if (StringEqual(token, "pagebreak_top")) {
	    par->pagebreak_top = 1;
	 }
	 else if (StringEqual(token, "pagebreak_bottom")) {
	    par->pagebreak_bottom = 1;
	 }
	 else if (StringEqual(token, "footnote")) {
	    par->footnoteflag = LYX_CLOSED_FOOTNOTE;
	    par->footnotekind = NextIntToken();
	 }
	 else if (StringEqual(token, "depth")) {
	    par->depth = NextIntToken();
	 }
	 else if (StringEqual(token, "paragraph_separation")) {
	    paragraph_separation = NextIntToken();
	 }
	 else if (StringEqual(token, "quotes_language")) {
	    quotes_language = NextIntToken();
	 }
	 else if (StringEqual(token, "quotes_times")) {
	    quotes_times = NextIntToken();
	 }
	 else if (StringEqual(token, "papersize")) {
	    papersize = NextIntToken();
	 }
	 else if (StringEqual(token, "paperfontsize")) {
	    fontsize = NextIntToken();
	 }
	 else if (StringEqual(token, "paperorientation")) {
	    orientation = NextIntToken();
	 }
	 else if (StringEqual(token, "papercolumns")) {
	    columns = NextIntToken();
	 }
	 else if (StringEqual(token, "papersides")) {
	    sides = NextIntToken();
	 }
	 else if (StringEqual(token, "paperpagestyle")) {
	    pagestyle = NextIntToken();
	 }
	 else if (StringEqual(token, "secnumdepth")) {
	    secnumdepth = NextIntToken();
	 }
	 else if (StringEqual(token, "no_isolatin1")) {
	    obsolete= NextIntToken();
	 }
	 else if (StringEqual(token, "no_babel")) {
	    obsolete = NextIntToken();
	 }
	 else if (StringEqual(token, "no_epsfig")) {
	    obsolete = NextIntToken();
	 }
	 else if (StringEqual(token, "baselinestretch")) {
	    baseline = NextFloatToken();
	 }
	 else if (StringEqual(token, "cursor")) {
	    cursor.par = par;
	    cursor.pos = NextIntToken();
	 }
	 else if (StringEqual(token, "fontfamily")) {
	    font.family = NextIntToken();
	 }
	 else if (StringEqual(token, "fontseries")) {
	    font.series = NextIntToken();
	 }
	 else if (StringEqual(token, "fontshape")) {
	    font.shape = NextIntToken();
	 }
	 else if (StringEqual(token, "fontsize")) {
	    font.size = NextIntToken();
	 }
	 else if (StringEqual(token, "latex")) {
	    font.latex = NextIntToken();
	 }
	 else if (StringEqual(token, "align")) {
	    par->align = NextIntToken();
	 }
	 else if (StringEqual(token, "added_space_top")) {
	    par->added_space_top = NextFloatToken();
	 }
	 else if (StringEqual(token, "added_space_bottom")) {
	    par->added_space_bottom = NextFloatToken();
	 }
	 else if (StringEqual(token, "labelwidthstring")) {
	    par->labelwidthstring = NextLongToken();
	    /* do not delete this token, it is still needed! */ 
	 }
	 else if (StringEqual(token, "InsetQuotes")) {
	    inset = new InsetQuotes;
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 
	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "InsetLatex")) {
	    inset = new InsetLatex;
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 
	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "InsetLatexDel")) {
	    inset = new InsetLatexDel;
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 
	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "InsetFormulaLatex")) {
	    inset = new InsetFormulaLatex;
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 
	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "Figure")) {
	    inset = new InsetFig(100, 100);
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 
	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "newline")) {
	    par->InsertChar(pos, LYX_META_NEWLINE);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "hfill")) {
	    par->InsertChar(pos, LYX_META_HFILL);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "protected_separator")) {
	    par->InsertChar(pos, LYX_META_PROTECTED_SEPARATOR);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "backslash")) {
	    par->InsertChar(pos, '\\');
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "float_placement")) {
	    float_placement = NextToken();
	 }
	 else {
	    fprintf(stderr, "LYX_ERROR: unknown command %s\n", token);
	 }
	 
	 delete token;
      }
      else {
	 /* simple text */
	 if (c!='\n') {
	    par->InsertChar(pos, c);
	    par->SetFont(pos, font);
	    pos++;
	 }
      }
      
      c = fgetc(myfile);
      
   }
   
   if (!return_par)
     return_par = par;

   paragraph = return_par;
}


// will try to use this in 0.11.x (Lgb)
#if 0
// tags for LyX files
enum _lyxtags {
	LY_ACCENT = 1,
	LY_ADDEDSPACEBOTTOM,
	LY_ADDEDSPACETOP,
	LY_ALIGN,
	LY_BACKSLASH,
	LY_BAR,
	LY_BASELINESTRETCH,
	LY_BEGINDEEPER,
	LY_BEGINFLOAT,
	LY_BEGININSET,
	LY_BEGINPREAMBLE,
	LY_CURSOR,
	LY_ENDDEEPER,
	LY_ENDFLOAT,
	LY_ENDINSET,
	LY_EPSFIG,
	LY_FAMILY,
	LY_FIGURE,
	LY_FILLBOTTOM,
	LY_FILLTOP,
	LY_FLOATPLACEMENT,
	LY_FONTENCODING,
	LY_FONTSCHEME,
	LY_HFILL,
	LY_INPUTENCODING,
	LY_INSETFORMULA,
	LY_INSETFORMULALATEX,
	LY_INSETLATEX,
	LY_INSETLATEXDEL,
	LY_INSETQUOTES,
	LY_LABELWIDTHSTRING,
	LY_LANGUAGE,
	LY_LATEX,
	LY_LAYOUT,
	LY_LINEBOTTOM,
	LY_LINETOP,
	LY_LYXTABLE,
	LY_NEWLINE,
	LY_NOBABEL,
	LY_NOEPSFIG,
	LY_NOINDENT,
	LY_NOISOLATIN,
	LY_OPTIONS,
	LY_PAGEBREAKBOTTOM,
	LY_PAGEBREAKSEPARATION,
	LY_PAGEBREAKTOP,
	LY_PAPERCOLUMNS,
	LY_PAPERFONTSIZE,
	LY_PAPERORIENTATION,
	LY_PAPERPAGESTYLE,
	LY_PAPERSIDES,
	LY_PAPERSIZE,
	LY_PROTECTEDSEPARATOR,
	LY_QUOTESLANGUAGE,
	LY_QUOTESTIMES,
	LY_SECNUMDEPTH,
	LY_SERIES,
	LY_SHAPE,
	LY_SIZE,
	LY_TEXTCLASS,
	LY_TOCDEPTH,
	LY_LAST
};

struct keyword_item lyxtags[LY_LAST-1] = {
	{ "\\Figure", LY_FIGURE },
	{ "\\InsetFormula", LY_INSETFORMULA },
	{ "\\InsetFormulaLatex", LY_INSETFORMULALATEX },
	{ "\\InsetLatex", LY_INSETLATEX },
	{ "\\InsetLatexDel", LY_INSETLATEXDEL },
	{ "\\InsetQuotes", LY_INSETQUOTES },
	{ "\\LyXTable", LY_LYXTABLE },
	{ "\\added_space_bottom", LY_ADDEDSPACEBOTTOM },
	{ "\\added_space_top", LY_ADDEDSPACETOP },
	{ "\\align", LY_ALIGN },
	{ "\\backslash", LY_BACKSLASH },
	{ "\\bar" , LY_BAR },
	{ "\\baselinestretch", LY_BASELINESTRETCH },
	{ "\\begin_deeper", LY_BEGINDEEPER },
	{ "\\begin_float", LY_BEGINFLOAT },
	{ "\\begin_inset", LY_BEGININSET },
	{ "\\begin_preamble", LY_BEGINPREAMBLE },
	{ "\\cursor", LY_CURSOR },
	{ "\\end_deeper", LY_ENDDEEPER },
	{ "\\end_float", LY_ENDFLOAT },
	{ "\\end_inset", LY_ENDINSET },
	{ "\\epsfig", LY_EPSFIG },
	{ "\\family", LY_FAMILY },
	{ "\\fill_bottom", LY_FILLBOTTOM },
	{ "\\fill_top", LY_FILLTOP },
	{ "\\float_placement", LY_FLOATPLACEMENT },
	{ "\\fontencoding", LY_FONTENCODING },
	{ "\\fontscheme", LY_FONTSCHEME },
	{ "\\hfill", LY_HFILL },
	{ "\\i", LY_ACCENT },
	{ "\\inputencoding", LY_INPUTENCODING },
	{ "\\labelwidthstring", LY_LABELWIDTHSTRING },
	{ "\\language", LY_LANGUAGE },
	{ "\\latex", LY_LATEX },
	{ "\\layout", LY_LAYOUT },
	{ "\\line_bottom", LY_LINEBOTTOM },
	{ "\\line_top", LY_LINETOP },
	{ "\\newline", LY_NEWLINE },
	{ "\\no_babel", LY_NOBABEL },
	{ "\\no_epsfig", LY_NOEPSFIG },
	{ "\\no_isolatin", LY_NOISOLATIN },
	{ "\\noindent", LY_NOINDENT },
	{ "\\options", LY_OPTIONS },
	{ "\\pagebreak_bottom", LY_PAGEBREAKBOTTOM },
	{ "\\pagebreak_separation", LY_PAGEBREAKSEPARATION },
	{ "\\pagebreak_top", LY_PAGEBREAKTOP },
	{ "\\papercolumns", LY_PAPERCOLUMNS },
	{ "\\paperfontsize", LY_PAPERFONTSIZE },
	{ "\\paperorientation", LY_PAPERORIENTATION },
	{ "\\paperpagestyle", LY_PAPERPAGESTYLE },
	{ "\\papersides", LY_PAPERSIDES },
	{ "\\papersize", LY_PAPERSIZE },
	{ "\\protected_separator", LY_PROTECTEDSEPARATOR },
	{ "\\quotes_language", LY_QUOTESLANGUAGE },
	{ "\\quotes_times", LY_QUOTESTIMES },
	{ "\\secnumdepth", LY_SECNUMDEPTH },
	{ "\\series", LY_SERIES },
	{ "\\shape", LY_SHAPE },
	{ "\\size", LY_SIZE },
	{ "\\textclass", LY_TEXTCLASS },
	{ "\\tocdepth", LY_TOCDEPTH }
};

int LyXTextParameters::readFile(const char* filename)
{
	int error = 0;
	LyXLexClass lex(lyxtags, LY_LAST);
	if (lyx_debug_level & DEBUG_LEX_PARSER)
		lex.printTable();
	lex.setFile(filename);
	if (!lex.IsOK()) return -2;

	// some scheme must be thought of for old files.

	readLyXformat2(&lex);
}


void LyXTextParameters::readLyXformat2(LyXLexClass *lex)
{
	while (lex->IsOK() && !error) {

		switch (lex->lex()) {
		case LEX_FEOF:
			break;
		case LEX_UNDEF:
			fprintf(stderr,
				"Line %d: Parse Error: Unknown tag %s.\n",
				lex->GetLineNo(), lexrc->text());
			error = 1;
			break;
			
		case LY_ACCENT:
			inset = new InsetLatexAccent;
			inset->Read(lex);
			par->InsertChar(pos,LYX_META_INSET);
			par->InsertInset(pos, inset);
			par->SetFont(pos, font);
			pos++;
			break;
			
		case LY_ADDEDSPACEBOTTOM:
			break;
		case LY_ADDEDSPACETOP:
			break;
		case LY_ALIGN:
			break;
		case LY_BACKSLASH:
			break;
		case LY_BAR:
			break;
		case LY_BASELINESTRETCH:
			break;
		case LY_BEGINDEEPER:
			break;
		case LY_BEGINFLOAT:
			break;
		case LY_BEGININSET:
			break;
		case LY_BEGINPREAMBLE:
			break;
		case LY_CURSOR:
			break;
		case LY_ENDDEEPER:
			break;
		case LY_ENDFLOAT:
			break;
		case LY_ENDINSET:
			break;
		case LY_EPSFIG:
			break;
		case LY_FAMILY:
			break;
		case LY_FIGURE:
			break;
		case LY_FILLBOTTOM:
			break;
		case LY_FILLTOP:
			break;
		case LY_FLOATPLACEMENT:
			break;
		case LY_FONTENCODING:
			break;
		case LY_FONTSCHEME:
			break;
		case LY_HFILL:
			break;
		case LY_INPUTENCODING:
			break;
		case LY_INSETFORMULA:
			break;
		case LY_INSETFORMULALATEX:
			break;
		case LY_INSETLATEX:
			break;
		case LY_INSETLATEXDEL:
			break;
		case LY_INSETQUOTES:
			break;
		case LY_LABELWIDTHSTRING:
			break;
		case LY_LANGUAGE:
			break;
		case LY_LATEX:
			break;
			
		case LY_LAYOUT:
			if (lexrc->next()) {
				if (!return_par)
					return_par = par;
				else
					par = new LyXParagraph(par);
				pos = 0;
				par->layout =
					lyxstyle.NumberOfLayout(textclass,
								lex->text());
				par->footnoteflag = footnoteflag;
				par->footnotekind = footnotekind;
				par->depth = depth;
				font = GetLyXFont(LYX_LAYOUT_DEFAULT,
						  LYX_LAYOUT_DEFAULT,
						  LYX_LAYOUT_DEFAULT,
						  LYX_LAYOUT_DEFAULT,
						  LYX_LAYOUT_DEFAULT,
						  LYX_LAYOUT_DEFAULT);
			}
			break;
			
		case LY_LINEBOTTOM:
			break;
		case LY_LINETOP:
			break;
		case LY_LYXTABLE:
			break;
		case LY_NEWLINE:
			break;
		case LY_NOBABEL:
			break;
		case LY_NOEPSFIG:
			break;
		case LY_NOINDENT:
			break;
		case LY_NOISOLATIN:
			break;
		case LY_OPTIONS:
			break;
		case LY_PAGEBREAKBOTTOM:
			break;
		case LY_PAGEBREAKSEPARATION:
			break;
		case LY_PAGEBREAKTOP:
			break;
		case LY_PAPERCOLUMNS:
			break;
		case LY_PAPERFONTSIZE:
			break;
		case LY_PAPERORIENTATION:
			break;
		case LY_PAPERPAGESTYLE:
			break;
		case LY_PAPERSIDES:
			break;
		case LY_PAPERSIZE:
			break;
		case LY_PROTECTEDSEPARATOR:
			break;
		case LY_QUOTESLANGUAGE:
			break;
		case LY_QUOTESTIMES:
			break;
		case LY_SECNUMDEPTH:
			break;
		case LY_SERIES:
			break;
		case LY_SHAPE:
			break;
		case LY_SIZE:
			break;
		case LY_TEXTCLASS:
			break;
		case LY_TOCDEPTH:
			break;
		}
	}
}
#endif

//
// Uwe C. Schroeder
// changed to be public and have one parameter
// if par = NULL normal behavior
// else insert behavior
//
void LyXTextParameters::readLyXformat2(LyXParagraph *par)
{
   char* token;
   char c;
   char *tmptok;
   //LyXParagraph *par = new LyXParagraph();
   Inset *inset;
   int pos = 0;
   int obsolete;
   char *obsolete_char;
   int tmpret, tmpret2;
   char depth = 0;
   char footnoteflag = LYX_NO_FOOTNOTE;
   char footnotekind = LYX_FOOTNOTE;
   ::textclass = textclass;
   LyXParagraph *return_par = NULL;
   LyXFont font = GetLyXFont(LYX_LAYOUT_DEFAULT,
			     LYX_LAYOUT_DEFAULT,
			     LYX_LAYOUT_DEFAULT,
			     LYX_LAYOUT_DEFAULT,
			     LYX_LAYOUT_DEFAULT,
			     LYX_LAYOUT_DEFAULT);
   if(!par) {
	   par = new LyXParagraph();
   } else {
	   bufferlist.current()->text->BreakParagraph();
	   return_par=bufferlist.current()->text->FirstParagraph();
	   pos=0;
   }

   c = fgetc(myfile);
   while (!feof(myfile)) {
      /* is it a lyx command? */ 
      if (c=='\\') {
	 token = NextToken();
	 /*printf("Token: %s\n", token);*/
         if (StringEqual(token, "i")) {
               inset = new InsetLatexAccent;
               inset->Read(myfile);
               par->InsertChar(pos, LYX_META_INSET); 
               
               par->InsertInset(pos, inset);
               par->SetFont(pos, font);
               pos++;
         } else
	 if (StringEqual(token, "layout")) {
	    if (!return_par) 
	      return_par = par;
	    else 
	      par = new LyXParagraph(par);
	    pos = 0;
	    tmptok = NextLongToken();
	    par->layout = lyxstyle.NumberOfLayout(textclass, tmptok);
	    par->footnoteflag = footnoteflag;
	    par->footnotekind = footnotekind;
	    par->depth = depth;
	    delete tmptok;
	    font = GetLyXFont(LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT);
	    
	 }
	 else if (StringEqual(token, "end_float")) {
	    if (!return_par) 
	      return_par = par;
	    else 
	      par = new LyXParagraph(par);
	    footnotekind = LYX_FOOTNOTE;
	    footnoteflag = LYX_NO_FOOTNOTE;
	    pos = 0;
	    tmptok = NextLongToken();
	    par->layout = LYX_DUMMY_LAYOUT;
	    delete tmptok;
	    font = GetLyXFont(LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT,
			      LYX_LAYOUT_DEFAULT);
	 }
	 else if (StringEqual(token, "begin_float")) {
	    tmpret = NextStringToken(token, string_footnotekinds);
	    if (tmpret != LYX_LAYOUT_DEFAULT) 
	       footnotekind = tmpret;
	    if (footnotekind == LYX_FOOTNOTE
		|| footnotekind == LYX_MARGIN)
	      footnoteflag = LYX_CLOSED_FOOTNOTE;
	    else 
	      footnoteflag = LYX_OPEN_FOOTNOTE;
	 }
	 else if (StringEqual(token, "begin_deeper")) {
	    depth++;
	 }
	 else if (StringEqual(token, "end_deeper")) {
	    if (!depth) {
	       fprintf(stderr, "LYX_ERROR: end_deeper: depth is already null \n");
	    }
	    else
	       depth--;
	 }
	 else if (StringEqual(token, "begin_preamble")) {
		 readPreamble();
	 }
	 else if (StringEqual(token, "textclass")) {
	    tmptok = NextLongToken();
	    ::textclass = lyxstyle.NumberOfClass(tmptok);
	    textclass = ::textclass;
	    delete tmptok;
	 }
	 else if (StringEqual(token, "options")) {
	    tmptok = NextLongToken();
	    options = tmptok;
	 }
	 else if (StringEqual(token, "language")) {
	    readLanguage();	    
	 }
	 else if (StringEqual(token, "fontencoding")) {
	    obsolete_char = NextLongToken();
	 }
	 else if (StringEqual(token, "inputencoding")) {
	    tmptok = NextLongToken();
	    inputenc = tmptok;
	 }
	 else if (StringEqual(token, "epsfig")) {
	   readEpsfig();
	 }	 
	 else if (StringEqual(token, "fontscheme")) {
	    tmptok = NextLongToken();
	    fonts = tmptok;
	 }
	 else if (StringEqual(token, "noindent")) {
	    par->noindent = 1;
	 }
	 else if (StringEqual(token, "fill_top")) {
	    par->fill_top = 1;
	 }
	 else if (StringEqual(token, "fill_bottom")) {
	    par->fill_bottom = 1;
	 }
	 else if (StringEqual(token, "line_top")) {
	    par->line_top = 1;
	 }
	 else if (StringEqual(token, "line_bottom")) {
	    par->line_bottom = 1;
	 }
	 else if (StringEqual(token, "pagebreak_top")) {
	    par->pagebreak_top = 1;
	 }
	 else if (StringEqual(token, "pagebreak_bottom")) {
	    par->pagebreak_bottom = 1;
	 }
	 else if (StringEqual(token, "paragraph_separation")) {
	    tmpret = NextStringToken(token, string_paragraph_separation);
	    if (tmpret != LYX_LAYOUT_DEFAULT) 
	       paragraph_separation = tmpret;
	 }
	 else if (StringEqual(token, "no_isolatin1")) {
	    obsolete= NextIntToken();
	 }
	 else if (StringEqual(token, "no_babel")) {
	    obsolete = NextIntToken();
	 }
	 else if (StringEqual(token, "no_epsfig")) {
	    obsolete = NextIntToken();
	 }
	 else if (StringEqual(token, "quotes_language")) {
	    tmpret = NextStringToken(token, string_quotes_language);
	    if (tmpret != LYX_LAYOUT_DEFAULT) 
	       quotes_language = tmpret;
	 }
	 else if (StringEqual(token, "quotes_times")) {
	    quotes_times = NextIntToken();
	 }
	 else if (StringEqual(token, "papersize")) {
	    tmpret = NextStringToken(token, string_papersize);
	    if (tmpret != LYX_LAYOUT_DEFAULT) 
	       papersize = tmpret;
	 }
	 else if (StringEqual(token, "paperfontsize")) {
	    fontsize = NextIntToken();
	 }
	 else if (StringEqual(token, "paperorientation")) {
	    tmpret = NextStringToken(token, string_orientation);
	    if (tmpret != LYX_LAYOUT_DEFAULT) 
	       orientation = tmpret;
	 }
	 else if (StringEqual(token, "papercolumns")) {
	    columns = NextIntToken();
	 }
	 else if (StringEqual(token, "papersides")) {
	    sides = NextIntToken();
	 }
	 else if (StringEqual(token, "paperpagestyle")) {
	    tmpret = NextStringToken(token, string_pagestyle);
	    if (tmpret != LYX_LAYOUT_DEFAULT) 
	       pagestyle = tmpret;
	 }
	 else if (StringEqual(token, "secnumdepth")) {
	    secnumdepth = NextIntToken();
	 }
	 else if (StringEqual(token, "tocdepth")) {
	    tocdepth = NextIntToken();
	 }
	 else if (StringEqual(token, "baselinestretch")) {
	    baseline = NextFloatToken();
	 }
	 else if (StringEqual(token, "cursor")) {
	    cursor.par = par;
	    cursor.pos = NextIntToken();
	 }
	 else if (StringEqual(token, "family")) { 
	    font.family = NextStringToken(token, string_family);
	    if (font.family == LYX_MODERN_FAMILY)
	       font.family = LYX_SANS_FAMILY;
	 }
	 else if (StringEqual(token, "series")) {
	    font.series = NextStringToken(token, string_series);
	 }
	 else if (StringEqual(token, "shape")) {
	    font.shape = NextStringToken(token, string_shape);
	 }
	 else if (StringEqual(token, "size")) {
	    font.size = NextStringToken(token, string_size);
	 }
	 else if (StringEqual(token, "latex")) {
	    font.latex = NextStringToken(token, string_latex);
	 }
	 else if (StringEqual(token, "bar")) {
	    font.bar = NextStringToken(token, string_bar);
	 }
	 else if (StringEqual(token, "align")) {
	    tmpret = NextStringToken(token, string_align);
	    if (tmpret != LYX_LAYOUT_DEFAULT) {
	       tmpret2 = 1;
	       for (; tmpret>0; tmpret--)
	       	  tmpret2 = tmpret2 * 2;
	       par->align = tmpret2;
	    }
	 }
	 else if (StringEqual(token, "added_space_top")) {
	    par->added_space_top = NextFloatToken();
	 }
	 else if (StringEqual(token, "added_space_bottom")) {
	    par->added_space_bottom = NextFloatToken();
	 }
	 else if (StringEqual(token, "labelwidthstring")) {
	    par->labelwidthstring = NextLongToken();
	    /* do not delete this token, it is still needed! */ 
	 }
	 else if (StringEqual(token, "end_inset")) {
	    /* simple ignore this. The insets do not have to read this */
		 // but insets should read it, it is a part of the inset
		 // isn't it? Lgb.
	 }
	 else if (StringEqual(token, "begin_inset")) {
	    tmptok = NextToken();
	    /* test the different insets */ 
	    if (StringEqual(tmptok, "Quotes")) {
	       inset = new InsetQuotes;
	       inset->Read(myfile);
	       par->InsertChar(pos, LYX_META_INSET); 
	       par->InsertInset(pos, inset);
	       par->SetFont(pos, font);
	       pos++;
	    }
	    else if (StringEqual(tmptok, "Latex")) {
	       inset = new InsetLatex;
	       inset->Read(myfile);
	       par->InsertChar(pos, LYX_META_INSET); 
	       par->InsertInset(pos, inset);
	       par->SetFont(pos, font);
	       pos++;
	    }
	    else if (StringEqual(tmptok, "LatexDel")) {
	       inset = new InsetLatexDel;
	       inset->Read(myfile);
	       par->InsertChar(pos, LYX_META_INSET); 
	       
	       par->InsertInset(pos, inset);
	       par->SetFont(pos, font);
	       pos++;
	    }
	    else if (StringEqual(tmptok, "\\i")) {
	       inset = new InsetLatexAccent;
	       inset->Read(myfile);
	       par->InsertChar(pos, LYX_META_INSET); 
	       
	       par->InsertInset(pos, inset);
	       par->SetFont(pos, font);
	       pos++;
	    }
	    else if (StringEqual(tmptok, "FormulaLatex")) {
	       inset = new InsetFormulaLatex;
	       inset->Read(myfile);
	       par->InsertChar(pos, LYX_META_INSET); 
	       par->InsertInset(pos, inset);
	       par->SetFont(pos, font);
	       pos++;
	    }
	    else if (StringEqual(tmptok, "Formula")) {
	       inset = new InsetFormula;
	       inset->Read(myfile);
	       par->InsertChar(pos, LYX_META_INSET); 
	       par->InsertInset(pos, inset);
	       par->SetFont(pos, font);
	       pos++;
	    }
	    else if (StringEqual(tmptok, "Figure")) {
	       inset = new InsetFig(100,100);
	       inset->Read(myfile);
	       par->InsertChar(pos, LYX_META_INSET); 
	       par->InsertInset(pos, inset);
	       par->SetFont(pos, font);
	       pos++;
	    }
	    else if (StringEqual(tmptok, "Label")) {
	       inset = new InsetLabel;
	       inset->Read(myfile);
	       par->InsertChar(pos, LYX_META_INSET); 
	       par->InsertInset(pos, inset);
	       par->SetFont(pos, font);
	       pos++;
	    }
	    else if (StringEqual(tmptok, "Info")) {
	       inset = new InsetInfo;
	       inset->Read(myfile);
	       par->InsertChar(pos, LYX_META_INSET); 
	       par->InsertInset(pos, inset);
	       par->SetFont(pos, font);
	       pos++;
	    }
	    delete tmptok;
	 }
	 else if (StringEqual(token, "InsetQuotes")) {
	    inset = new InsetQuotes;
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 
	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "InsetLatex")) {
	    inset = new InsetLatex;
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 
	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "InsetLatexDel")) {
	    inset = new InsetLatexDel;
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 

	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "InsetFormulaLatex")) {
	    inset = new InsetFormulaLatex;
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 
	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "InsetFormula")) {
	    inset = new InsetFormula;
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 
	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "Figure")) {
	    inset = new InsetFig(100,100);
	    inset->Read(myfile);
	    par->InsertChar(pos, LYX_META_INSET); 
	    par->InsertInset(pos, inset);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "newline")) {
	    par->InsertChar(pos, LYX_META_NEWLINE);
	    par->SetFont(pos, font);
	    pos++;
	 }
 	 else if (StringEqual(token, "LyXTable")) {
 	    par->table = new LyXTable(myfile);
 	 }
	 else if (StringEqual(token, "hfill")) {
	    par->InsertChar(pos, LYX_META_HFILL);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "protected_separator")) {
	    par->InsertChar(pos, LYX_META_PROTECTED_SEPARATOR);
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "backslash")) {
	    par->InsertChar(pos, '\\');
	    par->SetFont(pos, font);
	    pos++;
	 }
	 else if (StringEqual(token, "float_placement")) {
	    float_placement = NextToken();
	 }
	 else {
	    fprintf(stderr, "LYX_ERROR: unknown command %s\n", token);
	 }
	 
	 delete token;
      }
      else {
	 /* simple text */
	 if (c!='\n') {
	    par->InsertChar(pos, c);
	    par->SetFont(pos, font);
	    pos++;
	 }
      }
      
      c = fgetc(myfile);
      
   }
   
   if (!return_par)
     return_par = par;

   paragraph = return_par;
}


void LyXTextParameters::readFile()
{
   char* token;
   char c;
   
   c = fgetc(myfile);
   if (c != '#') {
      ungetc(c, myfile);
      readFileOld();
      return;
   }
   while (!feof(myfile)) {
      /* is it a lyx command? */ 
      if (c=='\\') {
	 token = NextToken();
	 if (StringEqual(token, "lyxformat")) {
	    delete token;
	    float format = NextFloatToken();
	    if (format > 1) {
	       if (LYX_FORMAT - format > 0.05) {
		  printf("Warning: read lyxformat %.2f but found %.2f\n",
			 LYX_FORMAT, format);
	       }
	       if (format - LYX_FORMAT > 0.05) {
		  printf("ERROR: read lyxformat %.2f but found %.2f\n",
			 LYX_FORMAT, format);
	       }
	       readLyXformat2();
	       return;
	    }
	    else {
		    readFileOld();
	       return;
	    }
	 }
	 delete token;
      }
      c = fgetc(myfile);
   }
   WriteAlert("LYX_ERROR:", "couldn't find out lyxformat\n", "");
}
	    	    
	      
void LyXTextParameters::writeFile(const char *filename, char flag)
{
  // if flag is != 0 writeFile will not create any GUI warnings, only stderr.
  // Needed for autosave in background or panic save (Matthias 120496)
   FILE* file = fopen(filename, "w");
   LyXFont font1, font2;
   Inset *inset;
   LyXParagraph *par = paragraph;
   char c;
   int i;
   int column;
   
   char footnoteflag = 0;
   char depth = 0;

   int h;
   
   ::textclass = textclass;
   
   if (!file) {
     if (flag)
       fprintf(stderr, "LYX_ERROR: Cannot write file: %s \n", filename);
     else
       WriteAlert("LYX_ERROR:", "Cannot write file:", filename);
     return;
   }
     
   /* some very important information */ 
   char * userName ;
   userName = getenv("LOGNAME");
   if (userName == NULL)
      userName = getenv("USER");
   if (userName == NULL)
      userName = "unknown";
   fprintf(file, "#This file was created by <%s> %s",
	   userName,(char*)date());
   fprintf(file, "#LyX 0.10 (C) 1995 1996 Matthias Ettrich and the LyX Team\n");
   
   /* at the very beginning the used lyx format */
   fprintf(file, "\\lyxformat %.2f\n", LYX_FORMAT);
   
   /* the textclass */
   fprintf(file, "\\textclass %s\n", lyxstyle.NameOfClass(textclass));
   
   /* then the the preamble */
   if (preamble && preamble[0]) {
      fprintf(file, "\\begin_preamble\n");
	{
	   for (i = 0; preamble[i];i++) {
	      fprintf(file, "%c", preamble[i]);
	   }
	   fprintf(file, "\n\\end_preamble\n");
	}
   }
      
   /* the options */ 
   if (options[0]) {
      fprintf(file, "\\options %s\n", options);
   }
   
   /* then the text parameters */ 
   fprintf(file, "\\language %s\n", language);
   fprintf(file, "\\inputencoding %s\n", inputenc);
   fprintf(file, "\\fontscheme %s\n", fonts);
   fprintf(file, "\\epsfig %s\n", epsfig);
   if (float_placement != NULL) {
   	fprintf(file, "\\float_placement %s\n", float_placement);
   }
   fprintf(file, "\\papersize %s \n", string_papersize[papersize]);
   fprintf(file, "\\paperfontsize %d \n", fontsize);
   fprintf(file, "\\baselinestretch %.2f \n", baseline);
   fprintf(file, "\\secnumdepth %d \n", secnumdepth);
   fprintf(file, "\\tocdepth %d \n", tocdepth);
   fprintf(file, "\\paragraph_separation %s \n",
	   string_paragraph_separation[paragraph_separation]);
   fprintf(file, "\\quotes_language %s \n",
	   string_quotes_language[quotes_language]);
   fprintf(file, "\\quotes_times %d \n", quotes_times);
   fprintf(file, "\\paperorientation %s \n", string_orientation[orientation]);
   fprintf(file, "\\papercolumns %d \n", columns);
   fprintf(file, "\\papersides %d \n", sides);
   fprintf(file, "\\paperpagestyle %s \n", string_pagestyle[pagestyle]);
   
   while (par) {
     if (par->footnoteflag != LYX_NO_FOOTNOTE || !par->previous || par->previous->footnoteflag == LYX_NO_FOOTNOTE){
	 
	 /* begins a footnote environment ? */ 
	 if (footnoteflag != par->footnoteflag) {
	    footnoteflag = par->footnoteflag;
	    if (footnoteflag) {
	       fprintf(file, "\n\\begin_float %s ", 
		       string_footnotekinds[par->footnotekind]);
	    }
	    else {
	       fprintf(file, "\n\\end_float ");
	    }
	 }
	 
	 /* begins or ends a deeper area ?*/ 
	 if (depth != par->depth) {
	    if (par->depth > depth) {
	       while (par->depth > depth) {
		  fprintf(file, "\n\\begin_deeper ");
		  depth++;
	       }
	    }
	    else {
	       while (par->depth < depth) {
		  fprintf(file, "\n\\end_deeper ");
		  depth--;
	       }
	    }
	 }
	 
	 /* First write the layout */ 
	 fprintf(file, "\n\\layout %s\n",
		 lyxstyle.NameOfLayout(textclass,par->layout));
	 
	 /* maybe some vertical spaces */ 
	 if (par->added_space_top != 0)
	    fprintf(file, "\\added_space_top %.2f ", par->added_space_top);
	 if (par->added_space_bottom != 0)
	    fprintf(file, "\\added_space_bottom %.2f ",
		    par->added_space_bottom);
	 
	 /* the labelwidthstring used in lists */ 
	 if (par->labelwidthstring)
	    fprintf(file, "\\labelwidthstring %s\n", par->labelwidthstring);
	 
	 /* some lines? */ 
	 if (par->line_top)
	    fprintf(file, "\\line_top ");
	 if (par->line_bottom)
	    fprintf(file, "\\line_bottom ");
	 
	 /* some pagebreaks? */ 
	 if (par->pagebreak_top)
	    fprintf(file, "\\pagebreak_top ");
	 if (par->pagebreak_bottom)
	    fprintf(file, "\\pagebreak_bottom ");
	 
	 /* noindent ? */ 
	 if (par->noindent)
	    fprintf(file, "\\noindent ");
	 
	 /* some fills ? */ 
	 if (par->fill_top)
	    fprintf(file, "\\fill_top ");
	 if (par->fill_bottom)
	    fprintf(file, "\\fill_bottom ");
	 
	 /* what about the alignment */ 
	 if (par->align != LYX_ALIGN_LAYOUT) {
	    switch (par->align) {
	     case LYX_ALIGN_LEFT: h = 1; break;
	     case LYX_ALIGN_RIGHT: h = 2; break;
	     case LYX_ALIGN_CENTER: h = 3; break;
	     default: h = 0; break;
	    }
	    fprintf(file, "\\align %s ", string_align[h]);
	 }
      }
      else {
	 /* dummy layout, that means a footnote ended */ 
	 fprintf(file, "\n\\end_float ");
	 footnoteflag = LYX_NO_FOOTNOTE;
      }
      
      /* It might be a table */ 
      if (par->table){
	fprintf(file, "\\LyXTable\n");
	par->table->Write(file);
      }
      
      /* ok, and now the contents */
      font1 = GetLyXFont(LYX_LAYOUT_DEFAULT,
			 LYX_LAYOUT_DEFAULT,
			 LYX_LAYOUT_DEFAULT,
			 LYX_LAYOUT_DEFAULT,
			 LYX_LAYOUT_DEFAULT,
			 LYX_LAYOUT_DEFAULT);
      
      if (par == cursor.par)
      	 fprintf(file, "\\cursor %d ", cursor.pos);
      
      columns = 0;
      for (i = 0; i < par->last; i++) {
	if (!i){
	  fprintf(file, "\n");
	  columns = 0;
	}
	 font2 = par->GetFontSettings(i);
	 if (font1.family != font2.family) {
	    if (font2.family == LYX_LAYOUT_DEFAULT)
	       fprintf(file, "\n\\family default \n");
	    else
	       fprintf(file, "\n\\family %s \n", string_family[font2.family]);
	    columns = 0;
	 }
	 if (font1.series != font2.series) {
	    if (font2.series == LYX_LAYOUT_DEFAULT)
	       fprintf(file, "\n\\series default \n");
	    else
	       fprintf(file, "\n\\series %s \n", string_series[font2.series]);
	    columns = 0;
	 }
	 if (font1.shape != font2.shape) {
	    if (font2.shape == LYX_LAYOUT_DEFAULT)
	       fprintf(file, "\n\\shape default \n");
	    else
	       fprintf(file, "\n\\shape %s \n", string_shape[font2.shape]);
	    columns = 0;
	 }
	 if (font1.size != font2.size) {
	    if (font2.size == LYX_LAYOUT_DEFAULT)
	       fprintf(file, "\n\\size default \n");
	    else
	       fprintf(file, "\n\\size %s \n", string_size[font2.size]);
	    columns = 0;
	 }
	 if (font1.latex != font2.latex) {
	    if (font2.latex == LYX_LAYOUT_DEFAULT)
	       fprintf(file, "\n\\latex default \n");
	    else
	       fprintf(file, "\n\\latex %s \n", string_latex[font2.latex]);
	 }
      
	 if (font1.bar != font2.bar) {
	    if (font2.bar == LYX_LAYOUT_DEFAULT)
	       fprintf(file, "\n\\bar default \n");
	    else
	       fprintf(file, "\n\\bar %s \n", string_bar[font2.bar]);
	    columns = 0;
	 }
      
	 c = par->GetChar(i);
	 switch (c) {
	  case LYX_META_INSET:
	    inset = par->GetInset(i);
            if (inset)
	      if (inset->DirectWrite()) {
                /* international char, let it write code
		 * directly so it's shorter in the file */
                inset->Write(file);
	      } else {
		fprintf(file, "\n\\begin_inset ");
		inset->Write(file);
		fprintf(file, "\n\\end_inset \n");
		fprintf(file, "\n");
		columns = 0;
	      }
	    break;
	  case LYX_META_NEWLINE: 
	    fprintf(file, "\n\\newline \n");
	    columns = 0;
	    break;
	  case LYX_META_HFILL: 
	    fprintf(file, "\n\\hfill \n");
	    columns = 0;
	    break;
	  case LYX_META_PROTECTED_SEPARATOR: 
	    fprintf(file, "\n\\protected_separator \n");
	    columns = 0;
	    break;
	  case '\\': 
	    fprintf(file, "\n\\backslash \n");
	    columns = 0;
	    break;
	  case '.':
	    fprintf(file, ".\n");
	    columns = 0;
	    break;
	  default:
	    if ((columns > 70 && c==' ')
		|| columns > 79){
	       fprintf(file, "\n");
	       columns = 0;
	    }
	    // this check is to amend a bug. LyX sometimes inserts '\0'
	    // this could cause problems.
	    if (c != '\0')
		    fprintf(file, "%c", c);
	    else if (lyx_debug_level)
		    fprintf(stderr,
			    "(param) writeFile: NUL char in structure.\n");
	    columns++;
	    break;
	 }
	 
	 font1 = font2;
      }
      
      par = par->next;
   }
   
   fprintf(file, "\n");
   fclose(file);
}


void LyXTextParameters::makeLaTeXFile(const char *filename,
				      const char* original_path,
				      int column)
{
   int i;
   LyXParagraph *par = paragraph;
   LyXParagraph *prevpar = par;
   ::textclass = textclass;
   tex_code_break_column = column; 

   FILE *file = fopen(filename, "w");

   if (!file) {
      WriteAlert("LYX_ERROR:","Cannot write file",filename);
      return;
   }
   
   ResetTexRow();

   char * userName ;
   userName = getenv("LOGNAME");
   if (userName == NULL)
      userName = getenv("USER");
   if (userName == NULL)
      userName = "unknown";

   fprintf(file, "%%%% This LaTeX-file was created by <%s> %s",
	   userName,(char*)date());
   fprintf(file, "%%%% LyX 0.10 (C) 1995 1996 by Matthias Ettrich and the LyX Team\n");
   fprintf(file, "\n%%%% Don't edit this file unless you are sure what you are doing.\n");
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   
   // here are few differences between nice LaTeX File and usual:
   // usual is nonstopmode and usual has a 
   // special input@path to allow the including of figures
   // with eigher \input or \epsfig (what figinsets do) .
   // nonstopmode is set if there is a tex_code_break_column. 
   // In this case somebody is interested in the generated LaTeX,
   // so this is OK. input@path is set when the actual parameter
   // original_path is set. This is done for usual tex-file, but not
   // for nice-latex-file. (Matthias 250696)
   if (!tex_code_break_column){
     // code for usual, NOT nice-latex-file
     fprintf(file, "\\nonstopmode\n");
     IncTexRow(par, 0);    
   }
   if (original_path) {
     fprintf(file, "\\makeatletter\n");
     IncTexRow(par, 0);    
     fprintf(file, "\\def\\input@path{{%s/}}\n", original_path);
     IncTexRow(par, 0);    
     fprintf(file, "\\makeatother\n");
     IncTexRow(par, 0);   
   }


   fprintf(file, "\\documentclass[");
   
   fprintf(file, "%dpt", fontsize);
   
   switch (papersize) {
   case PAPER_A4PAPER:
      fprintf(file, ",a4paper");
      break;
   case PAPER_USLETTER:
      fprintf(file, ",letterpaper");
      break;
   case PAPER_A5PAPER:
      fprintf(file, ",a5paper");
      break;
   case PAPER_B5PAPER:
      fprintf(file, ",b5paper");
      break;
   case PAPER_EXECUTIVEPAPER:
      fprintf(file, ",executivepaper");
      break;
   case PAPER_LEGALPAPER:
      fprintf(file, ",legalpaper");
      break;
   }
   
   if (sides == 2)
      fprintf(file, ",twoside");
   else
      fprintf(file, ",oneside");
   
   if (columns == 2)
      fprintf(file, ",twocolumn");
   else
      fprintf(file, ",onecolumn");
   
   if (orientation == ORIENTATION_LANDSCAPE)
      fprintf(file, ",landscape");

   // language should be a parameter to \documentclass
   if (!StringEqual(language, "default")) {
      fprintf(file, ",%s", language);
   }

   /* the user-defined options  */
   char* tmpchar = options;
   if (tmpchar != NULL) {
	   while (tmpchar[0] == ' ')
		   tmpchar++;
   
	   if (tmpchar[0])
		   fprintf(file, ",%s", options);
   }
   
   fprintf(file, "]{%s}\n", lyxstyle.NameOfClass(textclass));
   IncTexRow(par, 0);
   
   // this one is not per buffer
   if (!StringEqual(lyxrc.fontenc, "default")) {
      fprintf(file, "\\usepackage[%s]{fontenc}\n", lyxrc.fontenc);;
      IncTexRow(par, 0);
   }
   
   if (!StringEqual(inputenc, "default")) {
      fprintf(file, "\\usepackage[%s]{inputenc}\n", inputenc);;
      IncTexRow(par, 0);
   }
   if (!StringEqual(language, "default")) {
      fprintf(file, "\\usepackage{babel}\n");
      IncTexRow(par, 0);
   }
   if (!StringEqual(fonts, "default")) {
      fprintf(file, "\\usepackage{%s}\n", fonts);;
      IncTexRow(par, 0);
   }
   if (!StringEqual(epsfig, "none")) {
      fprintf(file, "\\usepackage[%s]{epsfig}\n", epsfig);;
      IncTexRow(par, 0);
   }
   
   /* at the very beginning the text parameters */
   switch (papersize) {
   case PAPER_A4:
      fprintf(file, "\\usepackage{a4}\n");
      IncTexRow(par, 0);
      break;
   case PAPER_A4WIDE:
      fprintf(file, "\\usepackage{a4wide}\n");
      IncTexRow(par, 0);
      break;
   case PAPER_WIDEMARGINSA4:
      fprintf(file, "\\usepackage[widemargins]{a4}\n");
      IncTexRow(par, 0);
      break;
   }

   // let's replace this with the lyx.sty itself. Lgb
   fprintf(file, "\n%%%%\n%%%% BEGIN The lyx specific LaTeX"
	   " commands.\n%%%%\n\n");
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   IncTexRow(par, 0);

   int itel = 0;
   while (lyx_sty[itel]) {
           fprintf(file,"%s\n",lyx_sty[itel]);
	   IncTexRow(par, 0);
	   itel++;
   }

   fprintf(file, "\n%%%%\n%%%% END The lyx specific LaTeX"
	   " commands.\n%%%%\n\n");
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   
   switch (pagestyle) {
   case PAGESTYLE_EMPTY:
      fprintf(file, "\\pagestyle{empty}\n");
      IncTexRow(par, 0);
      break;
   case PAGESTYLE_PLAIN:
      fprintf(file, "\\pagestyle{plain}\n");
      IncTexRow(par, 0);
      break;
   case PAGESTYLE_HEADINGS:
      fprintf(file, "\\pagestyle{headings}\n");
      IncTexRow(par, 0);
      break;
   case PAGESTYLE_FANCYHDR:
      fprintf(file, "\\usepackage{fancyhdr}\n");
      IncTexRow(par, 0);
      fprintf(file, "\\pagestyle{fancy}\n");
      IncTexRow(par, 0);
      break;
   }
   
   fprintf(file, "\\setcounter{secnumdepth}{%d}\n", secnumdepth);
   IncTexRow(par, 0);
   fprintf(file, "\\setcounter{tocdepth}{%d}\n", tocdepth);
   IncTexRow(par, 0);
   
   if (paragraph_separation) {
      fprintf(file, "\\lyxletterstyle\n");
      IncTexRow(par, 0);
   }
   
   if (baseline >= 1.01) {
      fprintf(file, "\\renewcommand{\\baselinestretch}{%.2f}\n", 
              baseline);
      IncTexRow(par, 0);
   }
   
   /* the user-defined praeamble */
   if (preamble) {
     fprintf(file, "\n%%%% Begin LyX user specified preamble:\n");
     IncTexRow(par, 0);
     IncTexRow(par, 0);
     for (i = 0; preamble[i]; i++) {
       fprintf(file, "%c", preamble[i]);
       if (preamble[i]=='\n')
	 IncTexRow(par, 0);
     }

     fprintf(file, "\n");
     IncTexRow(par, 0);
     fprintf(file, "\n%%%% End LyX user specified preamble.\n");
     IncTexRow(par, 0);
     IncTexRow(par, 0);
   }

   fprintf(file, "\\begin{document}\n\n");
   IncTexRow(par, 0);
   IncTexRow(par, 0);
   
   ::float_placement = float_placement;
   while (par) {
     if (par->IsDummy())
       fprintf(stderr, "Error in MakeLateXFile \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);
      
   }
   
   fprintf(file, "\\end{document}\n");
   IncTexRow(prevpar, prevpar->Last());
   fclose(file);
}


/* handle the layout constraints for a given paragraph */
void LyXTextParameters::linuxDocOnePar(FILE *file, LyXParagraph* &par, 
				       LyXParagraph* &prevpar, int is_init)
{
  LyXFont font;
  LyXParagraph *thispar = par;
  LyXParagraph *tmppar;
  int i = 0;

  int error;                     /* error flag */
  char error_message[64];        /* error message */
  int tag;                       /* number of the layout tag */
  static int depth;              /* paragraph depth */
  static int enum_flags[10];     /* enum/itemize status */
  static int desc_on;            /* description mode on/off */
  static int verb_on;            /* verbatim mode on/off */
  static int is_quote;           /* quote mode on/off */
  int special;                   /* special tag */

  /* first time initialisation */
  if (is_init) {
    depth = -1;
    enum_flags[0] = LINUXDOC_NONE;
    desc_on = 0;
    is_quote = 0;
  }   

  /* standard initialisation */
  is_quote = 0;
  verb_on = 0;
  special = LDS_NONE;
  if (par->IsDummy()){
    error = 1;
    fprintf(stderr, "Error in LinuxDocOnePar  \n");
  }
  par->AutoDeleteInsets();

  error = 0;
  tag = LinuxDocTag(lyxstyle.NameOfLayout(textclass, par->GetLayout()));

  if (depth==-1) {
	  // special handling for <toc> tag (\tableofcontents TeX macro)
    if (par->GetChar(0) == LYX_META_INSET) {
      Inset *inset = par->GetInset(0);
      char   lyx_code = inset->LyxCode();
      switch (lyx_code) {
	case LYX_TOC_CODE:
             fprintf(file, "\n<toc>");
             error = 1;             // fake : no futher processing required
             break;
        case LYX_HTMLURL_CODE: // Needed only to get <author> in sgml-file...
             if (tag == LINUXDOC_AUTHOR)
             {
        	fprintf(file, "\n<%s>", linuxdoc_tags[tag]);
             }
             break;
        default:
             break;
      }
    }
    else {
      /* before article body : limited tag set */
      switch(tag) {
      case LINUXDOC_TITLE:
      case LINUXDOC_AUTHOR:
      case LINUXDOC_DATE:
      case LINUXDOC_ABSTRACT:
        fprintf(file, "\n<%s>", linuxdoc_tags[tag]);
        break;
      case LINUXDOC_SECT:
        fprintf(file, "\n<%s>", linuxdoc_tags[tag]);
        depth = 0;
        break;
      default:
        sprintf(error_message, "Style %s not allowed before first Section.\n",
	        linuxdoc_styles[tag]);
        LinuxDocError(par, 0, error_message);
        error = 1;
        break;
      }
    }
  }
  else {
    /* handle enumerate, itemize and quote SGML tags closing */
    switch(enum_flags[depth]) {
    case LINUXDOC_ENUM:
    case LINUXDOC_ITEM:
      if (((tag != enum_flags[depth]) && (tag!=LINUXDOC_VERB) 
	   && (tag!=LINUXDOC_CODE)) || (depth > par->depth)) {
	fprintf(file, "\n</%s>", linuxdoc_tags[enum_flags[depth]]);
	if (depth == 0) enum_flags[depth] = LINUXDOC_NONE;
      }
      break;
    default:
      if ((tag!=LINUXDOC_ITEM) && (tag!=LINUXDOC_ENUM) 
	  && (depth < par->depth)) special = LDS_QUOTE;
      break;
    }

    /* handle descriptions closing */
    if ((desc_on) && (tag != LINUXDOC_DESCR)) {
      fprintf(file, "\n</descrip>\n");
      desc_on = 0;
    }

    /* write opening SGML tags */
    switch(tag) {
    case LINUXDOC_TITLE:
    case LINUXDOC_AUTHOR:
    case LINUXDOC_DATE:
    case LINUXDOC_ABSTRACT:
      sprintf(error_message, "Style %s not allowed after first Section.\n",
	      linuxdoc_styles[tag]);
      LinuxDocError(par ,i, error_message);
      error = 1;
      break;
    case LINUXDOC_PAR:
      if (special == LDS_NONE) fprintf(file, "\n\n");
      else fprintf(file, "%s", special_tags[special]);
      break;
    case LINUXDOC_VERB:
      font = GetFont(par, 0);
      verb_on = 1;
      /* special type handling for tscreen */
      if ((font.family == LYX_TYPEWRITER_FAMILY)
	  && (depth < par->depth)) special = LDS_TSCREEN;
      fprintf(file, "%s\n<verb>", special_tags[special]);
      break;
    case LINUXDOC_CODE:
      fprintf(file, "%s\n<code>", special_tags[special]);
      break;
    case LINUXDOC_SECT:
    case LINUXDOC_SECT1:
    case LINUXDOC_SECT2:
    case LINUXDOC_SECT3:
    case LINUXDOC_SECT4:
      if (depth!=0) {
	for (i=depth; i>=0; i--) {
	  if (enum_flags[depth]!=LINUXDOC_NONE)
	    fprintf(file, "\n</%s>", linuxdoc_tags[enum_flags[depth]]);
	  enum_flags[i] = LINUXDOC_NONE;
	}
      }
      fprintf(file, "%s\n<%s>", special_tags[special], linuxdoc_tags[tag]);
      break;
    case LINUXDOC_ENUM:
    case LINUXDOC_ITEM:
      if (depth < par->depth) {
	depth = par->depth;
	enum_flags[depth] = LINUXDOC_NONE;
      }
      if (enum_flags[depth] != tag) 
	fprintf(file, "\n<%s>", linuxdoc_tags[tag]);
      fprintf(file, "\n<item>");
      depth = par->depth;
      enum_flags[depth] = tag;
      break;
    case LINUXDOC_DESCR:
      if (!desc_on) fprintf(file, "\n<descrip>");
      fprintf(file, "\n<tag>");
      desc_on = 1;
      break;
    default:
      fprintf(file, "\n<%s>", linuxdoc_tags[tag]);
      break;
    }
  }

  if (!error) {
    SimpleLinuxDocOnePar(file, font, par, verb_on, desc_on);
    
    /* write closing SGML tags */
    switch(tag) {
    case LINUXDOC_ENUM:
    case LINUXDOC_ITEM:
    case LINUXDOC_DESCR:
    case LINUXDOC_PAR:
    case LINUXDOC_DATE:
    case LINUXDOC_AUTHOR:
    case LINUXDOC_TITLE:
      break;
    case LINUXDOC_SECT:
    case LINUXDOC_SECT1:
    case LINUXDOC_SECT2:
    case LINUXDOC_SECT3:
    case LINUXDOC_SECT4:
      fprintf(file, "\n<p>");
      break;
    default:
      fprintf(file, "\n</%s>", linuxdoc_tags[tag]);
      break;
    }
    if (special != LDS_NONE) fprintf(file, "%s", special_close[special]);
  }

  if (depth != -1) depth = par->depth;
  tmppar = par;
  prevpar = par;
  par = par->next;


  while (par && par->footnoteflag != LYX_NO_FOOTNOTE
	 && par->footnoteflag != thispar->footnoteflag) {
    /* no footnote support yet */
  }
}


void LyXTextParameters::makeLinuxDocFile(const char* filename, int column)
{
   int is_init = 1;
   LyXParagraph *par = paragraph;
   LyXParagraph *prevpar = par;

   FILE *file = fopen(filename, "w");
   ::textclass = textclass;
   tex_code_break_column = column; 

   if (!file) {
      WriteAlert("LYX_ERROR:", "Cannot write file",filename);
      return;
   }
   
   ResetTexRow();

   fprintf(file, "<!-- LinuxDoc file was created by LyX 0.10 (C) 1995 1996 by "
	"Matthias Ettrich -->\n");
   fprintf(file, "<!-- Export filter v0.5 by Pascal Andre               "
        "                 -->\n");
   
   fprintf(file, "\n<!doctype linuxdoc system>\n\n");
   fprintf(file, "<article>\n");   

   while (par) {
     if (par->IsDummy())
      	 fprintf(stderr, "Error in MakeLinuxDocFile \n");
      else
      	linuxDocOnePar(file, par, prevpar, is_init);
      is_init = 0;
   }
   
   fprintf(file, "\n\n</article>\n");
   fclose(file);
}


/* gets tag number from layout name */
int LyXTextParameters::LinuxDocTag(const char *layout)
{
  int i;

  for (i=0; i<LINUXDOC_NONE; i++)
    if (StringEqual(linuxdoc_styles[i], layout)) return i;

  return LINUXDOC_NONE;
}


/* push a tag in a style stack */
void LyXTextParameters::push_tag(FILE *file, const char *tag,
				 int& pos, char stack[5][3])
{
  int j;

  /* pop all previous tags */
  for (j=pos; j>=0; j--)
    fprintf(file, "</%s>", stack[j]); 

  /* add new tag */
  sprintf(stack[++pos], "%s", tag);

  /* push all tags */
  for (j=0; j<=pos; j++)
    fprintf(file, "<%s>", stack[j]);
}


// pop a tag from a style stack
void LyXTextParameters::pop_tag(FILE *file, const char * tag,
				int& pos, char stack[5][3])
{
  int j;

  // pop all tags till specified one
  for (j=pos; (j>=0) && (strcmp(stack[j], tag)); j--)
    fprintf(file, "</%s>", stack[j]);

  // closes the tag
  fprintf(file, "</%s>", tag);

  // push all tags, but the specified one
  for (j=j+1; j<=pos; j++) {
    fprintf(file, "<%s>", stack[j]);
    strcpy(stack[j-1], stack[j]);
  }
  pos --;
}


// gets next latex parameter
int LyXTextParameters::GetNextParameter(LyXParagraph *par, int pos,
					char *buffer, int size)
{
  int i, flag;
  char c;
  Inset *inset;

  flag = 1;
  BZERO(buffer, size);
  for (i=pos+1; i<=par->last && flag; i++) {
    c = par->GetChar(i);
    if (c == LYX_META_INSET) {
      inset = par->GetInset(i);
      switch (inset->LyxCode()) {
      case LYX_QUOTE_CODE:
        c='\"';
        break;
      case LYX_SEPARATOR_CODE:
      case LYX_ENDING_CODE:
	flag = 0;
	break;
      case LYX_TOC_CODE:
	LinuxDocError(par, i, "Error : table of contents not allowed "
		      "in body.\n");
	break;
       case LYX_IGNORE_CODE:
	 // ignore
	 break;
      default:
	LinuxDocError(par, i, "Error : unhandled inset.\n");
	break;
      }
    }
    if (flag) *buffer=c;
    buffer++;
  }

  if (flag) {
    LinuxDocError(par, pos, "Error : incomplete macro.\n");
    return 0;
  }
  return i;
}


/* handle internal paragraph parsing -- layout already processed */

void LyXTextParameters::SimpleLinuxDocOnePar(FILE *file, LyXFont &font1, 
                                 LyXParagraph *par, int &verb_on, 
                                 int &desc_on) 
{
  LyXFont font2;
  char c;
  Inset *inset;
  int main_body, j;

  int is_tt = 0;               /* typewriter font flag */
  int is_bf = 0;               /* bold font flag */
  int is_em = 0;               /* emphasis (italic) font flag */
  int is_quote = 0;            /* quote (paragraph indenting) flag */

  int stack_num = -1;          /* style stack position */
  char stack[5][3];    	       /* style stack */

  if (lyxstyle.Style(textclass, par->GetLayout())->labeltype != LABEL_MANUAL)
    main_body = 0;
  else
    main_body = par->BeginningOfMainBody();
   
  /* gets paragraph main font */
  if (main_body > 0)
    font1 = lyxstyle.Style(textclass, par->GetLayout())->labelfont;
  else
    font1 = lyxstyle.Style(textclass, par->GetLayout())->font;

  
  /* parsing main loop */
  for (int i = 0; i < par->last; i++) {

    /* handle quote tag */
    if (i == main_body && !par->IsDummy()) {
      if (main_body > 0)
	font1 = lyxstyle.Style(textclass, par->GetLayout())->font;
      if ((!verb_on) && (par->align == LYX_ALIGN_RIGHT)) {
	fprintf(file, "<quote>");
	is_quote = 1;
      }
    }

    font2 = GetFont(par, i);      

    /* handle <tt> tag */
    if (font1.family != font2.family) {
      if (verb_on)
	LinuxDocError(par, 0, "Error : TypeWriter font not allow in "
		      "Verbatim.\n");
      else {
	if (font2.family == LYX_TYPEWRITER_FAMILY) {
	  push_tag(file, "tt", stack_num, stack);
	  is_tt = 1;
	}
	else if (is_tt == 1) {
	  pop_tag(file, "tt", stack_num, stack);
	  is_tt = 0;
	}
      }
    }

    /* handle <bf> tag */
    if (font1.series != font2.series) {
      if (verb_on)
	LinuxDocError(par, 0, "Error : Bold font not allow in Verbatim.\n");
      else {
	if (font2.series == LYX_BOLD_SERIES) {
	  push_tag(file, "bf", stack_num, stack);
	  is_bf = 1;
	}
	else if (is_bf == 1) {
	  pop_tag(file, "bf", stack_num, stack);
	  is_bf = 0;
	}
      }
    }

    /* handle <em> tag */
    if ((!verb_on) && (font1.shape != font2.shape)) {
      if (verb_on)
	LinuxDocError(par, 0, "Error : Emphasis (italic font)  not allow in "
		      "Verbatim.\n");
      else {
	if (font2.shape == LYX_ITALIC_SHAPE) {
	  push_tag(file, "em", stack_num, stack);
	  is_em = 1;
	}
	else if (is_em == 1) {
	  pop_tag(file, "em", stack_num, stack);
	  is_em = 0;
	}
      }
    }
      
    c = par->GetChar(i);
      
    if (c == LYX_META_INSET) {
      inset = par->GetInset(i);
      switch (inset->LyxCode()) {
      case LYX_TOC_CODE:
	LinuxDocError(par, i, "Error : table of contents  not allowed "
		      "in body.\n");
	break;
      case LYX_QUOTE_CODE:
        fprintf(file, "\"");
        break;
      case LYX_MARK_CODE:
	{
	  int j;
	  char label[64];

	  if ((j = GetNextParameter(par, i, label, 64))) {
	    i = j;
	    fprintf(file, "<label id=\"%s\">", label);
	  }
	  i++;
	}
	break;
      case LYX_LABEL_CODE:
	   {
	      fprintf(file, "<label id=\"%s\">", ((InsetLabel*) inset)->GetLabel(1));
	   }
	 break;
      case LYX_REF_CODE:
	{
	  int j;
	  char label[64], name[64];

	  if ((j = GetNextParameter(par, i, label, 64)) && 
	      (j = GetNextParameter(par, j-1, name, 64))) {
	    i = j;
	    fprintf(file, "<ref id=\"%s\" name=\"%s\">", label, name);
	  }
	}
	break;
      case LYX_URL_CODE:
	{
	  int j;
	  char url[64], name[64];

	  if ((j = GetNextParameter(par, i, url, 64)) && 
	      (j = GetNextParameter(par, j-1, name, 64))) {
	    i = j;
	    fprintf(file, "<url url=\"%s\" name=\"%s\">", url, name);
	  }
	}
	break;
      case LYX_HTMLURL_CODE:
	{
	  int j;
	  char url[64], name[64];

	  if ((j = GetNextParameter(par, i, url, 64)) && 
	      (j = GetNextParameter(par, j-1, name, 64))) {
	    i = j;
	    fprintf(file, "<htmlurl url=\"%s\" name=\"%s\">", url, name);
	  }
	}
	break;
       case LYX_IGNORE_CODE:
	 /* ignore */ 
	 break;
       default:
	 LinuxDocError(par, i, "Error : unhandled inset.\n");
	 i++;
	 break;
      }
    }
    else {
      switch (c) {
      case LYX_META_HFILL:
	break;
      case LYX_META_PROTECTED_SEPARATOR: 
	fprintf(file, " "); break;
      case LYX_META_NEWLINE:
	fprintf(file, "\n"); break;
      case '&': 
	fprintf(file, "&amp;"); break;
      case '<': 
	fprintf(file, "&lt;"); break;
      case '>':
	fprintf(file, "&gt;"); break;
      case '$': 
	fprintf(file, "&dollar;"); break;
      case '#': 
	fprintf(file, "&num;"); break;
      case '%': 
	fprintf(file, "&percnt;"); break;
      case '~': 
	fprintf(file, "&tilde;"); break;
      case '\"': 
	/* should work says the doc, but ... fprintf(file, "&dquote;"); */
	fprintf(file, "\"");
	break;
      case ' ':
	if (desc_on == 1) {
	  fprintf(file, "</tag>");
	  desc_on = 2;
	}
	else fprintf(file, " ");
	break;
      default:
	fprintf(file, "%c", c); break;
      }
	 
    }
      
    font1 = font2;
  }
   
  /* needed if there is an optional argument but no contents */ 
  if (main_body > 0 && main_body == par->last) {
    font1 = lyxstyle.Style(textclass, par->GetLayout())->font;
  }

  /* pop all defined Styles (non verbatim) */
  if (!verb_on) for (j=stack_num; j>=0; j--)
    fprintf(file, "</%s>", stack[j]);

  /* closes quote tag if necessary */
  if (is_quote) fprintf(file, "</quote>");

  /* resets description flag correctly */
  if (desc_on == 2) desc_on = 1;
}


/* print an error message */
void LyXTextParameters::LinuxDocError(LyXParagraph *par, int pos,
				      const char *message) 
{
  InsetError *new_inset;

  /* insert an error marker in text */
  new_inset = new InsetError(message);
  par->InsertChar(pos, LYX_META_INSET);
  par->InsertInset(pos, new_inset);
}
