X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferParams.cpp;h=ba261ec7989d42a35ea5688af18c78b96a9b5e64;hb=14001c49fe0fb3d95a0f69f63344e7ae59d28180;hp=84c066114db628724a7b35f2d6c8df0623662498;hpb=48f9225e2703d398e71fd12618c8b9174f822bf3;p=lyx.git diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index 84c066114d..ba261ec798 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -4,10 +4,10 @@ * Licence details can be found in the file COPYING. * * \author Alfredo Braunstein - * \author Lars Gullik Bjønnes + * \author Lars Gullik Bjønnes * \author Jean-Marc Lasgouttes * \author John Levon - * \author André Pönitz + * \author André Pönitz * \author Martin Vermeer * * Full author contact details are available in file CREDITS. @@ -23,7 +23,10 @@ #include "buffer_funcs.h" #include "Bullet.h" #include "Color.h" +#include "ColorSet.h" #include "Encoding.h" +#include "HSpace.h" +#include "IndicesList.h" #include "Language.h" #include "LaTeXFeatures.h" #include "ModuleList.h" @@ -68,7 +71,7 @@ static char const * const string_quotes_language[] = { static char const * const string_papersize[] = { - "default", "custom", "letterpaper", "executivepaper", "legalpaper", + "default", "custom", "letterpaper", "legalpaper", "executivepaper", "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", "" }; @@ -84,24 +87,29 @@ static char const * const string_footnotekinds[] = { static char const * const tex_graphics[] = { - "default", "dvips", "dvitops", "emtex", - "ln", "oztex", "textures", "none", "" + "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx", + "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex", + "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex", + "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi", + "xetex", "none", "" }; + namespace lyx { // Local translators namespace { // Paragraph separation -typedef Translator ParSepTranslator; +typedef Translator ParSepTranslator; ParSepTranslator const init_parseptranslator() { - ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT); - translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP); + ParSepTranslator translator + (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation); + translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation); return translator; } @@ -114,17 +122,18 @@ ParSepTranslator const & parseptranslator() // Quotes language -typedef Translator QuotesLangTranslator; +typedef Translator QuotesLangTranslator; QuotesLangTranslator const init_quoteslangtranslator() { - QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ); - translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ); - translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ); - translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ); - translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ); - translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ); + QuotesLangTranslator translator + (string_quotes_language[0], InsetQuotes::EnglishQuotes); + translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes); + translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes); + translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes); + translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes); + translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes); return translator; } @@ -140,7 +149,7 @@ QuotesLangTranslator const & quoteslangtranslator() typedef Translator PaperSizeTranslator; -PaperSizeTranslator const init_papersizetranslator() +static PaperSizeTranslator initPaperSizeTranslator() { PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT); translator.addPair(string_papersize[1], PAPER_CUSTOM); @@ -159,7 +168,7 @@ PaperSizeTranslator const init_papersizetranslator() PaperSizeTranslator const & papersizetranslator() { - static PaperSizeTranslator translator = init_papersizetranslator(); + static PaperSizeTranslator translator = initPaperSizeTranslator(); return translator; } @@ -223,15 +232,15 @@ PackageTranslator const & packagetranslator() // Cite engine -typedef Translator CiteEngineTranslator; +typedef Translator CiteEngineTranslator; CiteEngineTranslator const init_citeenginetranslator() { - CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC); - translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL); - translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR); - translator.addPair("jurabib", biblio::ENGINE_JURABIB); + CiteEngineTranslator translator("basic", ENGINE_BASIC); + translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL); + translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR); + translator.addPair("jurabib", ENGINE_JURABIB); return translator; } @@ -264,7 +273,6 @@ SpaceTranslator const & spacetranslator() return translator; } - } // anon namespace @@ -275,13 +283,14 @@ public: AuthorList authorlist; BranchList branchlist; - vector extraEmbeddedFiles; Bullet temp_bullets[4]; Bullet user_defined_bullets[4]; + IndicesList indiceslist; Spacing spacing; /** This is the amount of space used for paragraph_separation "skip", * and for detached paragraphs in "indented" documents. */ + HSpace indentation; VSpace defskip; PDFOptions pdfoptions; LayoutFileIndex baseClass_; @@ -300,7 +309,7 @@ BufferParams::Impl::Impl() BufferParams::Impl * BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr) { - BOOST_ASSERT(ptr); + LASSERT(ptr, /**/); return new BufferParams::Impl(*ptr); } @@ -317,8 +326,8 @@ BufferParams::BufferParams() { setBaseClass(defaultBaseclass()); makeDocumentClass(); - paragraph_separation = PARSEP_INDENT; - quotes_language = InsetQuotes::EnglishQ; + paragraph_separation = ParagraphIndentSeparation; + quotes_language = InsetQuotes::EnglishQuotes; fontsize = "default"; /* PaperLayout */ @@ -327,43 +336,53 @@ BufferParams::BufferParams() use_geometry = false; use_amsmath = package_auto; use_esint = package_auto; - cite_engine_ = biblio::ENGINE_BASIC; + use_mhchem = package_auto; + cite_engine_ = ENGINE_BASIC; use_bibtopic = false; + use_indices = false; trackChanges = false; outputChanges = false; + use_default_options = true; secnumdepth = 3; tocdepth = 3; language = default_language; + fontenc = "global"; fontsRoman = "default"; fontsSans = "default"; fontsTypewriter = "default"; fontsDefaultFamily = "default"; + useXetex = false; fontsSC = false; fontsOSF = false; fontsSansScale = 100; fontsTypewriterScale = 100; inputenc = "auto"; graphicsDriver = "default"; + defaultOutputFormat = "default"; + bibtex_command = "default"; + index_command = "default"; sides = OneSide; columns = 1; listings_params = string(); pagestyle = "default"; + suppress_date = false; + // white is equal to no background color + backgroundcolor = lyx::rgbFromHexName("#ffffff"); compressed = false; - embedded = false; for (int iter = 0; iter < 4; ++iter) { user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter]; temp_bullet(iter) = ITEMIZE_DEFAULTS[iter]; } + // default index + indiceslist().addDefault(B_("Index")); + html_be_strict = true; + html_use_mathml = true; } -BufferParams::~BufferParams() -{} - - -docstring const BufferParams::B_(string const & l10n) const +docstring BufferParams::B_(string const & l10n) const { - BOOST_ASSERT(language); + LASSERT(language, /**/); return getMessages(language->code()).get(l10n); } @@ -380,54 +399,54 @@ AuthorList const & BufferParams::authors() const } -vector & BufferParams::extraEmbeddedFiles() +BranchList & BufferParams::branchlist() { - return pimpl_->extraEmbeddedFiles; + return pimpl_->branchlist; } -vector const & BufferParams::extraEmbeddedFiles() const +BranchList const & BufferParams::branchlist() const { - return pimpl_->extraEmbeddedFiles; + return pimpl_->branchlist; } -BranchList & BufferParams::branchlist() +IndicesList & BufferParams::indiceslist() { - return pimpl_->branchlist; + return pimpl_->indiceslist; } -BranchList const & BufferParams::branchlist() const +IndicesList const & BufferParams::indiceslist() const { - return pimpl_->branchlist; + return pimpl_->indiceslist; } Bullet & BufferParams::temp_bullet(lyx::size_type const index) { - BOOST_ASSERT(index < 4); + LASSERT(index < 4, /**/); return pimpl_->temp_bullets[index]; } Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const { - BOOST_ASSERT(index < 4); + LASSERT(index < 4, /**/); return pimpl_->temp_bullets[index]; } Bullet & BufferParams::user_defined_bullet(lyx::size_type const index) { - BOOST_ASSERT(index < 4); + LASSERT(index < 4, /**/); return pimpl_->user_defined_bullets[index]; } Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const { - BOOST_ASSERT(index < 4); + LASSERT(index < 4, /**/); return pimpl_->user_defined_bullets[index]; } @@ -456,6 +475,18 @@ PDFOptions const & BufferParams::pdfoptions() const } +HSpace const & BufferParams::getIndentation() const +{ + return pimpl_->indentation; +} + + +void BufferParams::setIndentation(HSpace const & indent) +{ + pimpl_->indentation = indent; +} + + VSpace const & BufferParams::getDefSkip() const { return pimpl_->defskip; @@ -468,8 +499,8 @@ void BufferParams::setDefSkip(VSpace const & vs) } -string const BufferParams::readToken(Lexer & lex, string const & token, - FileName const & filepath, FileName const & temppath) +string BufferParams::readToken(Lexer & lex, string const & token, + FileName const & filepath) { if (token == "\\textclass") { lex.next(); @@ -478,22 +509,14 @@ string const BufferParams::readToken(Lexer & lex, string const & token, // NOTE: in this case, the textclass (.cls file) is assumed to be available. string tcp; LayoutFileList & bcl = LayoutFileList::get(); - if (!temppath.empty()) - tcp = bcl.addLayoutFile(classname, temppath.absFilename(), LayoutFileList::Embedded); if (tcp.empty() && !filepath.empty()) - tcp = bcl.addLayoutFile(classname, filepath.absFilename(), LayoutFileList::Local); + tcp = bcl.addLocalLayout(classname, filepath.absFilename()); if (!tcp.empty()) setBaseClass(tcp); - else if (bcl.haveClass(classname)) { + else setBaseClass(classname); - } else { - // a warning will be given for unknown class - setBaseClass(defaultBaseclass()); - return classname; - } - // FIXME: this warning will be given even if there exists a local .cls - // file. Even worse, the .lyx file can not be compiled or exported - // because the textclass is marked as unavilable. + // We assume that a tex class exists for local or unknown layouts so this warning + // will only be given for system layouts. if (!baseClass()->isTeXClassAvailable()) { docstring const msg = bformat(_("The layout file requested by this document,\n" @@ -505,28 +528,54 @@ string const BufferParams::readToken(Lexer & lex, string const & token, frontend::Alert::warning(_("Document class not available"), msg + _("LyX will not be able to produce output.")); } - } else if (token == "\\begin_preamble") { readPreamble(lex); + } else if (token == "\\begin_local_layout") { + readLocalLayout(lex); } else if (token == "\\begin_modules") { readModules(lex); + } else if (token == "\\begin_removed_modules") { + readRemovedModules(lex); } else if (token == "\\options") { lex.eatLine(); options = lex.getString(); + } else if (token == "\\use_default_options") { + lex >> use_default_options; + } else if (token == "\\master") { + lex.eatLine(); + master = lex.getString(); + } else if (token == "\\suppress_date") { + lex >> suppress_date; } else if (token == "\\language") { readLanguage(lex); } else if (token == "\\inputencoding") { lex >> inputenc; } else if (token == "\\graphics") { readGraphicsDriver(lex); + } else if (token == "\\default_output_format") { + lex >> defaultOutputFormat; + } else if (token == "\\bibtex_command") { + lex.eatLine(); + bibtex_command = lex.getString(); + } else if (token == "\\index_command") { + lex.eatLine(); + index_command = lex.getString(); + } else if (token == "\\fontencoding") { + lex.eatLine(); + fontenc = lex.getString(); } else if (token == "\\font_roman") { - lex >> fontsRoman; + lex.eatLine(); + fontsRoman = lex.getString(); } else if (token == "\\font_sans") { - lex >> fontsSans; + lex.eatLine(); + fontsSans = lex.getString(); } else if (token == "\\font_typewriter") { - lex >> fontsTypewriter; + lex.eatLine(); + fontsTypewriter = lex.getString(); } else if (token == "\\font_default_family") { lex >> fontsDefaultFamily; + } else if (token == "\\use_xetex") { + lex >> useXetex; } else if (token == "\\font_sc") { lex >> fontsSC; } else if (token == "\\font_osf") { @@ -535,10 +584,16 @@ string const BufferParams::readToken(Lexer & lex, string const & token, lex >> fontsSansScale; } else if (token == "\\font_tt_scale") { lex >> fontsTypewriterScale; + } else if (token == "\\font_cjk") { + lex >> fontsCJK; } else if (token == "\\paragraph_separation") { string parsep; lex >> parsep; paragraph_separation = parseptranslator().find(parsep); + } else if (token == "\\paragraph_indentation") { + lex.next(); + string indentation = lex.getString(); + pimpl_->indentation = HSpace(indentation); } else if (token == "\\defskip") { lex.next(); string defskip = lex.getString(); @@ -564,18 +619,24 @@ string const BufferParams::readToken(Lexer & lex, string const & token, int useesint; lex >> useesint; use_esint = packagetranslator().find(useesint); + } else if (token == "\\use_mhchem") { + int usemhchem; + lex >> usemhchem; + use_mhchem = packagetranslator().find(usemhchem); } else if (token == "\\cite_engine") { string engine; lex >> engine; cite_engine_ = citeenginetranslator().find(engine); } else if (token == "\\use_bibtopic") { lex >> use_bibtopic; + } else if (token == "\\use_indices") { + lex >> use_indices; } else if (token == "\\tracking_changes") { lex >> trackChanges; } else if (token == "\\output_changes") { lex >> outputChanges; } else if (token == "\\branch") { - lex.next(); + lex.eatLine(); docstring branch = lex.getDocString(); branchlist().add(branch); while (true) { @@ -589,7 +650,11 @@ string const BufferParams::readToken(Lexer & lex, string const & token, if (branch_ptr) branch_ptr->setSelected(lex.getInteger()); } - // not yet operational + if (tok == "\\filename_suffix") { + lex.next(); + if (branch_ptr) + branch_ptr->setFilenameSuffix(lex.getInteger()); + } if (tok == "\\color") { lex.eatLine(); string color = lex.getString(); @@ -600,7 +665,36 @@ string const BufferParams::readToken(Lexer & lex, string const & token, color = lcolor.getX11Name(Color_background); // FIXME UNICODE lcolor.setColor(to_utf8(branch), color); - + } + } + } else if (token == "\\index") { + lex.eatLine(); + docstring index = lex.getDocString(); + docstring shortcut; + indiceslist().add(index); + while (true) { + lex.next(); + string const tok = lex.getString(); + if (tok == "\\end_index") + break; + Index * index_ptr = indiceslist().find(index); + if (tok == "\\shortcut") { + lex.next(); + shortcut = lex.getDocString(); + if (index_ptr) + index_ptr->setShortcut(shortcut); + } + if (tok == "\\color") { + lex.eatLine(); + string color = lex.getString(); + if (index_ptr) + index_ptr->setColor(color); + // Update also the Color table: + if (color == "none") + color = lcolor.getX11Name(Color_background); + // FIXME UNICODE + if (!shortcut.empty()) + lcolor.setColor(to_utf8(shortcut), color); } } } else if (token == "\\author") { @@ -608,11 +702,14 @@ string const BufferParams::readToken(Lexer & lex, string const & token, istringstream ss(lex.getString()); Author a; ss >> a; - author_map.push_back(pimpl_->authorlist.record(a)); + author_map[a.buffer_id()] = pimpl_->authorlist.record(a); } else if (token == "\\paperorientation") { string orient; lex >> orient; orientation = paperorientationtranslator().find(orient); + } else if (token == "\\backgroundcolor") { + lex.eatLine(); + backgroundcolor = lyx::rgbFromHexName(lex.getString()); } else if (token == "\\paperwidth") { lex >> paperwidth; } else if (token == "\\paperheight") { @@ -673,16 +770,10 @@ string const BufferParams::readToken(Lexer & lex, string const & token, toktmp << endl; return toktmp; } - } else if (token == "\\extra_embedded_files") { - extraEmbeddedFiles().clear(); - string par; - lex >> par; - string tmp; - par = split(par, tmp, ','); - while (!tmp.empty()) { - extraEmbeddedFiles().push_back(tmp); - par = split(par, tmp, ','); - } + } else if (token == "\\html_use_mathml") { + lex >> html_use_mathml; + } else if (token == "\\html_be_strict") { + lex >> html_be_strict; } else { lyxerr << "BufferParams::readToken(): Unknown token: " << token << endl; @@ -714,29 +805,67 @@ void BufferParams::writeFile(ostream & os) const if (!options.empty()) { os << "\\options " << options << '\n'; } + + // use the class options defined in the layout? + os << "\\use_default_options " + << convert(use_default_options) << "\n"; + + // the master document + if (!master.empty()) { + os << "\\master " << master << '\n'; + } - //the modules + // removed modules + if (!removedModules_.empty()) { + os << "\\begin_removed_modules" << '\n'; + list::const_iterator it = removedModules_.begin(); + list::const_iterator en = removedModules_.end(); + for (; it != en; it++) + os << *it << '\n'; + os << "\\end_removed_modules" << '\n'; + } + + // the modules if (!layoutModules_.empty()) { os << "\\begin_modules" << '\n'; LayoutModuleList::const_iterator it = layoutModules_.begin(); - for (; it != layoutModules_.end(); it++) + LayoutModuleList::const_iterator en = layoutModules_.end(); + for (; it != en; it++) os << *it << '\n'; os << "\\end_modules" << '\n'; } + + // local layout information + if (!local_layout.empty()) { + // remove '\n' from the end + string const tmplocal = rtrim(local_layout, "\n"); + os << "\\begin_local_layout\n" + << tmplocal + << "\n\\end_local_layout\n"; + } // then the text parameters if (language != ignore_language) os << "\\language " << language->lang() << '\n'; os << "\\inputencoding " << inputenc + << "\n\\fontencoding " << fontenc << "\n\\font_roman " << fontsRoman << "\n\\font_sans " << fontsSans << "\n\\font_typewriter " << fontsTypewriter << "\n\\font_default_family " << fontsDefaultFamily + << "\n\\use_xetex " << convert(useXetex) << "\n\\font_sc " << convert(fontsSC) << "\n\\font_osf " << convert(fontsOSF) << "\n\\font_sf_scale " << fontsSansScale << "\n\\font_tt_scale " << fontsTypewriterScale - << "\n\\graphics " << graphicsDriver << '\n'; + << '\n'; + if (!fontsCJK.empty()) { + os << "\\font_cjk " << fontsCJK << '\n'; + } + os << "\n\\graphics " << graphicsDriver << '\n'; + os << "\\default_output_format " << defaultOutputFormat << '\n'; + os << "\\bibtex_command " << bibtex_command << '\n'; + os << "\\index_command " << index_command << '\n'; if (!float_placement.empty()) { os << "\\float_placement " << float_placement << '\n'; @@ -750,21 +879,37 @@ void BufferParams::writeFile(ostream & os) const << "\n\\use_geometry " << convert(use_geometry) << "\n\\use_amsmath " << use_amsmath << "\n\\use_esint " << use_esint + << "\n\\use_mhchem " << use_mhchem << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_) << "\n\\use_bibtopic " << convert(use_bibtopic) + << "\n\\use_indices " << convert(use_indices) << "\n\\paperorientation " << string_orientation[orientation] + << "\n\\suppress_date " << convert(suppress_date) << '\n'; + if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) + os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n'; BranchList::const_iterator it = branchlist().begin(); BranchList::const_iterator end = branchlist().end(); for (; it != end; ++it) { - os << "\\branch " << to_utf8(it->getBranch()) - << "\n\\selected " << it->getSelected() - << "\n\\color " << lyx::X11hexname(it->getColor()) + os << "\\branch " << to_utf8(it->branch()) + << "\n\\selected " << it->isSelected() + << "\n\\filename_suffix " << it->hasFilenameSuffix() + << "\n\\color " << lyx::X11hexname(it->color()) << "\n\\end_branch" << "\n"; } + IndicesList::const_iterator iit = indiceslist().begin(); + IndicesList::const_iterator iend = indiceslist().end(); + for (; iit != iend; ++iit) { + os << "\\index " << to_utf8(iit->index()) + << "\n\\shortcut " << to_utf8(iit->shortcut()) + << "\n\\color " << lyx::X11hexname(iit->color()) + << "\n\\end_index" + << "\n"; + } + if (!paperwidth.empty()) os << "\\paperwidth " << VSpace(paperwidth).asLyXCommand() << '\n'; @@ -798,9 +943,12 @@ void BufferParams::writeFile(ostream & os) const os << "\\secnumdepth " << secnumdepth << "\n\\tocdepth " << tocdepth << "\n\\paragraph_separation " - << string_paragraph_separation[paragraph_separation] - << "\n\\defskip " << getDefSkip().asLyXCommand() - << "\n\\quotes_language " + << string_paragraph_separation[paragraph_separation]; + if (!paragraph_separation) + os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand(); + else + os << "\n\\defskip " << getDefSkip().asLyXCommand(); + os << "\n\\quotes_language " << string_quotes_language[quotes_language] << "\n\\papercolumns " << columns << "\n\\papersides " << sides @@ -825,30 +973,12 @@ void BufferParams::writeFile(ostream & os) const } } - os << "\\tracking_changes " << convert(trackChanges) << "\n"; - os << "\\output_changes " << convert(outputChanges) << "\n"; - - AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin(); - AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end(); - for (; a_it != a_end; ++a_it) { - if (a_it->second.used()) - os << "\\author " << a_it->second << "\n"; - else - os << "\\author " << Author() << "\n"; - } + os << "\\tracking_changes " << convert(trackChanges) << "\n" + << "\\output_changes " << convert(outputChanges) << "\n" + << "\\html_use_mathml " << convert(html_use_mathml) << "\n" + << "\\html_be_strict " << convert(html_be_strict) << "\n"; - vector::const_iterator e_it = extraEmbeddedFiles().begin(); - vector::const_iterator e_end = extraEmbeddedFiles().end(); - os << "\\extra_embedded_files \""; - bool first = true; - for (; e_it != e_end; ++e_it) { - if (!first) - os << ","; - else - first = false; - os << *e_it; - } - os << "\"\n"; + os << pimpl_->authorlist; } @@ -858,7 +988,7 @@ void BufferParams::validate(LaTeXFeatures & features) const if (outputChanges) { bool dvipost = LaTeXFeatures::isAvailable("dvipost"); - bool xcolorsoul = LaTeXFeatures::isAvailable("soul") && + bool xcolorulem = LaTeXFeatures::isAvailable("ulem") && LaTeXFeatures::isAvailable("xcolor"); switch (features.runparams().flavor) { @@ -866,18 +996,19 @@ void BufferParams::validate(LaTeXFeatures & features) const if (dvipost) { features.require("ct-dvipost"); features.require("dvipost"); - } else if (xcolorsoul) { - features.require("ct-xcolor-soul"); - features.require("soul"); + } else if (xcolorulem) { + features.require("ct-xcolor-ulem"); + features.require("ulem"); features.require("xcolor"); } else { features.require("ct-none"); } break; case OutputParams::PDFLATEX: - if (xcolorsoul) { - features.require("ct-xcolor-soul"); - features.require("soul"); + case OutputParams::XETEX: + if (xcolorulem) { + features.require("ct-xcolor-ulem"); + features.require("ulem"); features.require("xcolor"); // improves color handling in PDF output features.require("pdfcolmk"); @@ -900,6 +1031,8 @@ void BufferParams::validate(LaTeXFeatures & features) const features.require("amsmath"); if (use_esint == package_on) features.require("esint"); + if (use_mhchem == package_on) + features.require("mhchem"); // Document-level line spacing if (spacing().getSpace() != Spacing::Single && !spacing().isDefault()) @@ -927,8 +1060,22 @@ void BufferParams::validate(LaTeXFeatures & features) const } } - if (pdfoptions().use_hyperref) + if (pdfoptions().use_hyperref) { features.require("hyperref"); + // due to interferences with babel and hyperref, the color package has to + // be loaded after hyperref when hyperref is used with the colorlinks + // option, see http://www.lyx.org/trac/ticket/5291 + if (pdfoptions().colorlinks) + features.require("color"); + } + + if (useXetex) + features.require("xetex"); + + if (language->lang() == "vietnamese") + features.require("vietnamese"); + else if (language->lang() == "japanese") + features.require("japanese"); } @@ -1021,16 +1168,32 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, language_options << ','; language_options << language->babel(); } - // when Vietnamese is used, babel must directly be loaded with the - // language options, not in the class options, see + // if Vietnamese is used, babel must directly be loaded + // with language options, not in the class options, see // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html size_t viet = language_options.str().find("vietnam"); // viet = string::npos when not found + // the same is for all other languages that are not directly supported by + // babel, but where LaTeX-packages add babel support. + // this is currently the case for Latvian, Lithuanian, and Mongolian + size_t latvian = language_options.str().find("latvian"); + size_t lithu = language_options.str().find("lithuanian"); + size_t mongo = language_options.str().find("mongolian"); + // if Japanese is used, babel must directly be loaded + // with language options, not in the class options, see + // http://www.lyx.org/trac/ticket/4597#c4 + size_t japan = language_options.str().find("japanese"); if (lyxrc.language_global_options && !language_options.str().empty() - && viet == string::npos) + && viet == string::npos && japan == string::npos + && latvian == string::npos && lithu == string::npos + && mongo == string::npos) clsoptions << language_options.str() << ','; } + // the predefined options from the layout + if (use_default_options && !tclass.options().empty()) + clsoptions << tclass.options() << ','; + // the user-defined options if (!options.empty()) { clsoptions << options << ','; @@ -1047,11 +1210,16 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, texrow.newline(); // end of \documentclass defs + if (useXetex) { + os << "\\usepackage{fontspec}\n"; + texrow.newline(); + } + // font selection must be done before loading fontenc.sty string const fonts = loadFonts(fontsRoman, fontsSans, fontsTypewriter, fontsSC, fontsOSF, - fontsSansScale, fontsTypewriterScale); + fontsSansScale, fontsTypewriterScale, useXetex); if (!fonts.empty()) { os << from_ascii(fonts); texrow.newline(); @@ -1061,15 +1229,18 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, << from_ascii(fontsDefaultFamily) << "}\n"; // set font encoding - // this one is not per buffer - // for arabic_arabi and farsi we also need to load the LAE and LFE encoding - if (lyxrc.fontenc != "default") { - if (language->lang() == "arabic_arabi" || language->lang() == "farsi") { - os << "\\usepackage[" << from_ascii(lyxrc.fontenc) + // for arabic_arabi and farsi we also need to load the LAE and + // LFE encoding + // XeTeX works without fontenc + if (font_encoding() != "default" && language->lang() != "japanese" + && !useXetex) { + if (language->lang() == "arabic_arabi" + || language->lang() == "farsi") { + os << "\\usepackage[" << from_ascii(font_encoding()) << ",LFE,LAE]{fontenc}\n"; texrow.newline(); } else { - os << "\\usepackage[" << from_ascii(lyxrc.fontenc) + os << "\\usepackage[" << from_ascii(font_encoding()) << "]{fontenc}\n"; texrow.newline(); } @@ -1078,13 +1249,20 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, // handle inputenc etc. writeEncodingPreamble(os, features, texrow); - if (!listings_params.empty()) { + if (!listings_params.empty() || features.isRequired("listings")) { os << "\\usepackage{listings}\n"; texrow.newline(); + } + if (!listings_params.empty()) { os << "\\lstset{"; - // do not test validity because listings_params is supposed to be valid - string par = InsetListingsParams(listings_params).separatedParams(true); - os << from_ascii(par); + // do not test validity because listings_params is + // supposed to be valid + string par = + InsetListingsParams(listings_params).separatedParams(true); + // we can't support all packages, but we should load the color package + if (par.find("\\color", 0) != string::npos) + features.require("color"); + os << from_utf8(par); // count the number of newlines for (size_t i = 0; i < par.size(); ++i) if (par[i] == '\n') @@ -1092,72 +1270,73 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, os << "}\n"; texrow.newline(); } - if (use_geometry || nonstandard_papersize) { - os << "\\usepackage{geometry}\n"; - texrow.newline(); - os << "\\geometry{verbose"; + if (!tclass.provides("geometry") + && (use_geometry || nonstandard_papersize)) { + odocstringstream ods; + if (!getGraphicsDriver("geometry").empty()) + ods << getGraphicsDriver("geometry"); if (orientation == ORIENTATION_LANDSCAPE) - os << ",landscape"; + ods << ",landscape"; switch (papersize) { case PAPER_CUSTOM: if (!paperwidth.empty()) - os << ",paperwidth=" + ods << ",paperwidth=" << from_ascii(paperwidth); if (!paperheight.empty()) - os << ",paperheight=" + ods << ",paperheight=" << from_ascii(paperheight); break; case PAPER_USLETTER: - os << ",letterpaper"; + ods << ",letterpaper"; break; case PAPER_USLEGAL: - os << ",legalpaper"; + ods << ",legalpaper"; break; case PAPER_USEXECUTIVE: - os << ",executivepaper"; + ods << ",executivepaper"; break; case PAPER_A3: - os << ",a3paper"; + ods << ",a3paper"; break; case PAPER_A4: - os << ",a4paper"; + ods << ",a4paper"; break; case PAPER_A5: - os << ",a5paper"; + ods << ",a5paper"; break; case PAPER_B3: - os << ",b3paper"; + ods << ",b3paper"; break; case PAPER_B4: - os << ",b4paper"; + ods << ",b4paper"; break; case PAPER_B5: - os << ",b5paper"; + ods << ",b5paper"; break; default: // default papersize ie PAPER_DEFAULT switch (lyxrc.default_papersize) { case PAPER_DEFAULT: // keep compiler happy case PAPER_USLETTER: - os << ",letterpaper"; + ods << ",letterpaper"; break; case PAPER_USLEGAL: - os << ",legalpaper"; + ods << ",legalpaper"; break; case PAPER_USEXECUTIVE: - os << ",executivepaper"; + ods << ",executivepaper"; break; case PAPER_A3: - os << ",a3paper"; + ods << ",a3paper"; break; case PAPER_A4: - os << ",a4paper"; + ods << ",a4paper"; break; case PAPER_A5: - os << ",a5paper"; + ods << ",a5paper"; break; case PAPER_B5: - os << ",b5paper"; + ods << ",b5paper"; break; case PAPER_B3: case PAPER_B4: @@ -1165,6 +1344,13 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, break; } } + docstring const g_options = trim(ods.str(), ","); + os << "\\usepackage"; + if (!g_options.empty()) + os << '[' << g_options << ']'; + os << "{geometry}\n"; + texrow.newline(); + os << "\\geometry{verbose"; if (!topmargin.empty()) os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString()); if (!bottommargin.empty()) @@ -1183,6 +1369,8 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString()); os << "}\n"; texrow.newline(); + } else if (orientation == ORIENTATION_LANDSCAPE) { + features.require("papersize"); } if (tokenPos(tclass.opt_pagestyle(), @@ -1195,6 +1383,15 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, texrow.newline(); } + // only output when the background color is not white + if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) { + // only require color here, the background color will be defined + // in LaTeXFeatures.cpp to avoid interferences with the LaTeX + // package pdfpages + features.require("color"); + features.require("pagecolor"); + } + // Only if class has a ToC hierarchy if (tclass.hasTocLevels()) { if (secnumdepth != tclass.secnumdepth()) { @@ -1212,6 +1409,7 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, } if (paragraph_separation) { + // when skip separation switch (getDefSkip().kind()) { case VSpace::SMALLSKIP: os << "\\setlength{\\parskip}{\\smallskipamount}\n"; @@ -1232,63 +1430,64 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, break; } texrow.newline(); - os << "\\setlength{\\parindent}{0pt}\n"; texrow.newline(); - } - - // If we use jurabib, we have to call babel here. - if (use_babel && features.isRequired("jurabib")) { - os << from_ascii(babelCall(language_options.str())) - << '\n' - << from_ascii(features.getBabelOptions()); - texrow.newline(); + } else { + // when separation by indentation + // only output something when a width is given + if (getIndentation().asLyXCommand() != "default") { + os << "\\setlength{\\parindent}{" + << from_utf8(getIndentation().asLatexCommand()) + << "}\n"; + texrow.newline(); + } } // Now insert the LyX specific LaTeX commands... + docstring lyxpreamble; + + // due to interferences with babel and hyperref, the color package has to + // be loaded (when it is not already loaded) before babel when hyperref + // is used with the colorlinks option, see + // http://www.lyx.org/trac/ticket/5291 + // we decided therefore to load color always before babel, see + // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html + lyxpreamble += from_ascii(features.getColorOptions()); + + // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them. + if (use_babel + && (features.isRequired("jurabib") + || features.isRequired("hyperref") + || features.isRequired("vietnamese") + || features.isRequired("japanese") ) ) { + // FIXME UNICODE + lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n'; + lyxpreamble += from_utf8(features.getBabelOptions()) + '\n'; + } // The optional packages; - docstring lyxpreamble(from_ascii(features.getPackages())); + lyxpreamble += from_ascii(features.getPackages()); + + // Additional Indices + if (features.isRequired("splitidx")) { + IndicesList::const_iterator iit = indiceslist().begin(); + IndicesList::const_iterator iend = indiceslist().end(); + for (; iit != iend; ++iit) { + lyxpreamble += "\\newindex["; + lyxpreamble += iit->index(); + lyxpreamble += "]{"; + lyxpreamble += iit->shortcut(); + lyxpreamble += "}\n"; + } + } // Line spacing lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace"))); - // We try to load babel late, in case it interferes - // with other packages. But some packages also need babel to be loaded - // before, e.g. jurabib has to be called after babel. - // So load babel after the optional packages but before the user-defined - // preamble. This allows the users to redefine babel commands, e.g. to - // translate the word "Index" to the German "Stichwortverzeichnis". - // For more infos why this place was chosen, see - // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg128425.html - // If you encounter problems, you can shift babel to its old place behind - // the user-defined preamble. But in this case you must change the Vietnamese - // support from currently "\usepackage[vietnamese]{babel}" to: - // \usepackage{vietnamese} - // \usepackage{babel} - // because vietnamese must be loaded before hyperref - if (use_babel && !features.isRequired("jurabib")) { - // FIXME UNICODE - lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n'; - lyxpreamble += from_utf8(features.getBabelOptions()); - } - - // When the language "japanese-plain" is used, the package "japanese" must - // be loaded behind babel (it provides babel support for Japanese) but before - // hyperref, see - // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html - if (language->lang() == "japanese-plain" && - !documentClass().provides("japanese")) { - //load babel in case it was not loaded due to an empty language list - if (language_options.str().empty()) - lyxpreamble += "\\usepackage{babel}\n"; - lyxpreamble += "\\usepackage{japanese}\n"; - } - // PDF support. // * Hyperref manual: "Make sure it comes last of your loaded // packages, to give it a fighting chance of not being over-written, - // since its job is to redefine many LATEX commands." + // since its job is to redefine many LaTeX commands." // * Email from Heiko Oberdiek: "It is usually better to load babel // before hyperref. Then hyperref has a chance to detect babel. // * Has to be loaded before the "LyX specific LaTeX commands" to @@ -1299,33 +1498,52 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref")); lyxpreamble += oss.str(); } - - // this might be useful... - lyxpreamble += "\n\\makeatletter\n"; + + // Will be surrounded by \makeatletter and \makeatother when not empty + docstring atlyxpreamble; // Some macros LyX will need - docstring tmppreamble(from_ascii(features.getMacros())); + docstring tmppreamble(features.getMacros()); - if (!tmppreamble.empty()) { - lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " + if (!tmppreamble.empty()) + atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " "LyX specific LaTeX commands.\n" + tmppreamble + '\n'; - } // the text class specific preamble tmppreamble = features.getTClassPreamble(); - if (!tmppreamble.empty()) { - lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " + if (!tmppreamble.empty()) + atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " "Textclass specific LaTeX commands.\n" + tmppreamble + '\n'; - } + + // suppress date if selected + // use \@ifundefined because we cannot be sure that every document class + // has a \date command + if (suppress_date) + atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n"; /* the user-defined preamble */ - if (!preamble.empty()) { + if (!containsOnly(preamble, " \n\t")) // FIXME UNICODE - lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " + atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " "User specified LaTeX commands.\n" + from_utf8(preamble) + '\n'; + + // subfig loads internally the LaTeX package "caption". As + // caption is a very popular package, users will load it in + // the preamble. Therefore we must load subfig behind the + // user-defined preamble and check if the caption package was + // loaded or not. For the case that caption is loaded before + // subfig, there is the subfig option "caption=false". This + // option also works when a koma-script class is used and + // koma's own caption commands are used instead of caption. We + // use \PassOptionsToPackage here because the user could have + // already loaded subfig in the preamble. + if (features.isRequired("subfig")) { + atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n" + " \\PassOptionsToPackage{caption=false}{subfig}}\n" + "\\usepackage{subfig}\n"; } // Itemize bullet settings need to be last in case the user @@ -1361,9 +1579,26 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, } if (!bullets_def.empty()) - lyxpreamble += bullets_def + "}\n\n"; + atlyxpreamble += bullets_def + "}\n\n"; + + if (!atlyxpreamble.empty()) + lyxpreamble += "\n\\makeatletter\n" + + atlyxpreamble + "\\makeatother\n\n"; + + // We try to load babel late, in case it interferes with other packages. + // Jurabib and Hyperref have to be called after babel, though. + if (use_babel && !features.isRequired("jurabib") + && !features.isRequired("hyperref") + && !features.isRequired("vietnamese") + && !features.isRequired("japanese")) { + // FIXME UNICODE + lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n'; + lyxpreamble += from_utf8(features.getBabelOptions()) + '\n'; + } - lyxpreamble += "\\makeatother\n\n"; + docstring const i18npreamble = features.getTClassI18nPreamble(use_babel); + if (!i18npreamble.empty()) + lyxpreamble += i18npreamble + '\n'; int const nlines = int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n')); @@ -1372,6 +1607,16 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, } os << lyxpreamble; + + // these packages (xunicode, for that matter) need to be loaded at least + // after amsmath, amssymb, esint and the other packages that provide + // special glyphs + if (useXetex) { + os << "\\usepackage{xunicode}\n"; + texrow.newline(); + os << "\\usepackage{xltxtra}\n"; + texrow.newline(); + } return use_babel; } @@ -1383,7 +1628,7 @@ void BufferParams::useClassDefaults() sides = tclass.sides(); columns = tclass.columns(); pagestyle = tclass.pagestyle(); - options = tclass.options(); + use_default_options = true; // Only if class has a ToC hierarchy if (tclass.hasTocLevels()) { secnumdepth = tclass.secnumdepth(); @@ -1399,7 +1644,7 @@ bool BufferParams::hasClassDefaults() const return sides == tclass.sides() && columns == tclass.columns() && pagestyle == tclass.pagestyle() - && options == tclass.options() + && use_default_options && secnumdepth == tclass.secnumdepth() && tocdepth == tclass.tocdepth(); } @@ -1411,7 +1656,7 @@ DocumentClass const & BufferParams::documentClass() const } -DocumentClass * BufferParams::documentClassPtr() const { +DocumentClass const * BufferParams::documentClassPtr() const { return doc_class_; } @@ -1425,25 +1670,30 @@ void BufferParams::setDocumentClass(DocumentClass const * const tc) { bool BufferParams::setBaseClass(string const & classname) { LYXERR(Debug::TCLASS, "setBaseClass: " << classname); - LayoutFileList const & bcl = LayoutFileList::get(); + LayoutFileList & bcl = LayoutFileList::get(); if (!bcl.haveClass(classname)) { docstring s = - bformat(_("The document class %1$s could not be found."), + bformat(_("The document class %1$s could not be found. " + "A default textclass with default layouts will be used. " + "LyX might not be able to produce output unless a correct " + "textclass is selected from the document settings dialog."), from_utf8(classname)); - frontend::Alert::error(_("Class not found"), s); - return false; + frontend::Alert::error(_("Document class not found"), s); + bcl.addEmptyClass(classname); } - if (bcl[classname].load()) { - pimpl_->baseClass_ = classname; - return true; + bool const success = bcl[classname].load(); + if (!success) { + docstring s = + bformat(_("The document class %1$s could not be loaded."), + from_utf8(classname)); + frontend::Alert::error(_("Could not load class"), s); + return false; } - - docstring s = - bformat(_("The document class %1$s could not be loaded."), - from_utf8(classname)); - frontend::Alert::error(_("Could not load class"), s); - return false; + + pimpl_->baseClass_ = classname; + layoutModules_.adaptToBaseClass(baseClass(), removedModules_); + return true; } @@ -1467,73 +1717,34 @@ void BufferParams::makeDocumentClass() if (!baseClass()) return; - doc_class_ = &(DocumentClassBundle::get().newClass(*baseClass())); - - //FIXME It might be worth loading the children's modules here, - //just as we load their bibliographies and such, instead of just - //doing a check in InsetInclude. - LayoutModuleList::const_iterator it = layoutModules_.begin(); - for (; it != layoutModules_.end(); it++) { - string const modName = *it; - LyXModule * lm = moduleList[modName]; - if (!lm) { - docstring const msg = - bformat(_("The module %1$s has been requested by\n" - "this document but has not been found in the list of\n" - "available modules. If you recently installed it, you\n" - "probably need to reconfigure LyX.\n"), from_utf8(modName)); - frontend::Alert::warning(_("Module not available"), - msg + _("Some layouts may not be available.")); - lyxerr << "BufferParams::makeDocumentClass(): Module " << - modName << " requested but not found in module list." << - endl; - continue; - } - if (!lm->isAvailable()) { - docstring const msg = - bformat(_("The module %1$s requires a package that is\n" - "not available in your LaTeX installation. LaTeX output\n" - "may not be possible.\n"), from_utf8(modName)); - frontend::Alert::warning(_("Package not available"), msg); - } - FileName layout_file = libFileSearch("layouts", lm->getFilename()); - if (!doc_class_->read(layout_file, TextClass::MODULE)) { - docstring const msg = - bformat(_("Error reading module %1$s\n"), from_utf8(modName)); + doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_)); + + if (!local_layout.empty()) { + if (!doc_class_->read(local_layout, TextClass::MODULE)) { + docstring const msg = _("Error reading internal layout information"); frontend::Alert::warning(_("Read Error"), msg); } } } - -vector const & BufferParams::getModules() const +bool BufferParams::moduleCanBeAdded(string const & modName) const { - return layoutModules_; + return layoutModules_.moduleCanBeAdded(modName, baseClass()); } - -bool BufferParams::addLayoutModule(string const & modName) +bool BufferParams::addLayoutModule(string const & modName) { LayoutModuleList::const_iterator it = layoutModules_.begin(); LayoutModuleList::const_iterator end = layoutModules_.end(); - for (; it != end; it++) { + for (; it != end; it++) if (*it == modName) - break; - } - if (it != layoutModules_.end()) - return false; + return false; layoutModules_.push_back(modName); return true; } -void BufferParams::clearLayoutModules() -{ - layoutModules_.clear(); -} - - Font const BufferParams::getFont() const { FontInfo f = documentClass().defaultfont(); @@ -1557,6 +1768,16 @@ void BufferParams::readPreamble(Lexer & lex) } +void BufferParams::readLocalLayout(Lexer & lex) +{ + if (lex.getString() != "\\begin_local_layout") + lyxerr << "Error (BufferParams::readLocalLayout):" + "consistency check failed." << endl; + + local_layout = lex.getLongString("\\end_local_layout"); +} + + void BufferParams::readLanguage(Lexer & lex) { if (!lex.next()) return; @@ -1589,7 +1810,8 @@ void BufferParams::readGraphicsDriver(Lexer & lex) if (test == tmptok) { graphicsDriver = tmptok; break; - } else if (test == "") { + } + if (test.empty()) { lex.printError( "Warning: graphics driver `$$Token' not recognized!\n" " Setting graphics driver to `default'.\n"); @@ -1650,7 +1872,38 @@ void BufferParams::readModules(Lexer & lex) } -string const BufferParams::paperSizeName(Papersize_Purpose const & purpose) const +void BufferParams::readRemovedModules(Lexer & lex) +{ + if (!lex.eatLine()) { + lyxerr << "Error (BufferParams::readRemovedModules):" + "Unexpected end of input." << endl; + return; + } + while (true) { + string mod = lex.getString(); + if (mod == "\\end_removed_modules") + break; + removedModules_.push_back(mod); + lex.eatLine(); + } + // now we want to remove any removed modules that were previously + // added. normally, that will be because default modules were added in + // setBaseClass(), which gets called when \textclass is read at the + // start of the read. + list::const_iterator rit = removedModules_.begin(); + list::const_iterator const ren = removedModules_.end(); + for (; rit != ren; rit++) { + LayoutModuleList::iterator const mit = layoutModules_.begin(); + LayoutModuleList::iterator const men = layoutModules_.end(); + LayoutModuleList::iterator found = find(mit, men, *rit); + if (found == men) + continue; + layoutModules_.erase(found); + } +} + + +string BufferParams::paperSizeName(PapersizePurpose purpose) const { char real_papersize = papersize; if (real_papersize == PAPER_DEFAULT) @@ -1742,7 +1995,13 @@ string const BufferParams::dvips_options() const } -string const BufferParams::babelCall(string const & lang_opts) const +string const BufferParams::font_encoding() const +{ + return (fontenc == "global") ? lyxrc.fontenc : fontenc; +} + + +string BufferParams::babelCall(string const & lang_opts) const { string lang_pack = lyxrc.language_package; if (lang_pack != "\\usepackage{babel}") @@ -1752,20 +2011,52 @@ string const BufferParams::babelCall(string const & lang_opts) const // other languages are used (lang_opts is then empty) if (lang_opts.empty()) return string(); - // when Vietnamese is used, babel must directly be loaded with the + // If Vietnamese is used, babel must directly be loaded with the // language options, see // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html size_t viet = lang_opts.find("vietnam"); // viet = string::npos when not found - if (!lyxrc.language_global_options || viet != string::npos) + // the same is for all other languages that are not directly supported by + // babel, but where LaTeX-packages add babel support. + // this is currently the case for Latvian, Lithuanian, and Mongolian + size_t latvian = lang_opts.find("latvian"); + size_t lithu = lang_opts.find("lithuanian"); + size_t mongo = lang_opts.find("mongolian"); + // If Japanese is used, babel must directly be loaded with the + // language options, see + // http://www.lyx.org/trac/ticket/4597#c4 + size_t japan = lang_opts.find("japanese"); + if (!lyxrc.language_global_options || viet != string::npos + || japan != string::npos || latvian != string::npos + || lithu != string::npos || mongo != string::npos) return "\\usepackage[" + lang_opts + "]{babel}"; return lang_pack; } +docstring BufferParams::getGraphicsDriver(string const & package) const +{ + docstring result; + + if (package == "geometry") { + if (graphicsDriver == "dvips" + || graphicsDriver == "dvipdfm" + || graphicsDriver == "pdftex" + || graphicsDriver == "vtex") + result = from_ascii(graphicsDriver); + else if (graphicsDriver == "dvipdfmx") + result = from_ascii("dvipdfm"); + } + + return result; +} + + void BufferParams::writeEncodingPreamble(odocstream & os, LaTeXFeatures & features, TexRow & texrow) const { + if (useXetex) + return; if (inputenc == "auto") { string const doc_encoding = language->encoding()->latexName(); @@ -1777,14 +2068,14 @@ void BufferParams::writeEncodingPreamble(odocstream & os, set encodings = features.getEncodingSet(doc_encoding); - // When the encodings EUC-JP-plain, JIS-plain, or SJIS-plainare used, the - // package inputenc must be omitted. Therefore set the encoding to empty. + // If the "japanese" package (i.e. pLaTeX) is used, + // inputenc must be omitted. // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html - if (doc_encoding == "EUC-JP-plain" || doc_encoding == "JIS-plain" || - doc_encoding == "SJIS-plain") - encodings.clear(); + if (package == Encoding::japanese) + features.require("japanese"); - if (!encodings.empty() || package == Encoding::inputenc) { + if ((!encodings.empty() || package == Encoding::inputenc) + && !features.isRequired("japanese")) { os << "\\usepackage["; set::const_iterator it = encodings.begin(); set::const_iterator const end = encodings.end(); @@ -1803,38 +2094,63 @@ void BufferParams::writeEncodingPreamble(odocstream & os, texrow.newline(); } if (package == Encoding::CJK || features.mustProvide("CJK")) { - os << "\\usepackage{CJK}\n"; + if (language->encoding()->name() == "utf8-cjk" + && LaTeXFeatures::isAvailable("CJKutf8")) + os << "\\usepackage{CJKutf8}\n"; + else + os << "\\usepackage{CJK}\n"; texrow.newline(); } } else if (inputenc != "default") { switch (encoding().package()) { case Encoding::none: + case Encoding::japanese: break; case Encoding::inputenc: + // do not load inputenc if japanese is used + if (features.isRequired("japanese")) + break; os << "\\usepackage[" << from_ascii(inputenc) << "]{inputenc}\n"; texrow.newline(); break; case Encoding::CJK: - os << "\\usepackage{CJK}\n"; + if (encoding().name() == "utf8-cjk" + && LaTeXFeatures::isAvailable("CJKutf8")) + os << "\\usepackage{CJKutf8}\n"; + else + os << "\\usepackage{CJK}\n"; texrow.newline(); break; } } - // The encoding "armscii8" is only available when the package "armtex" is loaded. - // armscii8 is used for Armenian. - if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") { + // The encoding "armscii8" (for Armenian) is only available when + // the package "armtex" is loaded. + if (language->encoding()->latexName() == "armscii8" + || inputenc == "armscii8") { os << "\\usepackage{armtex}\n"; texrow.newline(); } } +string const BufferParams::parseFontName(string const & name) const +{ + string mangled = name; + size_t const idx = mangled.find('['); + if (idx == string::npos || idx == 0) + return mangled; + else + return mangled.substr(0, idx - 1); +} + + string const BufferParams::loadFonts(string const & rm, string const & sf, string const & tt, bool const & sc, bool const & osf, - int const & sfscale, int const & ttscale) const + int const & sfscale, int const & ttscale, + bool const & xetex) const { /* The LaTeX font world is in a flux. In the PSNFSS font interface, several packages have been replaced by others, that might not @@ -1854,6 +2170,37 @@ string const BufferParams::loadFonts(string const & rm, ostringstream os; + if (xetex) { + if (rm != "default") + os << "\\setmainfont[Mapping=tex-text]{" + << parseFontName(rm) << "}\n"; + if (sf != "default") { + string const sans = parseFontName(sf); + if (sfscale != 100) + os << "\\setsansfont[Scale=" + << float(sfscale) / 100 + << ",Mapping=tex-text]{" + << sans << "}\n"; + else + os << "\\setsansfont[Mapping=tex-text]{" + << sans << "}\n"; + } + if (tt != "default") { + string const mono = parseFontName(tt); + if (ttscale != 100) + os << "\\setmonofont[Scale=" + << float(sfscale) / 100 + << "]{" + << mono << "}\n"; + else + os << "\\setmonofont[Mapping=tex-text]{" + << mono << "}\n"; + } + if (osf) + os << "\\defaultfontfeatures{Numbers=OldStyle}\n"; + return os.str(); + } + // ROMAN FONTS // Computer Modern (must be explicitely selectable -- there might be classes // that define a different default font! @@ -1869,7 +2216,7 @@ string const BufferParams::loadFonts(string const & rm, // AE else if (rm == "ae") { // not needed when using OT1 font encoding. - if (lyxrc.fontenc != "default") + if (font_encoding() != "default") os << "\\usepackage{ae,aecompl}\n"; } // Times @@ -1908,7 +2255,7 @@ string const BufferParams::loadFonts(string const & rm, // fourier supersedes utopia.sty, but does // not work with OT1 encoding. if (LaTeXFeatures::isAvailable("fourier") - && lyxrc.fontenc != "default") { + && font_encoding() != "default") { os << "\\usepackage"; if (osf || sc) { os << '['; @@ -1961,7 +2308,7 @@ string const BufferParams::loadFonts(string const & rm, else if (tt == "courier" ) os << "\\usepackage{" << tt << "}\n"; // Computer Modern, Latin Modern, CM Bright - else if (tt != "default") + else if (tt != "default") os << "\\renewcommand{\\ttdefault}{" << tt << "}\n"; return os.str(); @@ -1970,30 +2317,31 @@ string const BufferParams::loadFonts(string const & rm, Encoding const & BufferParams::encoding() const { + if (useXetex) + return *(encodings.fromLaTeXName("utf8-plain")); if (inputenc == "auto" || inputenc == "default") - return *(language->encoding()); - Encoding const * const enc = - encodings.getFromLaTeXName(inputenc); + return *language->encoding(); + Encoding const * const enc = encodings.fromLaTeXName(inputenc); if (enc) return *enc; - lyxerr << "Unknown inputenc value `" << inputenc - << "'. Using `auto' instead." << endl; - return *(language->encoding()); + LYXERR0("Unknown inputenc value `" << inputenc + << "'. Using `auto' instead."); + return *language->encoding(); } -biblio::CiteEngine BufferParams::getEngine() const +CiteEngine BufferParams::citeEngine() const { // FIXME the class should provide the numerical/ // authoryear choice if (documentClass().provides("natbib") - && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL) - return biblio::ENGINE_NATBIB_AUTHORYEAR; + && cite_engine_ != ENGINE_NATBIB_NUMERICAL) + return ENGINE_NATBIB_AUTHORYEAR; return cite_engine_; } -void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine) +void BufferParams::setCiteEngine(CiteEngine cite_engine) { cite_engine_ = cite_engine; }