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

#include "config.h"

#include <stdio.h>

#include "lyxrc.h"
#include "definitions.h"
#include "toolbar.h"
#include "layout.h"
#include "keybind.h"
#include "lyxserver.h"
#include "lyxlex.h"
#include "lyxparameters.h"
#include "paths.h"
#include "lyx_cb.h"
#include "intl.h"

extern char textclass; /* from file.C I really don't know what it is
			* used for. */

extern void Obsolete(LyXLexClass*);

enum _LyXRCTags {
	RC_BEGINPREAMBLE=1,
	RC_BEGINTOOLBAR,
	RC_OPTIONS,
	RC_TEXTCLASS,
	RC_LANGUAGE,
	RC_FONTENCODING,
	RC_INPUTENCODING,
	RC_FONTSCHEME,
	RC_PRINTER,
	RC_PRINTCOMMAND,
	RC_PRINTEVENPAGEFLAG,
	RC_PRINTODDPAGEFLAG,
	RC_PRINTREVERSEFLAG,
	RC_PRINTLANDSCAPEFLAG,
	RC_PRINTTOPRINTER,
	RC_PRINTTOFILE,
	RC_PRINTFILEEXTENSION,
	RC_PRINTEXSTRAOPTIONS,
	RC_PRINTSPOOLCMD,
	RC_LATEXCOMMAND,
	RC_NORMALFONTSIZE,
	RC_FONTSIZES,
	RC_AUTOSAVE,
	RC_XDVIEXTRAOPTIONS,
	RC_SGMLEXTRAOPTIONS,
	RC_LYXLAYOUTLIB,
	RC_TEMPLATEPATH,
	RC_TEMPDIRPATH,
	RC_USETEMPDIR,
	RC_LASTFILES,
	RC_ROMANFONT,
	RC_SANSFONT,
	RC_TYPEWRITERFONT,
	RC_FONTNORM,
	RC_PARAGRAPHSEPARATION,
	RC_EPSFIG,
	RC_FLOATPLACEMENT,
	RC_QUOTESLANGUAGE,
	RC_QUOTESTIMES,
	RC_PAPERSIZE,
	RC_PAPERFONTSIZE,
	RC_PAPERORIENTATION,
	RC_PAPERCOLUMNS,
	RC_PAPERSIDES,
	RC_PAPERPAGESTYLE,
	RC_BASELINESTRETCH,
	RC_ALLOWACCENTS,
	RC_SECNUMDEPTH,
	RC_TOCDEPTH,
	RC_AUTOREGIONDELETE,
	RC_BIND,
	RC_SERVERPIPE,
	RC_NOBABEL,
	RC_NOEPSFIG,
	RC_NOMENUACCELERATORS,
	RC_INPUT,
	RC_BINDFILE,
	RC_KBMAP,
	RC_KBMAP_PRIMARY,
	RC_KBMAP_SECONDARY,
	RC_LAST	
};

