]> git.lyx.org Git - lyx.git/blobdiff - src/tex2lyx/preamble.C
* src/LyXAction.C: mark goto-clear-bookmark as working without buffer
[lyx.git] / src / tex2lyx / preamble.C
index cd43c63a8417afbc6c3612dd3ddf666abcc2369c..acb066814aeda319778ae5ee5000b572f1158ad8 100644 (file)
@@ -18,6 +18,7 @@
 #include "lyxtextclass.h"
 #include "lyxlex.h"
 #include "support/filetools.h"
+#include "support/lstrings.h"
 
 #include <algorithm>
 #include <iostream>
@@ -26,6 +27,9 @@
 #include <vector>
 #include <map>
 
+
+namespace lyx {
+
 using std::istringstream;
 using std::ostream;
 using std::ostringstream;
@@ -34,17 +38,21 @@ using std::vector;
 using std::cerr;
 using std::endl;
 
-using lyx::support::LibFileSearch;
+using support::FileName;
+using support::libFileSearch;
 
 // special columntypes
 extern std::map<char, int> special_columns;
 
+std::map<string, vector<string> > used_packages;
+
 namespace {
 
-const char * known_languages[] = { "austrian", "babel", "bahasa", "basque",
-"breton", "british", "bulgarian", "catalan", "croatian", "czech", "danish",
-"dutch", "english", "esperanto", "estonian", "finnish", "francais",
-"frenchb", "galician", "german", "germanb", "greek", "hebcal", "hebfont",
+const char * const known_languages[] = { "austrian", "babel", "bahasa",
+"basque", "breton", "british", "bulgarian", "catalan", "croatian", "czech",
+"danish", "dutch", "english", "esperanto", "estonian", "finnish",
+"francais", "french", "frenchb", "frenchle", "frenchpro",
+"galician", "german", "germanb", "greek", "hebcal", "hebfont",
 "hebrew", "hebrew_newcode", "hebrew_oldcode", "hebrew_p", "hyphen",
 "icelandic", "irish", "italian", "latin", "lgrcmr", "lgrcmro", "lgrcmss",
 "lgrcmtt", "lgrenc", "lgrlcmss", "lgrlcmtt", "lheclas", "lhecmr",
@@ -54,7 +62,9 @@ const char * known_languages[] = { "austrian", "babel", "bahasa", "basque",
 "russianb", "samin", "scottish", "serbian", "slovak", "slovene", "spanish",
 "swedish", "turkish", "ukraineb", "usorbian", "welsh", 0};
 
-char const * known_fontsizes[] = { "10pt", "11pt", "12pt", 0 };
+const char * const known_french_languages[] = {"french", "frenchb", "francais",
+                                              "frenchle", "frenchpro", 0};
+char const * const known_fontsizes[] = { "10pt", "11pt", "12pt", 0 };
 
 // some ugly stuff
 ostringstream h_preamble;
@@ -66,27 +76,25 @@ string h_fontscheme              = "default";
 string h_graphics                = "default";
 string h_paperfontsize           = "default";
 string h_spacing                 = "single";
-// Match the entry in ../src/tex-strings.C. Why not "default"?
-string h_papersize               = "Default";
-string h_paperpackage            = "default";
-string h_use_geometry            = "0";
+string h_papersize               = "default";
+string h_use_geometry            = "false";
 string h_use_amsmath             = "0";
-string h_use_natbib              = "0";
-string h_use_numerical_citations = "0";
+string h_cite_engine             = "basic";
+string h_use_bibtopic            = "false";
 string h_paperorientation        = "portrait";
 string h_secnumdepth             = "3";
 string h_tocdepth                = "3";
 string h_paragraph_separation    = "indent";
 string h_defskip                 = "medskip";
 string h_quotes_language         = "english";
-string h_quotes_times            = "2";
 string h_papercolumns            = "1";
 string h_papersides              = string();
 string h_paperpagestyle          = "default";
-string h_tracking_changes        = "0";
+string h_tracking_changes        = "false";
+string h_output_changes          = "false";
 
 
-void handle_opt(vector<string> & opts, char const ** what, string & target)
+void handle_opt(vector<string> & opts, char const * const * what, string & target)
 {
        if (opts.empty())
                return;
@@ -103,13 +111,70 @@ void handle_opt(vector<string> & opts, char const ** what, string & target)
 }
 
 
-void handle_package(string const & name, string const & options)
+/*!
+ * Split a package options string (keyval format) into a vector.
+ * Example input:
+ *   authorformat=smallcaps,
+ *   commabeforerest,
+ *   titleformat=colonsep,
+ *   bibformat={tabular,ibidem,numbered}
+ */
+vector<string> split_options(string const & input)
 {
+       vector<string> options;
+       string option;
+       Parser p(input);
+       while (p.good()) {
+               Token const & t = p.get_token();
+               if (t.asInput() == ",") {
+                       options.push_back(option);
+                       option.erase();
+               } else if (t.asInput() == "=") {
+                       option += '=';
+                       p.skip_spaces(true);
+                       if (p.next_token().asInput() == "{")
+                               option += '{' + p.getArg('{', '}') + '}';
+               } else if (t.cat() != catSpace)
+                       option += t.asInput();
+       }
+
+       if (!option.empty())
+               options.push_back(option);
+
+       return options;
+}
+
+
+/*!
+ * Add package \p name with options \p options to used_packages.
+ * Remove options from \p options that we don't want to output.
+ */
+void add_package(string const & name, vector<string> & options)
+{
+       // every package inherits the global options
+       if (used_packages.find(name) == used_packages.end())
+               used_packages[name] = split_options(h_options);
+
+       vector<string> & v = used_packages[name];
+       v.insert(v.end(), options.begin(), options.end());
+       if (name == "jurabib") {
+               // Don't output the order argument (see the cite command
+               // handling code in text.C).
+               vector<string>::iterator end =
+                       remove(options.begin(), options.end(), "natbiborder");
+               end = remove(options.begin(), end, "jurabiborder");
+               options.erase(end, options.end());
+       }
+}
+
+
+void handle_package(string const & name, string const & opts)
+{
+       vector<string> options = split_options(opts);
+       add_package(name, options);
+
        //cerr << "handle_package: '" << name << "'\n";
-       if (name == "a4wide") {
-               h_papersize = "a4paper";
-               h_paperpackage = "widemarginsa4";
-       } else if (name == "ae")
+       if (name == "ae")
                h_fontscheme = "ae";
        else if (name == "aecompl")
                h_fontscheme = "ae";
@@ -121,29 +186,60 @@ void handle_package(string const & name, string const & options)
                ; // ignore this
        else if (name == "fontenc")
                ; // ignore this
-       else if (name == "inputenc")
-               h_inputencoding = options;
-       else if (name == "makeidx")
+       else if (name == "inputenc") {
+               h_inputencoding = opts;
+               options.clear();
+       } else if (name == "makeidx")
                ; // ignore this
        else if (name == "verbatim")
                ; // ignore this
+       else if (name == "graphicx")
+               ; // ignore this
        else if (is_known(name, known_languages)) {
-               h_language = name;
-               h_quotes_language = name;
-       } else {
-               if (!options.empty())
-                       h_preamble << "\\usepackage[" << options << "]{" << name << "}\n";
-               else
-                       h_preamble << "\\usepackage{" << name << "}\n";
+               if (is_known(name, known_french_languages)) {
+                       h_language = "french";
+                       h_quotes_language = "french";
+               } else {
+                       h_language = name;
+                       h_quotes_language = name;
+               }
+
+       } else if (name == "natbib") {
+               h_cite_engine = "natbib_authoryear";
+               vector<string>::iterator it =
+                       find(options.begin(), options.end(), "authoryear");
+               if (it != options.end())
+                       options.erase(it);
+               else {
+                       it = find(options.begin(), options.end(), "numbers");
+                       if (it != options.end()) {
+                               h_cite_engine = "natbib_numerical";
+                               options.erase(it);
+                       }
+               }
+       } else if (name == "jurabib") {
+               h_cite_engine = "jurabib";
+       } else if (options.empty())
+               h_preamble << "\\usepackage{" << name << "}\n";
+       else {
+               h_preamble << "\\usepackage[" << opts << "]{" << name << "}\n";
+               options.clear();
        }
+
+       // We need to do something with the options...
+       if (!options.empty())
+               cerr << "Ignoring options '" << join(options, ",")
+                    << "' of package " << name << '.' << endl;
 }
 
 
 
 void end_preamble(ostream & os, LyXTextClass const & /*textclass*/)
 {
-       os << "#LyX file created by  tex2lyx 0.1.2 \n"
-          << "\\lyxformat 228\n"
+       os << "#LyX file created by  tex2lyx 0.1.2\n"
+          << "\\lyxformat 245\n"
+          << "\\begin_document\n"
+          << "\\begin_header\n"
           << "\\textclass " << h_textclass << "\n"
           << "\\begin_preamble\n" << h_preamble.str() << "\n\\end_preamble\n";
        if (!h_options.empty())
@@ -155,23 +251,23 @@ void end_preamble(ostream & os, LyXTextClass const & /*textclass*/)
           << "\\paperfontsize " << h_paperfontsize << "\n"
           << "\\spacing " << h_spacing << "\n"
           << "\\papersize " << h_papersize << "\n"
-          << "\\paperpackage " << h_paperpackage << "\n"
           << "\\use_geometry " << h_use_geometry << "\n"
           << "\\use_amsmath " << h_use_amsmath << "\n"
-          << "\\use_natbib " << h_use_natbib << "\n"
-          << "\\use_numerical_citations " << h_use_numerical_citations << "\n"
+          << "\\cite_engine " << h_cite_engine << "\n"
+          << "\\use_bibtopic " << h_use_bibtopic << "\n"
           << "\\paperorientation " << h_paperorientation << "\n"
           << "\\secnumdepth " << h_secnumdepth << "\n"
           << "\\tocdepth " << h_tocdepth << "\n"
           << "\\paragraph_separation " << h_paragraph_separation << "\n"
           << "\\defskip " << h_defskip << "\n"
           << "\\quotes_language " << h_quotes_language << "\n"
-          << "\\quotes_times " << h_quotes_times << "\n"
           << "\\papercolumns " << h_papercolumns << "\n"
           << "\\papersides " << h_papersides << "\n"
           << "\\paperpagestyle " << h_paperpagestyle << "\n"
           << "\\tracking_changes " << h_tracking_changes << "\n"
-          << "\\end_header\n";
+          << "\\output_changes " << h_output_changes << "\n"
+          << "\\end_header\n\n"
+          << "\\begin_body\n";
        // clear preamble for subdocuments
        h_preamble.str("");
 }
@@ -184,7 +280,7 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
        special_columns['D'] = 3;
        bool is_full_document = false;
 
-       // determine wether this is a full document or a fragment for inclusion
+       // determine whether this is a full document or a fragment for inclusion
        while (p.good()) {
                Token const & t = p.get_token();
 
@@ -244,7 +340,8 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
                                star = true;
                        }
                        string const name = p.verbatim_item();
-                       string const opts = p.getOpt();
+                       string const opt1 = p.getOpt();
+                       string const opt2 = p.getFullOpt();
                        string const body = p.verbatim_item();
                        // only non-lyxspecific stuff
                        if (   name != "\\noun"
@@ -253,14 +350,19 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
                            && name != "\\lyxline"
                            && name != "\\lyxaddress"
                            && name != "\\lyxrightaddress"
+                           && name != "\\lyxdot"
                            && name != "\\boldsymbol"
                            && name != "\\lyxarrow") {
                                ostringstream ss;
                                ss << '\\' << t.cs();
                                if (star)
                                        ss << '*';
-                               ss << '{' << name << '}' << opts << '{' << body << "}";
+                               ss << '{' << name << '}' << opt1 << opt2
+                                  << '{' << body << "}";
                                h_preamble << ss.str();
+
+                               // Add the command to the known commands
+                               add_known_command(name, opt1, !opt2.empty());
 /*
                                ostream & out = in_preamble ? h_preamble : os;
                                out << "\\" << t.cs() << "{" << name << "}"
@@ -273,7 +375,13 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
                        vector<string> opts;
                        split(p.getArg('[', ']'), opts, ',');
                        handle_opt(opts, known_languages, h_language);
+                       if (is_known(h_language, known_french_languages))
+                               h_language = "french";
                        handle_opt(opts, known_fontsizes, h_paperfontsize);
+                       // delete "pt" at the end
+                       string::size_type i = h_paperfontsize.find("pt");
+                       if (i != string::npos)
+                               h_paperfontsize.erase(i);
                        h_quotes_language = h_language;
                        h_options = join(opts, ",");
                        h_textclass = p.getArg('{', '}');
@@ -302,8 +410,9 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
                        ss << p.getOpt();
                        ss << '{' << p.verbatim_item() << '}';
                        ss << '{' << p.verbatim_item() << '}';
-                       if (name != "lyxcode" && name != "lyxlist"
-                                       && name != "lyxrightadress" && name != "lyxaddress")
+                       if (name != "lyxcode" && name != "lyxlist" &&
+                           name != "lyxrightadress" &&
+                           name != "lyxaddress" && name != "lyxgreyedout")
                                h_preamble << ss.str();
                }
 
@@ -311,7 +420,8 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
                        string name = p.get_token().cs();
                        while (p.next_token().cat() != catBegin)
                                name += p.get_token().asString();
-                       h_preamble << "\\def\\" << name << '{' << p.verbatim_item() << "}";
+                       h_preamble << "\\def\\" << name << '{'
+                                  << p.verbatim_item() << "}";
                }
 
                else if (t.cs() == "newcolumntype") {
@@ -361,22 +471,34 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
                        h_preamble << "\\begin{" << name << "}";
                }
 
+               else if (t.cs() == "jurabibsetup") {
+                       vector<string> jurabibsetup =
+                               split_options(p.getArg('{', '}'));
+                       // add jurabibsetup to the jurabib package options
+                       add_package("jurabib", jurabibsetup);
+                       if (!jurabibsetup.empty()) {
+                               h_preamble << "\\jurabibsetup{"
+                                          << join(jurabibsetup, ",") << '}';
+                       }
+               }
+
                else if (!t.cs().empty())
                        h_preamble << '\\' << t.cs();
        }
        p.skip_spaces();
 
        // Force textclass if the user wanted it
-       if (!forceclass.empty()) {
+       if (!forceclass.empty())
                h_textclass = forceclass;
-       }
-       string layoutfilename = LibFileSearch("layouts", h_textclass, "layout");
+       if (noweb_mode && !lyx::support::prefixIs(h_textclass, "literate-"))
+               h_textclass.insert(0, "literate-");
+       FileName layoutfilename = libFileSearch("layouts", h_textclass, "layout");
        if (layoutfilename.empty()) {
                cerr << "Error: Could not find layout file for textclass \"" << h_textclass << "\"." << endl;
                exit(1);
        }
        LyXTextClass textclass;
-       textclass.Read(layoutfilename);
+       textclass.read(layoutfilename);
        if (h_papersides.empty()) {
                ostringstream ss;
                ss << textclass.sides();
@@ -387,3 +509,6 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
 }
 
 // }])
+
+
+} // namespace lyx