X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferParams.cpp;h=2a3841f85dd976b9999fd834588cc4654589fc30;hb=04e6076ebb889a3215eaa4ff5cb200822611185c;hp=f1d009279de4c0a70a40f9e06cfd5f4e0034aca0;hpb=3a9a0fc3e6c49784437eb7b2cba481845b4f5687;p=lyx.git diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index f1d009279d..2a3841f85d 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" @@ -69,7 +72,11 @@ static char const * const string_quotes_language[] = { static char const * const string_papersize[] = { "default", "custom", "letterpaper", "legalpaper", "executivepaper", - "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", "" + "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper", + "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper", + "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper", + "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j", + "b6j", "" }; @@ -92,6 +99,7 @@ static char const * const tex_graphics[] = { }; + namespace lyx { // Local translators @@ -152,12 +160,34 @@ static PaperSizeTranslator initPaperSizeTranslator() translator.addPair(string_papersize[2], PAPER_USLETTER); translator.addPair(string_papersize[3], PAPER_USLEGAL); translator.addPair(string_papersize[4], PAPER_USEXECUTIVE); - translator.addPair(string_papersize[5], PAPER_A3); - translator.addPair(string_papersize[6], PAPER_A4); - translator.addPair(string_papersize[7], PAPER_A5); - translator.addPair(string_papersize[8], PAPER_B3); - translator.addPair(string_papersize[9], PAPER_B4); - translator.addPair(string_papersize[10], PAPER_B5); + translator.addPair(string_papersize[5], PAPER_A0); + translator.addPair(string_papersize[6], PAPER_A1); + translator.addPair(string_papersize[7], PAPER_A2); + translator.addPair(string_papersize[8], PAPER_A3); + translator.addPair(string_papersize[9], PAPER_A4); + translator.addPair(string_papersize[10], PAPER_A5); + translator.addPair(string_papersize[11], PAPER_A6); + translator.addPair(string_papersize[12], PAPER_B0); + translator.addPair(string_papersize[13], PAPER_B1); + translator.addPair(string_papersize[14], PAPER_B2); + translator.addPair(string_papersize[15], PAPER_B3); + translator.addPair(string_papersize[16], PAPER_B4); + translator.addPair(string_papersize[17], PAPER_B5); + translator.addPair(string_papersize[18], PAPER_B6); + translator.addPair(string_papersize[19], PAPER_C0); + translator.addPair(string_papersize[20], PAPER_C1); + translator.addPair(string_papersize[21], PAPER_C2); + translator.addPair(string_papersize[22], PAPER_C3); + translator.addPair(string_papersize[23], PAPER_C4); + translator.addPair(string_papersize[24], PAPER_C5); + translator.addPair(string_papersize[25], PAPER_C6); + translator.addPair(string_papersize[26], PAPER_JISB0); + translator.addPair(string_papersize[27], PAPER_JISB1); + translator.addPair(string_papersize[28], PAPER_JISB2); + translator.addPair(string_papersize[29], PAPER_JISB3); + translator.addPair(string_papersize[30], PAPER_JISB4); + translator.addPair(string_papersize[31], PAPER_JISB5); + translator.addPair(string_papersize[32], PAPER_JISB6); return translator; } @@ -269,7 +299,6 @@ SpaceTranslator const & spacetranslator() return translator; } - } // anon namespace @@ -282,10 +311,12 @@ public: BranchList branchlist; 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_; @@ -331,33 +362,60 @@ BufferParams::BufferParams() use_geometry = false; use_amsmath = package_auto; use_esint = package_auto; + use_mhchem = package_auto; + use_mathdots = package_auto; cite_engine_ = ENGINE_BASIC; use_bibtopic = false; + use_indices = false; trackChanges = false; outputChanges = false; use_default_options = true; + maintain_unincluded_children = false; 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"; - compressed = false; + suppress_date = false; + // no color is the default (white) + backgroundcolor = lyx::rgbFromHexName("#ffffff"); + isbackgroundcolor = false; + // no color is the default (black) + fontcolor = lyx::rgbFromHexName("#000000"); + isfontcolor = false; + // light gray is the default font color for greyed-out notes + notefontcolor = lyx::rgbFromHexName("#cccccc"); + boxbgcolor = lyx::rgbFromHexName("#ff0000"); + compressed = lyxrc.save_compressed; 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 = false; + html_math_output = MathML; + html_math_img_scale = 1.0; + + output_sync = false; + use_refstyle = true; } @@ -392,6 +450,18 @@ BranchList const & BufferParams::branchlist() const } +IndicesList & BufferParams::indiceslist() +{ + return pimpl_->indiceslist; +} + + +IndicesList const & BufferParams::indiceslist() const +{ + return pimpl_->indiceslist; +} + + Bullet & BufferParams::temp_bullet(lyx::size_type const index) { LASSERT(index < 4, /**/); @@ -444,6 +514,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; @@ -452,6 +534,8 @@ VSpace const & BufferParams::getDefSkip() const void BufferParams::setDefSkip(VSpace const & vs) { + // DEFSKIP will cause an infinite loop + LASSERT(vs.kind() != VSpace::DEFSKIP, return); pimpl_->defskip = vs; } @@ -467,7 +551,7 @@ string BufferParams::readToken(Lexer & lex, string const & token, string tcp; LayoutFileList & bcl = LayoutFileList::get(); if (tcp.empty() && !filepath.empty()) - tcp = bcl.addLocalLayout(classname, filepath.absFilename()); + tcp = bcl.addLocalLayout(classname, filepath.absFileName()); if (!tcp.empty()) setBaseClass(tcp); else @@ -475,16 +559,22 @@ string BufferParams::readToken(Lexer & lex, string const & token, // 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 desc = + translateIfPossible(from_utf8(baseClass()->description())); + docstring const prereqs = from_utf8(baseClass()->prerequisites()); docstring const msg = - bformat(_("The layout file requested by this document,\n" - "%1$s.layout,\n" - "is not usable. This is probably because a LaTeX\n" - "class or style file required by it is not\n" - "available. See the Customization documentation\n" - "for more information.\n"), from_utf8(classname)); + bformat(_("The selected document class\n" + "\t%1$s\n" + "requires external files that are not available.\n" + "The document class can still be used, but the\n" + "document cannot be compiled until the following\n" + "prerequisites are installed:\n" + "\t%2$s\n" + "See section 3.1.2.2 of the User's Guide for\n" + "more information."), desc, prereqs); frontend::Alert::warning(_("Document class not available"), - msg + _("LyX will not be able to produce output.")); - } + msg); + } } else if (token == "\\begin_preamble") { readPreamble(lex); } else if (token == "\\begin_local_layout") { @@ -493,6 +583,10 @@ string BufferParams::readToken(Lexer & lex, string const & token, readModules(lex); } else if (token == "\\begin_removed_modules") { readRemovedModules(lex); + } else if (token == "\\begin_includeonly") { + readIncludeonly(lex); + } else if (token == "\\maintain_unincluded_children") { + lex >> maintain_unincluded_children; } else if (token == "\\options") { lex.eatLine(); options = lex.getString(); @@ -501,20 +595,38 @@ string BufferParams::readToken(Lexer & lex, string const & token, } 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") { @@ -529,13 +641,17 @@ string BufferParams::readToken(Lexer & lex, string const & token, 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(); - if (defskip == "defskip") - // this is invalid - defskip = "medskip"; + string const defskip = lex.getString(); pimpl_->defskip = VSpace(defskip); + if (pimpl_->defskip.kind() == VSpace::DEFSKIP) + // that is invalid + pimpl_->defskip = VSpace(VSpace::MEDSKIP); } else if (token == "\\quotes_language") { string quotes_lang; lex >> quotes_lang; @@ -554,18 +670,28 @@ string 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 == "\\use_mathdots") { + int usemathdots; + lex >> usemathdots; + use_mathdots = packagetranslator().find(usemathdots); } 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) { @@ -579,7 +705,11 @@ string 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(); @@ -590,7 +720,36 @@ string 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") { @@ -598,11 +757,27 @@ string 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()); + isbackgroundcolor = true; + } else if (token == "\\fontcolor") { + lex.eatLine(); + fontcolor = lyx::rgbFromHexName(lex.getString()); + isfontcolor = true; + } else if (token == "\\notefontcolor") { + lex.eatLine(); + string color = lex.getString(); + notefontcolor = lyx::rgbFromHexName(color); + } else if (token == "\\boxbgcolor") { + lex.eatLine(); + string color = lex.getString(); + boxbgcolor = lyx::rgbFromHexName(color); } else if (token == "\\paperwidth") { lex >> paperwidth; } else if (token == "\\paperheight") { @@ -663,6 +838,26 @@ string BufferParams::readToken(Lexer & lex, string const & token, toktmp << endl; return toktmp; } + } else if (token == "\\html_math_output") { + int temp; + lex >> temp; + html_math_output = static_cast(temp); + } else if (token == "\\html_be_strict") { + lex >> html_be_strict; + } else if (token == "\\html_math_img_scale") { + lex >> html_math_img_scale; + } else if (token == "\\html_latex_start") { + lex.eatLine(); + html_latex_start = lex.getString(); + } else if (token == "\\html_latex_end") { + lex.eatLine(); + html_latex_end = lex.getString(); + } else if (token == "\\output_sync") { + lex >> output_sync; + } else if (token == "\\output_sync_macro") { + lex >> output_sync_macro; + } else if (token == "\\use_refstyle") { + lex >> use_refstyle; } else { lyxerr << "BufferParams::readToken(): Unknown token: " << token << endl; @@ -707,8 +902,8 @@ void BufferParams::writeFile(ostream & os) const // removed modules if (!removedModules_.empty()) { os << "\\begin_removed_modules" << '\n'; - set::const_iterator it = removedModules_.begin(); - set::const_iterator en = removedModules_.end(); + list::const_iterator it = removedModules_.begin(); + list::const_iterator en = removedModules_.end(); for (; it != en; it++) os << *it << '\n'; os << "\\end_removed_modules" << '\n'; @@ -723,7 +918,19 @@ void BufferParams::writeFile(ostream & os) const os << *it << '\n'; os << "\\end_modules" << '\n'; } - + + // includeonly + if (!includedChildren_.empty()) { + os << "\\begin_includeonly" << '\n'; + list::const_iterator it = includedChildren_.begin(); + list::const_iterator en = includedChildren_.end(); + for (; it != en; it++) + os << *it << '\n'; + os << "\\end_includeonly" << '\n'; + } + os << "\\maintain_unincluded_children " + << convert(maintain_unincluded_children) << '\n'; + // local layout information if (!local_layout.empty()) { // remove '\n' from the end @@ -737,10 +944,12 @@ void BufferParams::writeFile(ostream & os) const 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 @@ -750,6 +959,12 @@ void BufferParams::writeFile(ostream & os) const os << "\\font_cjk " << fontsCJK << '\n'; } os << "\n\\graphics " << graphicsDriver << '\n'; + os << "\\default_output_format " << defaultOutputFormat << '\n'; + os << "\\output_sync " << output_sync << '\n'; + if (!output_sync_macro.empty()) + os << "\\output_sync_macro \"" << output_sync_macro << "\"\n"; + os << "\\bibtex_command " << bibtex_command << '\n'; + os << "\\index_command " << index_command << '\n'; if (!float_placement.empty()) { os << "\\float_placement " << float_placement << '\n'; @@ -763,21 +978,45 @@ 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\\use_mathdots " << use_mathdots << "\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\\use_refstyle " << use_refstyle << '\n'; + if (isbackgroundcolor == true) + os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n'; + if (isfontcolor == true) + os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n'; + if (notefontcolor != lyx::rgbFromHexName("#cccccc")) + os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n'; + if (boxbgcolor != lyx::rgbFromHexName("#ff0000")) + os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n'; BranchList::const_iterator it = branchlist().begin(); BranchList::const_iterator end = branchlist().end(); for (; it != end; ++it) { 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'; @@ -811,9 +1050,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 @@ -838,17 +1080,19 @@ void BufferParams::writeFile(ostream & os) const } } - os << "\\tracking_changes " << convert(trackChanges) << "\n"; - os << "\\output_changes " << convert(outputChanges) << "\n"; + os << "\\tracking_changes " << convert(trackChanges) << '\n' + << "\\output_changes " << convert(outputChanges) << '\n' + << "\\html_math_output " << html_math_output << '\n' + << "\\html_be_strict " << convert(html_be_strict) << '\n'; + + if (html_math_img_scale != 1.0) + os << "\\html_math_img_scale " << convert(html_math_img_scale) << '\n'; + if (!html_latex_start.empty()) + os << "\\html_latex_start " << html_latex_start << '\n'; + if (!html_latex_end.empty()) + os << "\\html_latex_end " << html_latex_end << '\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 << pimpl_->authorlist; } @@ -858,7 +1102,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 +1110,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 +1145,10 @@ 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"); + if (use_mathdots == package_on) + features.require("mathdots"); // Document-level line spacing if (spacing().getSpace() != Spacing::Single && !spacing().isDefault()) @@ -931,11 +1180,14 @@ void BufferParams::validate(LaTeXFeatures & features) const 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://bugzilla.lyx.org/show_bug.cgi?id=5291 + // 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") @@ -944,7 +1196,7 @@ void BufferParams::validate(LaTeXFeatures & features) const bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, - TexRow & texrow) const + TexRow & texrow, FileName const & filepath) const { os << "\\documentclass"; @@ -958,11 +1210,15 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, clsoptions << fontsize << "pt,"; } - // custom, A3, B3 and B4 paper sizes need geometry - bool nonstandard_papersize = papersize == PAPER_B3 - || papersize == PAPER_B4 - || papersize == PAPER_A3 - || papersize == PAPER_CUSTOM; + // all paper sizes except of A4, A5, B5 and the US sizes need the + // geometry package + bool nonstandard_papersize = papersize != PAPER_DEFAULT + && papersize != PAPER_USLETTER + && papersize != PAPER_USLEGAL + && papersize != PAPER_USEXECUTIVE + && papersize != PAPER_A4 + && papersize != PAPER_A5 + && papersize != PAPER_B5; if (!use_geometry) { switch (papersize) { @@ -985,9 +1241,31 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, clsoptions << "legalpaper,"; break; case PAPER_DEFAULT: + case PAPER_A0: + case PAPER_A1: + case PAPER_A2: case PAPER_A3: + case PAPER_A6: + case PAPER_B0: + case PAPER_B1: + case PAPER_B2: case PAPER_B3: case PAPER_B4: + case PAPER_B6: + case PAPER_C0: + case PAPER_C1: + case PAPER_C2: + case PAPER_C3: + case PAPER_C4: + case PAPER_C5: + case PAPER_C6: + case PAPER_JISB0: + case PAPER_JISB1: + case PAPER_JISB2: + case PAPER_JISB3: + case PAPER_JISB4: + case PAPER_JISB5: + case PAPER_JISB6: case PAPER_CUSTOM: break; } @@ -1024,7 +1302,7 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, features.useLanguage(default_language); ostringstream language_options; - bool const use_babel = features.useBabel(); + bool const use_babel = features.useBabel() && !tclass.provides("babel"); if (use_babel) { language_options << features.getLanguages(); if (!language->babel().empty()) { @@ -1039,18 +1317,20 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, // 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 + // this is currently the case for Latvian, Lithuanian, Mongolian + // and Turkmen size_t latvian = language_options.str().find("latvian"); size_t lithu = language_options.str().find("lithuanian"); size_t mongo = language_options.str().find("mongolian"); + size_t turkmen = language_options.str().find("turkmen"); // if Japanese is used, babel must directly be loaded // with language options, not in the class options, see - // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4 + // 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 && japan == string::npos && latvian == string::npos && lithu == string::npos - && mongo == string::npos) + && mongo == string::npos && turkmen == string::npos) clsoptions << language_options.str() << ','; } @@ -1074,11 +1354,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(); @@ -1088,17 +1373,21 @@ 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" && language->lang() != "japanese") { + // XeTeX works without fontenc + if (font_encoding() != "default" && language->lang() != "japanese" + && !useXetex && !tclass.provides("fontenc")) { + size_t fars = language_options.str().find("farsi"); + size_t arab = language_options.str().find("arabic"); if (language->lang() == "arabic_arabi" - || language->lang() == "farsi") { - os << "\\usepackage[" << from_ascii(lyxrc.fontenc) + || language->lang() == "farsi" || fars != string::npos + || arab != string::npos) { + 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(); } @@ -1107,6 +1396,31 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, // handle inputenc etc. writeEncodingPreamble(os, features, texrow); + // includeonly + if (!features.runparams().includeall && !includedChildren_.empty()) { + os << "\\includeonly{"; + list::const_iterator it = includedChildren_.begin(); + bool first = true; + for (; it != includedChildren_.end() ; ++it) { + string incfile = *it; + FileName inc = makeAbsPath(incfile, filepath.absFileName()); + string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")). + mangledFileName(); + if (!features.runparams().nice) + incfile = mangled; + // \includeonly doesn't want an extension + incfile = changeExtension(incfile, string()); + incfile = support::latex_path(incfile); + if (!incfile.empty()) { + if (!first) + os << ","; + os << from_utf8(incfile); + } + first = false; + } + os << "}\n"; + } + if (!listings_params.empty() || features.isRequired("listings")) { os << "\\usepackage{listings}\n"; texrow.newline(); @@ -1128,98 +1442,198 @@ 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_A0: + ods << ",a0paper"; + break; + case PAPER_A1: + ods << ",a1paper"; + break; + case PAPER_A2: + ods << ",a2paper"; 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_A6: + ods << ",a6paper"; + break; + case PAPER_B0: + ods << ",b0paper"; + break; + case PAPER_B1: + ods << ",b1paper"; + break; + case PAPER_B2: + ods << ",b2paper"; 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; + case PAPER_B6: + ods << ",b6paper"; + break; + case PAPER_C0: + ods << ",c0paper"; + break; + case PAPER_C1: + ods << ",c1paper"; + break; + case PAPER_C2: + ods << ",c2paper"; + break; + case PAPER_C3: + ods << ",c3paper"; + break; + case PAPER_C4: + ods << ",c4paper"; + break; + case PAPER_C5: + ods << ",c5paper"; + break; + case PAPER_C6: + ods << ",c6paper"; + break; + case PAPER_JISB0: + ods << ",b0j"; + break; + case PAPER_JISB1: + ods << ",b1j"; + break; + case PAPER_JISB2: + ods << ",b2j"; + break; + case PAPER_JISB3: + ods << ",b3j"; + break; + case PAPER_JISB4: + ods << ",b4j"; + break; + case PAPER_JISB5: + ods << ",b5j"; + break; + case PAPER_JISB6: + ods << ",b6j"; 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_A0: + case PAPER_A1: + case PAPER_A2: + case PAPER_A6: + case PAPER_B0: + case PAPER_B1: + case PAPER_B2: case PAPER_B3: case PAPER_B4: + case PAPER_B6: + case PAPER_C0: + case PAPER_C1: + case PAPER_C2: + case PAPER_C3: + case PAPER_C4: + case PAPER_C5: + case PAPER_C6: + case PAPER_JISB0: + case PAPER_JISB1: + case PAPER_JISB2: + case PAPER_JISB3: + case PAPER_JISB4: + case PAPER_JISB5: + case PAPER_JISB6: case PAPER_CUSTOM: break; } } - if (!topmargin.empty()) - os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString()); - if (!bottommargin.empty()) - os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString()); - if (!leftmargin.empty()) - os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString()); - if (!rightmargin.empty()) - os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString()); - if (!headheight.empty()) - os << ",headheight=" << from_ascii(Length(headheight).asLatexString()); - if (!headsep.empty()) - os << ",headsep=" << from_ascii(Length(headsep).asLatexString()); - if (!footskip.empty()) - os << ",footskip=" << from_ascii(Length(footskip).asLatexString()); - if (!columnsep.empty()) - os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString()); - os << "}\n"; + docstring const g_options = trim(ods.str(), ","); + os << "\\usepackage"; + if (!g_options.empty()) + os << '[' << g_options << ']'; + os << "{geometry}\n"; texrow.newline(); - } else if (orientation == ORIENTATION_LANDSCAPE) { + // output this only if use_geometry is true + if (use_geometry) { + os << "\\geometry{verbose"; + if (!topmargin.empty()) + os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString()); + if (!bottommargin.empty()) + os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString()); + if (!leftmargin.empty()) + os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString()); + if (!rightmargin.empty()) + os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString()); + if (!headheight.empty()) + os << ",headheight=" << from_ascii(Length(headheight).asLatexString()); + if (!headsep.empty()) + os << ",headsep=" << from_ascii(Length(headsep).asLatexString()); + if (!footskip.empty()) + os << ",footskip=" << from_ascii(Length(footskip).asLatexString()); + if (!columnsep.empty()) + os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString()); + os << "}\n"; + texrow.newline(); + } + } else if (orientation == ORIENTATION_LANDSCAPE + || papersize != PAPER_DEFAULT) { features.require("papersize"); } @@ -1233,6 +1647,24 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, texrow.newline(); } + // only output when the background color is not default + if (isbackgroundcolor == true) { + // 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 output when the font color is not default + if (isfontcolor == true) { + // only require color here, the font color will be defined + // in LaTeXFeatures.cpp to avoid interferences with the LaTeX + // package pdfpages + features.require("color"); + features.require("fontcolor"); + } + // Only if class has a ToC hierarchy if (tclass.hasTocLevels()) { if (secnumdepth != tclass.secnumdepth()) { @@ -1250,6 +1682,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"; @@ -1270,18 +1703,35 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, break; } texrow.newline(); - os << "\\setlength{\\parindent}{0pt}\n"; 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; + if (output_sync) { + if (!output_sync_macro.empty()) + lyxpreamble += from_utf8(output_sync_macro) +"\n"; + else if (features.runparams().flavor == OutputParams::LATEX) + lyxpreamble += "\\usepackage[active]{srcltx}\n"; + else if (features.runparams().flavor == OutputParams::PDFLATEX) + lyxpreamble += "\\synctex=-1\n"; + } + // 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://bugzilla.lyx.org/show_bug.cgi?id=5291 + // 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()); @@ -1300,6 +1750,19 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, // The optional packages; 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"))); @@ -1311,18 +1774,30 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, // before hyperref. Then hyperref has a chance to detect babel. // * Has to be loaded before the "LyX specific LaTeX commands" to // avoid errors with algorithm floats. - // use hyperref explicitely when it is required + // use hyperref explicitly if it is required if (features.isRequired("hyperref")) { - odocstringstream oss; - pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref")); - lyxpreamble += oss.str(); - } - - // Will be surrounded by \makeatletter and \makeatother when needed + // pass what we have to stream here, since we need + // to access the stream itself in PDFOptions. + os << lyxpreamble; + + int lines = + int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n')); + + OutputParams tmp_params = features.runparams(); + lines += pdfoptions().writeLaTeX(tmp_params, os, + documentClass().provides("hyperref")); + texrow.newlines(lines); + // set back for the rest + lyxpreamble.clear(); + } else if (features.isRequired("nameref")) + // hyperref loads this automatically + lyxpreamble += "\\usepackage{nameref}\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()) atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " @@ -1336,8 +1811,14 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, "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 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " "User specified LaTeX commands.\n" @@ -1394,11 +1875,9 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, if (!bullets_def.empty()) atlyxpreamble += bullets_def + "}\n\n"; - if (atlyxpreamble.find(from_ascii("@")) != docstring::npos) + if (!atlyxpreamble.empty()) lyxpreamble += "\n\\makeatletter\n" + atlyxpreamble + "\\makeatother\n\n"; - else - lyxpreamble += '\n' + atlyxpreamble; // We try to load babel late, in case it interferes with other packages. // Jurabib and Hyperref have to be called after babel, though. @@ -1411,13 +1890,25 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, lyxpreamble += from_utf8(features.getBabelOptions()) + '\n'; } + docstring const i18npreamble = features.getTClassI18nPreamble(use_babel); + if (!i18npreamble.empty()) + lyxpreamble += i18npreamble + '\n'; + int const nlines = int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n')); - for (int j = 0; j != nlines; ++j) { - texrow.newline(); - } + texrow.newlines(nlines); 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; } @@ -1457,196 +1948,30 @@ DocumentClass const & BufferParams::documentClass() const } -DocumentClass const * BufferParams::documentClassPtr() const { +DocumentClass const * BufferParams::documentClassPtr() const +{ return doc_class_; } -void BufferParams::setDocumentClass(DocumentClass const * const tc) { +void BufferParams::setDocumentClass(DocumentClass const * const tc) +{ // evil, but this function is evil doc_class_ = const_cast(tc); } -void BufferParams::removeExcludedModules() -{ - // remove any modules the new base class excludes - list oldModules = getModules(); - clearLayoutModules(); - list::const_iterator oit = oldModules.begin(); - list::const_iterator oen = oldModules.end(); - list const & provmods = baseClass()->providedModules(); - list const & exclmods = baseClass()->excludedModules(); - for (; oit != oen; ++oit) { - string const & modname = *oit; - // are we excluded by the document class? - if (find(exclmods.begin(), exclmods.end(), modname) != exclmods.end()) { - LYXERR0("Module " << modname << " dropped because excluded by document class."); - continue; - } - // determine whether some provided module excludes us or we exclude it - list::const_iterator pit = provmods.begin(); - list::const_iterator pen = provmods.end(); - bool excluded = false; - for (; !excluded && pit != pen; ++pit) { - if (!LyXModule::areCompatible(modname, *pit)) { - LYXERR0("Module " << modname << - " dropped becuase it conflicts with provided module " << *pit); - excluded = true; - } - } - if (excluded) - continue; - layoutModules_.push_back(*oit); - } -} - - -void BufferParams::addDefaultModules() -{ - // add any default modules not already in use - list const & mods = baseClass()->defaultModules(); - list::const_iterator mit = mods.begin(); - list::const_iterator men = mods.end(); - - // we want to add these to the front, but in the right order, - // so we collect them here first. - list modulesToAdd; - - for (; mit != men; mit++) { - string const & modName = *mit; - // make sure the user hasn't removed it - if (find(removedModules_.begin(), removedModules_.end(), modName) != - removedModules_.end()) { - LYXERR(Debug::TCLASS, "Default module `" << modName << - "' not added because removed by user."); - continue; - } - - if (moduleCanBeAdded(modName)) { - LYXERR(Debug::TCLASS, "Default module `" << modName << "' added."); - modulesToAdd.push_back(modName); - } else - LYXERR(Debug::TCLASS, - "Default module `" << modName << "' could not be added."); - } - - // OK, now we can add the default modules. - layoutModules_.insert( - layoutModules_.begin(), modulesToAdd.begin(), modulesToAdd.end()); -} - - -bool BufferParams::checkModuleConsistency() { - bool consistent = true; - // Perform a consistency check on the set of modules. - // In particular, we need to check that modules provided by this class - // do not conflict with modules chosen by the user. - list oldModules = getModules(); - clearLayoutModules(); - list::const_iterator oit = oldModules.begin(); - list::const_iterator oen = oldModules.end(); - list const & provmods = baseClass()->providedModules(); - list const & exclmods = baseClass()->excludedModules(); - for (; oit != oen; ++oit) { - string const & modname = *oit; - // skip modules that the class provides - if (find(provmods.begin(), provmods.end(), modname) != provmods.end()) { - consistent = false; - LYXERR0("Module " << modname << " dropped because provided by document class."); - continue; - } - // are we excluded by the document class? - // FIXME This can probably be removed, since removeExcludedModules ought - // already to have done this test. - if (find(exclmods.begin(), exclmods.end(), modname) != exclmods.end()) { - consistent = false; - LYXERR0("WARNING: Module " << modname << " should already have been dropped!"); - continue; - } - // FIXME This test can probably also be dropped, for the same reason. - // determine whether some provided module excludes us or we exclude it - list::const_iterator pit = provmods.begin(); - list::const_iterator pen = provmods.end(); - bool excluded = false; - for (; !excluded && pit != pen; ++pit) { - if (!LyXModule::areCompatible(modname, *pit)) { - consistent = false; - LYXERR0("WARNING: Module " << modname << " should already have been dropped!"); - excluded = true; - } - } - - if (excluded) - continue; - - // Determine whether some prior module excludes us, or we exclude it - list::const_iterator lit = layoutModules_.begin(); - list::const_iterator len = layoutModules_.end(); - for (; !excluded && lit != len; ++lit) { - if (!LyXModule::areCompatible(modname, *lit)) { - consistent = false; - LYXERR0("Module " << modname << - " dropped because it is excluded by prior module " << *lit); - excluded = true; - } - } - - if (excluded) - continue; - - // determine whether some provided module or some prior module - // satisfies our requirements - LyXModule const * const oldmod = moduleList[modname]; - if (!oldmod) { - LYXERR0("Default module " << modname << - " added although it is unavailable and can't check requirements."); - continue; - } - - vector const & reqs = oldmod->getRequiredModules(); - if (!reqs.empty()) { - // we now set excluded to true, meaning that we haven't - // yet found a required module. - excluded = true; - vector::const_iterator rit = reqs.begin(); - vector::const_iterator ren = reqs.end(); - for (; rit != ren; ++rit) { - string const reqmod = *rit; - if (find(provmods.begin(), provmods.end(), reqmod) != - provmods.end()) { - excluded = false; - break; - } - if (find(layoutModules_.begin(), layoutModules_.end(), reqmod) != - layoutModules_.end()) { - excluded = false; - break; - } - } - } - if (excluded) { - consistent = false; - LYXERR0("Module " << modname << " dropped because requirements not met."); - } else { - LYXERR(Debug::TCLASS, "Module " << modname << " passed consistency check."); - layoutModules_.push_back(modname); - } - } - return consistent; -} - - bool BufferParams::setBaseClass(string const & classname) { LYXERR(Debug::TCLASS, "setBaseClass: " << classname); LayoutFileList & bcl = LayoutFileList::get(); if (!bcl.haveClass(classname)) { docstring s = - 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."), + bformat(_("The layout file:\n" + "%1$s\n" + "could not be found. A default textclass with default\n" + "layouts will be used. LyX will not be able to produce\n" + "correct output."), from_utf8(classname)); frontend::Alert::error(_("Document class not found"), s); bcl.addEmptyClass(classname); @@ -1655,29 +1980,18 @@ bool BufferParams::setBaseClass(string const & classname) bool const success = bcl[classname].load(); if (!success) { docstring s = - bformat(_("The document class %1$s could not be loaded."), + bformat(_("Due to some error in it, the layout file:\n" + "%1$s\n" + "could not be loaded. A default textclass with default\n" + "layouts will be used. LyX will not be able to produce\n" + "correct output."), from_utf8(classname)); frontend::Alert::error(_("Could not load class"), s); - return false; + bcl.addEmptyClass(classname); } pimpl_->baseClass_ = classname; - // the previous document class may have loaded some modules that the - // new one excludes, and the new class may provide, etc, some that - // conflict with ones that were already loaded. So we need to go - // through the list and fix everything. I suppose there are various - // ways this could be done, but the following seems to work at the - // moment. (Thanks to Philippe Charpentier for helping work out all - // the bugs---rgh.) - // - // first, we remove any modules the new document class excludes - removeExcludedModules(); - // next, we add any default modules the new class provides - addDefaultModules(); - // finally, we perform a general consistency check on the set of - // loaded modules - checkModuleConsistency(); - + layoutModules_.adaptToBaseClass(baseClass(), removedModules_); return true; } @@ -1702,41 +2016,8 @@ void BufferParams::makeDocumentClass() if (!baseClass()) return; - doc_class_ = &(DocumentClassBundle::get().newClass(*baseClass())); + doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_)); - // 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.")); - LYXERR0("BufferParams::makeDocumentClass(): Module " << - modName << " requested but not found in module list."); - 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)); - frontend::Alert::warning(_("Read Error"), msg); - } - } if (!local_layout.empty()) { if (!doc_class_->read(local_layout, TextClass::MODULE)) { docstring const msg = _("Error reading internal layout information"); @@ -1748,65 +2029,7 @@ void BufferParams::makeDocumentClass() bool BufferParams::moduleCanBeAdded(string const & modName) const { - // Is the module already present? - LayoutModuleList::const_iterator it = layoutModules_.begin(); - LayoutModuleList::const_iterator end = layoutModules_.end(); - for (; it != end; it++) - if (*it == modName) - return false; - - LyXModule const * const lm = moduleList[modName]; - if (!lm) - return true; - - // Is this module explicitly excluded by the document class? - list::const_iterator const exclmodstart = - baseClass()->excludedModules().begin(); - list::const_iterator const exclmodend = - baseClass()->excludedModules().end(); - if (find(exclmodstart, exclmodend, modName) != exclmodend) - return false; - - // Is this module already provided by the document class? - list::const_iterator const provmodstart = - baseClass()->providedModules().begin(); - list::const_iterator const provmodend = - baseClass()->providedModules().end(); - if (find(provmodstart, provmodend, modName) != provmodend) - return false; - - // Check for conflicts with used modules - // first the provided modules... - list::const_iterator provmodit = provmodstart; - for (; provmodit != provmodend; ++provmodit) { - if (!LyXModule::areCompatible(modName, *provmodit)) - return false; - } - // and then the selected modules - LayoutModuleList::const_iterator mit = getModules().begin(); - LayoutModuleList::const_iterator const men = getModules().end(); - for (; mit != men; ++mit) - if (!LyXModule::areCompatible(modName, *mit)) - return false; - - // Check whether some required module is available - vector const reqs = lm->getRequiredModules(); - if (reqs.empty()) - return true; - - mit = getModules().begin(); // reset - vector::const_iterator rit = reqs.begin(); - vector::const_iterator ren = reqs.end(); - bool foundone = false; - for (; rit != ren; ++rit) { - if (find(mit, men, *rit) != men || - find(provmodstart, provmodend, *rit) != provmodend) { - foundone = true; - break; - } - } - - return foundone; + return layoutModules_.moduleCanBeAdded(modName, baseClass()); } @@ -1960,15 +2183,15 @@ void BufferParams::readRemovedModules(Lexer & lex) string mod = lex.getString(); if (mod == "\\end_removed_modules") break; - removedModules_.insert(mod); + 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. - set::const_iterator rit = removedModules_.begin(); - set::const_iterator const ren = removedModules_.end(); + 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(); @@ -1980,6 +2203,23 @@ void BufferParams::readRemovedModules(Lexer & lex) } +void BufferParams::readIncludeonly(Lexer & lex) +{ + if (!lex.eatLine()) { + lyxerr << "Error (BufferParams::readIncludeonly):" + "Unexpected end of input." << endl; + return; + } + while (true) { + string child = lex.getString(); + if (child == "\\end_includeonly") + break; + includedChildren_.push_back(child); + lex.eatLine(); + } +} + + string BufferParams::paperSizeName(PapersizePurpose purpose) const { char real_papersize = papersize; @@ -2004,14 +2244,42 @@ string BufferParams::paperSizeName(PapersizePurpose purpose) const } return string(); } + case PAPER_A0: + // dvips and dvipdfm do not know this + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "a0"; + case PAPER_A1: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "a1"; + case PAPER_A2: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "a2"; case PAPER_A3: return "a3"; case PAPER_A4: return "a4"; case PAPER_A5: return "a5"; + case PAPER_A6: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "a6"; + case PAPER_B0: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "b0"; + case PAPER_B1: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "b1"; + case PAPER_B2: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "b2"; case PAPER_B3: - // dvips and dvipdfm do not know this if (purpose == DVIPS || purpose == DVIPDFM) return string(); return "b3"; @@ -2021,10 +2289,69 @@ string BufferParams::paperSizeName(PapersizePurpose purpose) const return string(); return "b4"; case PAPER_B5: - // dvipdfm does not know this if (purpose == DVIPDFM) return string(); return "b5"; + case PAPER_B6: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "b6"; + case PAPER_C0: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "c0"; + case PAPER_C1: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "c1"; + case PAPER_C2: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "c2"; + case PAPER_C3: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "c3"; + case PAPER_C4: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "c4"; + case PAPER_C5: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "c5"; + case PAPER_C6: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "c6"; + case PAPER_JISB0: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "jisb0"; + case PAPER_JISB1: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "jisb1"; + case PAPER_JISB2: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "jisb2"; + case PAPER_JISB3: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "jisb3"; + case PAPER_JISB4: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "jisb4"; + case PAPER_JISB5: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "jisb5"; + case PAPER_JISB6: + if (purpose == DVIPS || purpose == DVIPDFM) + return string(); + return "jisb6"; case PAPER_USEXECUTIVE: // dvipdfm does not know this if (purpose == DVIPDFM) @@ -2072,6 +2399,12 @@ string const BufferParams::dvips_options() 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; @@ -2089,25 +2422,48 @@ string BufferParams::babelCall(string const & lang_opts) const // 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 + // this is currently the case for Latvian, Lithuanian, Mongolian + // and Turkmen size_t latvian = lang_opts.find("latvian"); size_t lithu = lang_opts.find("lithuanian"); size_t mongo = lang_opts.find("mongolian"); + size_t turkmen = lang_opts.find("turkmen"); // If Japanese is used, babel must directly be loaded with the // language options, see - // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4 + // 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) + || lithu != string::npos || mongo != string::npos + || turkmen != 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(); @@ -2145,7 +2501,11 @@ 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") { @@ -2162,7 +2522,11 @@ void BufferParams::writeEncodingPreamble(odocstream & os, 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; } @@ -2178,10 +2542,22 @@ void BufferParams::writeEncodingPreamble(odocstream & os, } +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 @@ -2201,8 +2577,39 @@ 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 + // Computer Modern (must be explicitly selectable -- there might be classes // that define a different default font! if (rm == "cmr") { os << "\\renewcommand{\\rmdefault}{cmr}\n"; @@ -2216,7 +2623,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 @@ -2255,7 +2662,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 << '['; @@ -2317,6 +2724,8 @@ 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.fromLaTeXName(inputenc);