static keyword_item lyxrcTags[] = {
	{ "\\allow_accents", RC_ALLOWACCENTS },
	{ "\\auto_region_delete", RC_AUTOREGIONDELETE },
	{ "\\autosave", RC_AUTOSAVE },
	{ "\\baselinestretch", RC_BASELINESTRETCH },
	{ "\\begin_preamble", RC_BEGINPREAMBLE },
	{ "\\begin_toolbar", RC_BEGINTOOLBAR },
	{ "\\bind", RC_BIND },
	{ "\\bind_file", RC_BINDFILE },
	{ "\\epsfig", RC_EPSFIG },
	{ "\\float_placement", RC_FLOATPLACEMENT },
	{ "\\font_norm", RC_FONTNORM },
	{ "\\fontencoding", RC_FONTENCODING },
	{ "\\fontscheme", RC_FONTSCHEME },
	{ "\\fontsizes", RC_FONTSIZES },
	{ "\\input", RC_INPUT },
	{ "\\inputencoding", RC_INPUTENCODING },
	{ "\\kbmap", RC_KBMAP },
	{ "\\kbmap_primary", RC_KBMAP_PRIMARY },
	{ "\\kbmap_secondary", RC_KBMAP_SECONDARY },
	{ "\\language", RC_LANGUAGE },
	{ "\\lastfiles", RC_LASTFILES },
	{ "\\latex_command", RC_LATEXCOMMAND },
	{ "\\lyx_layout_lib", RC_LYXLAYOUTLIB },
	{ "\\no_babel", RC_NOBABEL },
	{ "\\no_epsfig", RC_NOEPSFIG },
	{ "\\normal_fontsize", RC_NORMALFONTSIZE },
	{ "\\options", RC_OPTIONS },
	{ "\\papercolumns", RC_PAPERCOLUMNS },
	{ "\\paperfontsize", RC_PAPERFONTSIZE },
	{ "\\paperorientation", RC_PAPERORIENTATION },
	{ "\\paperpagestyle", RC_PAPERPAGESTYLE },
	{ "\\papersides", RC_PAPERSIDES },
	{ "\\papersize", RC_PAPERSIZE },
	{ "\\paragraph_separation", RC_PARAGRAPHSEPARATION },
	{ "\\print_command", RC_PRINTCOMMAND },
	{ "\\print_evenpage_flag", RC_PRINTEVENPAGEFLAG },
	{ "\\print_extra_options", RC_PRINTEXSTRAOPTIONS },
	{ "\\print_file_extension", RC_PRINTFILEEXTENSION },
	{ "\\print_landscape_flag", RC_PRINTLANDSCAPEFLAG },
	{ "\\print_oddpage_flag", RC_PRINTODDPAGEFLAG },
	{ "\\print_reverse_flag", RC_PRINTREVERSEFLAG },
	{ "\\print_spool_cmd", RC_PRINTSPOOLCMD },
	{ "\\print_to_file", RC_PRINTTOFILE },
	{ "\\print_to_printer", RC_PRINTTOPRINTER },
	{ "\\printer", RC_PRINTER },
	{ "\\quotes_language", RC_QUOTESLANGUAGE },
	{ "\\quotes_times", RC_QUOTESTIMES },
	{ "\\roman_font", RC_ROMANFONT },
	{ "\\sans_font", RC_SANSFONT },
	{ "\\secnumdepth", RC_SECNUMDEPTH },
	{ "\\serverpipe", RC_SERVERPIPE },
	{ "\\sgml_extra_options", RC_SGMLEXTRAOPTIONS },
	{ "\\tempdir_path", RC_TEMPDIRPATH },
	{ "\\template_path", RC_TEMPLATEPATH },
	{ "\\textclass", RC_TEXTCLASS },
	{ "\\tocdepth", RC_TOCDEPTH },
	{ "\\typewriter_font", RC_TYPEWRITERFONT },
	{ "\\use_tempdir", RC_USETEMPDIR },
	{ "\\xdvi_extra_options", RC_XDVIEXTRAOPTIONS },
};

/* Let the range depend of the size of lyxrcTags.  Alejandro 240596 */
static const lyxrcCount = sizeof(lyxrcTags) / sizeof(keyword_item);

LyXRC::LyXRC()
{
   //fprintf (stderr, "LyXRC default constructor called\n");
   allowAccents = false;
   fontenc = StringCopy(""); /* is this bad? We should try to
				* make people use T1 encoding enstead
				* of OT1. Lgb
			      * Yes, but I have problems with math
			      * symbols. Maybe it's my TeX version, but
			      * it's not bad if we let the user choose.
			      * Alejandro 200696
				*/
   // Why isn't the printer read from the environment? (I'll change that,
   // because I think this is a bug.) Lgb
   printer = getenv("PRINTER");
   if (getenv("PRINTER") == NULL)
	   printer = StringCopy("lp");
   else printer = StringCopy(getenv("PRINTER")); // now it is safe to use
   // delete[] on printer   
   print_command = StringCopy ("dvips");
   print_evenpage_flag = StringCopy ("-B");
   print_oddpage_flag =StringCopy ("-A");
   print_reverse_flag = StringCopy ("-r");
   print_landscape_flag = StringCopy ("-t landscape");
   print_to_printer = StringCopy ("-P");
   print_to_file = StringCopy ("-o");
   print_file_extension = StringCopy (".ps");
   print_extra_options = StringCopy ("");
   print_spool_cmd = StringCopy ("");
   xdvi_extra_options = StringCopy ("");
   sgml_extra_options = StringCopy ("");
   lyx_layout_lib = StringCopy (".");
   tempdir_path = StringCopy ("/tmp");
   use_tempdir = true;
   template_path = StringCopy ("");
   latex_command = StringCopy ("latex");
   default_zoom = 14;
   autosave = 300;
   auto_region_delete = true;
   lastfiles = NULL;
}


