]> git.lyx.org Git - lyx.git/blobdiff - src/tex2lyx/Preamble.cpp
tex2lyx/Preamble.cpp: fix some comments
[lyx.git] / src / tex2lyx / Preamble.cpp
index e381af444d1ce9859bbca5f37e9766d8484298de..f084ad33a3dd2ae3e7215613a5fb3d89a0b1337f 100644 (file)
@@ -40,8 +40,6 @@ namespace lyx {
 // special columntypes
 extern map<char, int> special_columns;
 
-const char * const modules_placeholder = "\001modules\001";
-
 Preamble preamble;
 
 namespace {
@@ -167,6 +165,12 @@ const char * const known_basic_color_codes[] = {"#0000ff", "#000000", "#00ffff",
 const char * const known_if_3arg_commands[] = {"@ifundefined", "IfFileExists",
 0};
 
+// codes used to remove packages that are loaded automatically by LyX.
+// Syntax: package_beg_sep<name>package_mid_sep<package loading code>package_end_sep
+const char package_beg_sep = '\001';
+const char package_mid_sep = '\002';
+const char package_end_sep = '\003';
+
 
 // returns true if at least one of the options in what has been found
 bool handle_opt(vector<string> & opts, char const * const * what, string & target)
@@ -288,9 +292,24 @@ vector<string> Preamble::getPackageOptions(string const & package) const
 }
 
 
-string Preamble::addModules(string const & lyxpreamble, string const & modules)
+void Preamble::registerAutomaticallyLoadedPackage(std::string const & package)
+{
+       auto_packages.insert(package);
+}
+
+
+void Preamble::addModule(string const & module)
 {
-       return subst(lyxpreamble, modules_placeholder, modules);
+       used_modules.push_back(module);
+}
+
+
+void Preamble::suppressDate(bool suppress)
+{
+       if (suppress)
+               h_suppress_date = "true";
+       else
+               h_suppress_date = "false";
 }
 
 
@@ -342,7 +361,7 @@ string remove_braces(string const & value)
 } // anonymous namespace
 
 
-Preamble::Preamble() : one_language(true), ifundefined_color_set(false)
+Preamble::Preamble() : one_language(true)
 {
        //h_backgroundcolor;
        //h_boxbgcolor;
@@ -580,7 +599,6 @@ void Preamble::handle_package(Parser &p, string const & name,
                // we need to keep it in the preamble to prevent cases like bug #7861.
                if (!opts.empty()) {
                        // check if more than one option was used - used later for inputenc
-                       // in case inputenc is parsed before babel, set the encoding to auto
                        if (options.begin() != options.end() - 1)
                                one_language = false;
                        // babel takes the last language of the option of its \usepackage
@@ -615,8 +633,8 @@ void Preamble::handle_package(Parser &p, string const & name,
                // inputenc option because otherwise h_inputencoding must be
                // set to "auto" (the default encoding of the document language)
                // Therefore check for the "," character.
-               // It is also only set when there is not more then one babel
-               // language option but this is handled in the routine for babel.
+               // It is also only set when there is not more than one babel
+               // language option.
                if (opts.find(",") == string::npos && one_language == true)
                        h_inputencoding = opts;
                if (!options.empty())
@@ -652,15 +670,11 @@ void Preamble::handle_package(Parser &p, string const & name,
        else if (name == "url")
                ; // ignore this
 
-       else if (name == "subscript")
-               ; // ignore this
-
-       else if (name == "color") {
-               // with the following command this package is only loaded when needed for
-               // undefined colors, since we only support the predefined colors
-               // only add it if not yet added
-               if (!ifundefined_color_set)
-                       h_preamble << "\\@ifundefined{definecolor}\n {\\usepackage{color}}{}\n";
+       else if (name == "color" || name == "subscript" || name == "ulem") {
+               if (!in_lyx_preamble)
+                       h_preamble << package_beg_sep << name
+                                  << package_mid_sep << "\\usepackage{"
+                                  << name << '}' << package_end_sep;
        }
 
        else if (name == "graphicx")
@@ -669,13 +683,6 @@ void Preamble::handle_package(Parser &p, string const & name,
        else if (name == "setspace")
                ; // ignore this
 
-#if 0
-       // do not ignore as long as we don't support all commands (e.g. \xout is missing)
-       // and as long as we don't support change tracking
-       else if (name == "ulem")
-               ; // ignore this
-#endif
-
        else if (name == "geometry")
                ; // Ignore this, the geometry settings are made by the \geometry
                  // command. This command is handled below.
@@ -750,7 +757,7 @@ void Preamble::handle_if(Parser & p, bool in_lyx_preamble)
 }
 
 
-void Preamble::end_preamble(ostream & os, TeX2LyXDocClass const & /*tc*/)
+bool Preamble::writeLyXHeader(ostream & os)
 {
        // translate from babel to LyX names
        h_language = babel2lyx(h_language);
@@ -788,13 +795,42 @@ void Preamble::end_preamble(ostream & os, TeX2LyXDocClass const & /*tc*/)
           << "\\begin_document\n"
           << "\\begin_header\n"
           << "\\textclass " << h_textclass << "\n";
-       if (!h_preamble.str().empty())
-               os << "\\begin_preamble\n" << h_preamble.str() << "\n\\end_preamble\n";
+       string const raw = h_preamble.str();
+       if (!raw.empty()) {
+               os << "\\begin_preamble\n";
+               for (string::size_type i = 0; i < raw.size(); ++i) {
+                       if (raw[i] == package_beg_sep) {
+                               // Here follows some package loading code that
+                               // must be skipped if the package is loaded
+                               // automatically.
+                               string::size_type j = raw.find(package_mid_sep, i);
+                               if (j == string::npos)
+                                       return false;
+                               string::size_type k = raw.find(package_end_sep, j);
+                               if (k == string::npos)
+                                       return false;
+                               string const package = raw.substr(i + 1, j - i - 1);
+                               string const replacement = raw.substr(j + 1, k - j - 1);
+                               if (auto_packages.find(package) == auto_packages.end())
+                                       os << replacement;
+                               i = k;
+                       } else
+                               os.put(raw[i]);
+               }
+               os << "\n\\end_preamble\n";
+       }
        if (!h_options.empty())
                os << "\\options " << h_options << "\n";
-       os << "\\use_default_options " << h_use_default_options << "\n"
-          << modules_placeholder
-          << "\\language " << h_language << "\n"
+       os << "\\use_default_options " << h_use_default_options << "\n";
+       if (!used_modules.empty()) {
+               os << "\\begin_modules\n";
+               vector<string>::const_iterator const end = used_modules.end();
+               vector<string>::const_iterator it = used_modules.begin();
+               for (; it != end; it++)
+                       os << *it << '\n';
+               os << "\\end_modules\n";
+       }
+       os << "\\language " << h_language << "\n"
           << "\\language_package " << h_language_package << "\n"
           << "\\inputencoding " << h_inputencoding << "\n"
           << "\\fontencoding " << h_fontencoding << "\n"
@@ -878,11 +914,12 @@ void Preamble::end_preamble(ostream & os, TeX2LyXDocClass const & /*tc*/)
           << "\\begin_body\n";
        // clear preamble for subdocuments
        h_preamble.str("");
+       return true;
 }
 
 
-void Preamble::parse(Parser & p, ostream & os,
-       string const & forceclass, TeX2LyXDocClass & tc)
+void Preamble::parse(Parser & p, string const & forceclass,
+                     TeX2LyXDocClass & tc)
 {
        // initialize fixed types
        special_columns['D'] = 3;
@@ -968,12 +1005,14 @@ void Preamble::parse(Parser & p, ostream & os,
                else if (t.cs() == "color") {
                        string argument = p.getArg('{', '}');
                        // check the case that a standard color is used
-                       if (is_known(argument, known_basic_colors))
-                               h_fontcolor = color2code(argument);
+                       if (is_known(argument, known_basic_colors)) {
+                               h_fontcolor = rgbcolor2code(argument);
+                               preamble.registerAutomaticallyLoadedPackage("color");
+                       } else if (argument == "document_fontcolor")
+                               preamble.registerAutomaticallyLoadedPackage("color");
                        // check the case that LyX's document_fontcolor is defined
                        // but not used for \color
-                       if (argument != "document_fontcolor"
-                               && !is_known(argument, known_basic_colors)) {
+                       else {
                                h_preamble << t.asInput() << '{' << argument << '}';
                                // the color might already be set because \definecolor
                                // is parsed before this
@@ -984,12 +1023,13 @@ void Preamble::parse(Parser & p, ostream & os,
                else if (t.cs() == "pagecolor") {
                        string argument = p.getArg('{', '}');
                        // check the case that a standard color is used
-                       if (is_known(argument, known_basic_colors))
-                               h_backgroundcolor = color2code(argument);
+                       if (is_known(argument, known_basic_colors)) {
+                               h_backgroundcolor = rgbcolor2code(argument);
+                       } else if (argument == "page_backgroundcolor")
+                               preamble.registerAutomaticallyLoadedPackage("color");
                        // check the case that LyX's page_backgroundcolor is defined
                        // but not used for \pagecolor
-                       if (argument != "page_backgroundcolor"
-                               && !is_known(argument, known_basic_colors)) {
+                       else {
                                h_preamble << t.asInput() << '{' << argument << '}';
                                // the color might already be set because \definecolor
                                // is parsed before this
@@ -1306,18 +1346,27 @@ void Preamble::parse(Parser & p, ostream & os,
                        string const arg2 = p.verbatim_item();
                        string const arg3 = p.verbatim_item();
                        // test case \@ifundefined{date}{}{\date{}}
-                       if (arg1 == "date" && arg2.empty() && arg3 == "\\date{}") {
+                       if (t.cs() == "@ifundefined" && arg1 == "date" &&
+                           arg2.empty() && arg3 == "\\date{}") {
                                h_suppress_date = "true";
-                       // test case \@ifundefined{definecolor}{\usepackage{color}}{}
-                       // because we could pollute the preamble with it in roundtrips
-                       } else if (arg1 == "definecolor" && arg2 == "\\usepackage{color}"
-                               && arg3.empty()) {
-                               ifundefined_color_set = true;
+                       // older tex2lyx versions did output
+                       // \@ifundefined{definecolor}{\usepackage{color}}{}
+                       } else if (t.cs() == "@ifundefined" &&
+                                  arg1 == "definecolor" &&
+                                  arg2 == "\\usepackage{color}" &&
+                                  arg3.empty()) {
+                               if (!in_lyx_preamble)
+                                       h_preamble << package_beg_sep
+                                                  << "color"
+                                                  << package_mid_sep
+                                                  << "\\@ifundefined{definecolor}{color}{}"
+                                                  << package_end_sep;
                        // test for case
                        //\@ifundefined{showcaptionsetup}{}{%
                        // \PassOptionsToPackage{caption=false}{subfig}}
                        // that LyX uses for subfloats
-                       } else if (arg1 == "showcaptionsetup" && arg2.empty()
+                       } else if (t.cs() == "@ifundefined" &&
+                                  arg1 == "showcaptionsetup" && arg2.empty()
                                && arg3 == "%\n \\PassOptionsToPackage{caption=false}{subfig}") {
                                ; // do nothing
                        } else if (!in_lyx_preamble) {
@@ -1358,7 +1407,6 @@ void Preamble::parse(Parser & p, ostream & os,
                ss << tc.sides();
                h_papersides = ss.str();
        }
-       end_preamble(os, tc);
 }
 
 
@@ -1371,12 +1419,16 @@ string babel2lyx(string const & language)
 }
 
 
-string color2code(string const & name)
+string rgbcolor2code(string const & name)
 {
        char const * const * where = is_known(name, known_basic_colors);
-       if (where)
+       if (where) {
+               // "red", "green" etc
                return known_basic_color_codes[where - known_basic_colors];
-       return name;
+       }
+       // "255,0,0", "0,255,0" etc
+       RGBColor c(RGBColorFromLaTeX(name));
+       return X11hexname(c);
 }
 
 // }])