// special columntypes
extern map<char, int> special_columns;
-const char * const modules_placeholder = "\001modules\001";
-
Preamble preamble;
namespace {
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)
}
-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";
}
} // anonymous namespace
-Preamble::Preamble() : one_language(true), ifundefined_color_set(false)
+Preamble::Preamble() : one_language(true)
{
//h_backgroundcolor;
//h_boxbgcolor;
// 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
// 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())
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")
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.
}
-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);
<< "\\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"
<< "\\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;
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
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
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) {
ss << tc.sides();
h_papersides = ss.str();
}
- end_preamble(os, tc);
}
}
-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);
}
// }])