LyXRC::~LyXRC()
{
   delete printer;
   delete print_command;
   delete print_evenpage_flag;
   delete print_oddpage_flag;
   delete print_reverse_flag;
   delete print_landscape_flag;
   delete print_to_printer;
   delete print_to_file;
   delete print_file_extension;
   delete print_extra_options;
   delete print_spool_cmd;
   delete xdvi_extra_options;
   delete sgml_extra_options;
   delete lyx_layout_lib;
   delete template_path;
   delete latex_command;
   if (lastfiles) delete lastfiles;
}


int LyXRC::Read(const char* filename)
{
	int error = 0;
	int tmpret;
	LyXLexClass lexrc(lyxrcTags, lyxrcCount);
	if (lyx_debug_level & DEBUG_LEX_PARSER)
		lexrc.printTable();
	lexrc.setFile(filename);
	if (!lexrc.IsOK()) return -2;
	
	
	::textclass = parameters.textclass;
	
	while (lexrc.IsOK() && !error) {

		switch(lexrc.lex()) {
		case LEX_FEOF:
			break;
		case LEX_UNDEF:
			fprintf(stderr,
				"Line %d: Parse Error: Unknown tag %s.\n",
				lexrc.GetLineNo(), lexrc.text());
			error = 1;
			break;
		case RC_INPUT:
		        if (lexrc.next())
			        Read(lexrc.text());
			break;
		  case RC_BINDFILE:                     // RVDK_PATCH_5
			  if (lexrc.next()) {
				  if ( system_lyxdir ) {
					  char tmp[100];
					  // can this be considered anything else
					  // than a hack?
					  sprintf(tmp, "%s/%s", system_lyxdir,"bind");
					  //fprintf(stderr, "bind dir: %s\n", tmp);
					  PathPush (tmp);
					  if (Read(lexrc.text()) >= 0) 
						  BindFileSet = true;
					  PathPop(); 
				  }
			  }
			  break;
		case RC_BEGINPREAMBLE:
			parameters.readPreamble(&lexrc);
			//fprintf(stderr,"Preamble: '%s'\n",
			//parameters.preamble); fflush(stderr);
			break;
			
		case RC_BEGINTOOLBAR:
			toolbar.read(&lexrc);
			break;
			
		case RC_OPTIONS:
			if (lexrc.EatLine())
				parameters.options = lexrc.GetString();
			if (lyx_debug_level & DEBUG_LEX_PARSER)
				fprintf(stderr,"Reading options[%s]\n",
					parameters.options);
			break;
			
		case RC_TEXTCLASS:
			if (lexrc.next()) {
			if (lyx_debug_level & DEBUG_LEX_PARSER)
				fprintf(stderr,"Reading textclass\n");
			        ::textclass = lyxstyle.NumberOfClass(lexrc.text());
				parameters.textclass = ::textclass;
			}
			break;

		  case RC_KBMAP:
			if (lexrc.next())
			  KeyMapOn(lexrc.GetBool());
			  break;

		  case RC_KBMAP_PRIMARY:
			if (lexrc.next())
			  setPrimary(lexrc.GetString());
			  break;

		  case RC_KBMAP_SECONDARY:
			if (lexrc.next())
			  setSecondary(lexrc.GetString());
			  break;
			  
		case RC_LANGUAGE:
			parameters.readLanguage(&lexrc);
			if (lyx_debug_level & DEBUG_LYXRC)
				fprintf(stderr,"Language: `%s'\n",
					parameters.language);
		        break;
			
		case RC_FONTENCODING:
			if (lexrc.next())
				fontenc = lexrc.GetString();
			break;
			
		case RC_INPUTENCODING:
			if (lexrc.next())
				parameters.inputenc = lexrc.GetString();
			break;
			
		case RC_FONTSCHEME:
			if (lexrc.next())
				parameters.fonts = lexrc.GetString();
			break;
			
		case RC_PRINTER:
			if (lexrc.next())
				printer = lexrc.GetString();
			break;
			
		case RC_PRINTCOMMAND:
			if (lexrc.next())
				print_command = lexrc.GetString();
			break;
			
		case RC_PRINTEVENPAGEFLAG:
			if (lexrc.next())
				print_evenpage_flag = lexrc.GetString();
			break;
			
		case RC_PRINTODDPAGEFLAG:
			if (lexrc.next())
				print_oddpage_flag = lexrc.GetString();
			break;
			
		case RC_PRINTREVERSEFLAG:
			if (lexrc.next())
				print_reverse_flag = lexrc.GetString();
			break;
			
		case RC_PRINTLANDSCAPEFLAG:
			if (lexrc.next())
				print_landscape_flag = lexrc.GetString();
			break;
			
		case RC_PRINTTOPRINTER:
			if (lexrc.next())
				print_to_printer = lexrc.GetString();
			break;
			
		case RC_PRINTTOFILE:
			if (lexrc.next())
				print_to_file = lexrc.GetString();
			break;
			
		case RC_PRINTFILEEXTENSION:
			if (lexrc.next())
				print_file_extension = lexrc.GetString();
			break;
			
		case RC_PRINTEXSTRAOPTIONS:
			if (lexrc.EatLine())
				print_extra_options = lexrc.GetString();
			break;
			
		case RC_PRINTSPOOLCMD:
			if (lexrc.next())
				print_spool_cmd = lexrc.GetString();
			break;
			
		case RC_LATEXCOMMAND:
			if (lexrc.next())
				latex_command = lexrc.GetString();
			break;
			
		case RC_NORMALFONTSIZE:
			if (lexrc.next())
				default_zoom = lexrc.GetInteger();
			break;
			
		case RC_FONTSIZES:
			if (lexrc.next())
				font_sizes[LYX_SIZE_TINY] =
					lexrc.GetInteger();
			if (lexrc.next())
				font_sizes[LYX_SIZE_SMALL] =
					lexrc.GetInteger();
			if (lexrc.next())
				font_sizes[LYX_SIZE_NORMAL] =
					lexrc.GetInteger();
			if (lexrc.next())
				font_sizes[LYX_SIZE_LARGE] =
					lexrc.GetInteger();
			if (lexrc.next())
				font_sizes[LYX_SIZE_LARGER] =
					lexrc.GetInteger();
			if (lexrc.next())
				font_sizes[LYX_SIZE_LARGEST] =
					lexrc.GetInteger();
			if (lexrc.next())
				font_sizes[LYX_SIZE_HUGE] =
					lexrc.GetInteger();
			if (lexrc.next())
				font_sizes[LYX_SIZE_GIANT] =
					lexrc.GetInteger();
			break;
			
		case RC_AUTOSAVE:
			if (lexrc.next())
				autosave = lexrc.GetInteger();
			break;
			
		case RC_XDVIEXTRAOPTIONS:
			if (lexrc.EatLine())
				xdvi_extra_options = lexrc.GetString();
			break;
			
		case RC_SGMLEXTRAOPTIONS:
			if (lexrc.EatLine())
				sgml_extra_options = lexrc.GetString();
			break;
			
		case RC_LYXLAYOUTLIB:
			if (lexrc.next())
				lyx_layout_lib = lexrc.GetString();
			break;
			
		case RC_TEMPLATEPATH:
			if (lexrc.next())
				template_path = lexrc.GetString();
			break;
			
		case RC_TEMPDIRPATH:
			if (lexrc.next())
				template_path = lexrc.GetString();
			break;
			
		case RC_USETEMPDIR:
			if (lexrc.next())
				use_tempdir = lexrc.GetBool();
			break;
			
		case RC_LASTFILES:
			if (lexrc.next())
				lastfiles = lexrc.GetString();
			break;
			
		case RC_ROMANFONT:
			if (lexrc.next())
			roman_font_name = lexrc.GetString();
			break;
			
		case RC_SANSFONT:
			if (lexrc.next())
			sans_font_name = lexrc.GetString();
			break;
			
		case RC_TYPEWRITERFONT:
			if (lexrc.next())
			typewriter_font_name = lexrc.GetString();
			break;
			
		case RC_FONTNORM:
			if (lexrc.next())
			font_norm = lexrc.GetString();
			break;
			
		case RC_PARAGRAPHSEPARATION:
				tmpret = lexrc.FindToken(string_paragraph_separation);
				if (tmpret >= 0) 
		                        parameters.paragraph_separation = tmpret;
			break;
		       
		 case RC_EPSFIG:
			parameters.readEpsfig(&lexrc);
			break;
			
		case RC_QUOTESLANGUAGE:
				tmpret = lexrc.FindToken(string_quotes_language);
				if (tmpret >= 0) 
					parameters.quotes_language = tmpret;
			break;
			
		case RC_QUOTESTIMES:
			if (lexrc.next())
				parameters.quotes_times =  lexrc.GetInteger();
			break;
			
		case RC_PAPERSIZE:
				tmpret = lexrc.FindToken(string_papersize);
				if (tmpret >= 0) 
					parameters.papersize = tmpret;
			break;
			
		case RC_PAPERFONTSIZE:
			if (lexrc.next())
			parameters.fontsize = lexrc.GetInteger();
			break;
			
		case RC_PAPERORIENTATION:
				tmpret = lexrc.FindToken(string_orientation);
				if (tmpret >= 0) 
					parameters.orientation = tmpret;
			break;
			
		case RC_PAPERCOLUMNS:
			if (lexrc.next())
			parameters.columns = lexrc.GetInteger();
			break;
			
		case RC_PAPERSIDES:
			if (lexrc.next())
			parameters.sides = lexrc.GetInteger();
			break;
			
		case RC_PAPERPAGESTYLE:
				tmpret = lexrc.FindToken(string_pagestyle);
				if (tmpret >= 0) 
					parameters.pagestyle = tmpret;
			break;
			
		case RC_BASELINESTRETCH:
			if (lexrc.next())
			parameters.baseline = lexrc.GetFloat();
			break;
			
		case RC_ALLOWACCENTS:
			if (lexrc.next()) 
				allowAccents = lexrc.GetBool();
			break;
			
		case RC_SECNUMDEPTH:
			if (lexrc.next())
			parameters.secnumdepth = lexrc.GetInteger();
			break;
			
		case RC_TOCDEPTH:
			if (lexrc.next())
			parameters.tocdepth = lexrc.GetInteger();
			break;
		
		case RC_AUTOREGIONDELETE:
			/* -------> Auto region delete defaults to true. */
		        if (lexrc.next())
		        	auto_region_delete = lexrc.GetBool();
			break;
			
		case RC_BIND:
		{
			// !!!chb, dynamic key binding...
			int action, res=0;
			kb_sequence tmpseq;
			char seq[100], cmd[100];
			
			if (lexrc.lex()==LEX_DATA)  {
				strcpy(seq, lexrc.text());
				if (lyx_debug_level & DEBUG_LYXRC) {
					fprintf(stderr,"RC_BIND: seq: `%s'\n",
						seq);
				}
			}
		        else
		            { error = 1; break; }
		   
			if (lexrc.lex()==LEX_DATA) {
			    strcpy(cmd, lexrc.text());
				if (lyx_debug_level & DEBUG_LYXRC) {
					fprintf(stderr,"RC_BIND: cmd: `%s'\n",
						cmd);
				}
			}
		        else
		            { error = 1; break; }
			
			if ((action = LookupLyxFunc(cmd))>=0) {
				if (lyx_debug_level & DEBUG_LYXRC) {
					fprintf(stderr,
						"RC_BIND: action: ´%d'\n",
						(int)action);
				}
				res = toplevel_keymap->bind(seq,
							    action);
				if (res == 1)
					fprintf(stderr,
						"LyXRC ERROR: invalid"
						" keysequence `%s'\n", seq);
			} else
				fprintf(stderr, "LYX_ERROR: unknown lyx"
					" func /%s/\n", cmd);

			break;
		}
		case RC_SERVERPIPE:
			if (lexrc.lex()==LEX_DATA) {
			   // In this case we must allocate memory.
			   // It is done automatically by GetString().
			   // [Alejandro]
			   lyxpipes.pipename = lexrc.GetString();
			}
			break;
			
		case RC_NOBABEL:
		case RC_NOEPSFIG:
			Obsolete(&lexrc);
			break;
		case RC_FLOATPLACEMENT:
			if (lexrc.next())
				parameters.float_placement = lexrc.GetString();
			break;
		}
	}
	return 0;
}


void LyXRC::Print()
{
  printf("The current internal LyXRC:\n");  
}


LyXRC lyxrc;

