X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferParams.cpp;h=d94600fb0f303b8511f4a05b3f6eb681e37322ef;hb=f3370c3e6a0686b03769e48bcd3fb673925533a9;hp=41e43e73dcad89640658dd8da614621128197478;hpb=425d092204118ea6c24c28e85fdf03fcf2bb51a4;p=lyx.git diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index 41e43e73dc..d94600fb0f 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -24,11 +24,13 @@ #include "Bullet.h" #include "Color.h" #include "ColorSet.h" +#include "Converter.h" #include "Encoding.h" #include "HSpace.h" #include "IndicesList.h" #include "Language.h" #include "LaTeXFeatures.h" +#include "LaTeXFonts.h" #include "ModuleList.h" #include "Font.h" #include "Lexer.h" @@ -50,6 +52,7 @@ #include "support/filetools.h" #include "support/gettext.h" #include "support/Messages.h" +#include "support/mutex.h" #include "support/Translator.h" #include "support/lstrings.h" @@ -72,7 +75,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", "" }; @@ -81,11 +88,6 @@ static char const * const string_orientation[] = { }; -static char const * const string_footnotekinds[] = { - "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", "" -}; - - static char const * const tex_graphics[] = { "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx", "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex", @@ -116,7 +118,8 @@ ParSepTranslator const init_parseptranslator() ParSepTranslator const & parseptranslator() { - static ParSepTranslator translator = init_parseptranslator(); + static ParSepTranslator const translator = + init_parseptranslator(); return translator; } @@ -140,7 +143,8 @@ QuotesLangTranslator const init_quoteslangtranslator() QuotesLangTranslator const & quoteslangtranslator() { - static QuotesLangTranslator translator = init_quoteslangtranslator(); + static QuotesLangTranslator const translator = + init_quoteslangtranslator(); return translator; } @@ -156,19 +160,42 @@ 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; } PaperSizeTranslator const & papersizetranslator() { - static PaperSizeTranslator translator = initPaperSizeTranslator(); + static PaperSizeTranslator const translator = + initPaperSizeTranslator(); return translator; } @@ -187,7 +214,8 @@ PaperOrientationTranslator const init_paperorientationtranslator() PaperOrientationTranslator const & paperorientationtranslator() { - static PaperOrientationTranslator translator = init_paperorientationtranslator(); + static PaperOrientationTranslator const translator = + init_paperorientationtranslator(); return translator; } @@ -206,7 +234,7 @@ SidesTranslator const init_sidestranslator() SidesTranslator const & sidestranslator() { - static SidesTranslator translator = init_sidestranslator(); + static SidesTranslator const translator = init_sidestranslator(); return translator; } @@ -226,28 +254,29 @@ PackageTranslator const init_packagetranslator() PackageTranslator const & packagetranslator() { - static PackageTranslator translator = init_packagetranslator(); + static PackageTranslator const translator = + init_packagetranslator(); return translator; } // Cite engine -typedef Translator CiteEngineTranslator; +typedef Translator CiteEngineTypeTranslator; -CiteEngineTranslator const init_citeenginetranslator() +CiteEngineTypeTranslator const init_citeenginetypetranslator() { - CiteEngineTranslator translator("basic", ENGINE_BASIC); - translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL); - translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR); - translator.addPair("jurabib", ENGINE_JURABIB); + CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR); + translator.addPair("numerical", ENGINE_TYPE_NUMERICAL); + translator.addPair("default", ENGINE_TYPE_DEFAULT); return translator; } -CiteEngineTranslator const & citeenginetranslator() +CiteEngineTypeTranslator const & citeenginetypetranslator() { - static CiteEngineTranslator translator = init_citeenginetranslator(); + static CiteEngineTypeTranslator const translator = + init_citeenginetypetranslator(); return translator; } @@ -269,7 +298,7 @@ SpaceTranslator const init_spacetranslator() SpaceTranslator const & spacetranslator() { - static SpaceTranslator translator = init_spacetranslator(); + static SpaceTranslator const translator = init_spacetranslator(); return translator; } @@ -309,8 +338,7 @@ BufferParams::Impl::Impl() BufferParams::Impl * BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr) { - LASSERT(ptr, /**/); - + LBUFERR(ptr); return new BufferParams::Impl(*ptr); } @@ -334,32 +362,33 @@ BufferParams::BufferParams() papersize = PAPER_DEFAULT; orientation = ORIENTATION_PORTRAIT; use_geometry = false; - use_amsmath = package_auto; - use_esint = package_auto; - use_mhchem = package_auto; - cite_engine_ = ENGINE_BASIC; + cite_engine_.push_back("basic"); + cite_engine_type_ = ENGINE_TYPE_DEFAULT; + biblio_style = "plain"; use_bibtopic = false; use_indices = false; - trackChanges = false; - outputChanges = false; + track_changes = false; + output_changes = 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; + fonts_roman = "default"; + fonts_sans = "default"; + fonts_typewriter = "default"; + fonts_math = "auto"; + fonts_default_family = "default"; + useNonTeXFonts = false; + fonts_expert_sc = false; + fonts_old_figures = false; + fonts_sans_scale = 100; + fonts_typewriter_scale = 100; inputenc = "auto"; - graphicsDriver = "default"; - defaultOutputFormat = "default"; + lang_package = "default"; + graphics_driver = "default"; + default_output_format = "default"; bibtex_command = "default"; index_command = "default"; sides = OneSide; @@ -367,27 +396,94 @@ BufferParams::BufferParams() listings_params = string(); pagestyle = "default"; suppress_date = false; - // white is equal to no background color + justification = true; + // no color is the default (white) backgroundcolor = lyx::rgbFromHexName("#ffffff"); - compressed = false; + 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 = true; - html_use_mathml = true; + html_be_strict = false; + html_math_output = MathML; + html_math_img_scale = 1.0; + html_css_as_file = false; + display_pixel_ratio = 1.0; + + output_sync = false; + use_refstyle = true; } docstring BufferParams::B_(string const & l10n) const { - LASSERT(language, /**/); + LASSERT(language, return from_utf8(l10n)); return getMessages(language->code()).get(l10n); } +BufferParams::Package BufferParams::use_package(std::string const & p) const +{ + PackageMap::const_iterator it = use_packages.find(p); + if (it == use_packages.end()) + return package_auto; + return it->second; +} + + +void BufferParams::use_package(std::string const & p, BufferParams::Package u) +{ + use_packages[p] = u; +} + + +map const & BufferParams::auto_packages() +{ + static map packages; + if (packages.empty()) { + // We could have a race condition here that two threads + // discover an empty map at the same time and want to fill + // it, but that is no problem, since the same contents is + // filled in twice then. Having the locker inside the + // packages.empty() condition has the advantage that we + // don't need the mutex overhead for simple reading. + static Mutex mutex; + Mutex::Locker locker(&mutex); + // adding a package here implies a file format change! + packages["amsmath"] = + N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas"); + packages["amssymb"] = + N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas"); + packages["cancel"] = + N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas"); + packages["esint"] = + N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas"); + packages["mathdots"] = + N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas"); + packages["mathtools"] = + N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas"); + packages["mhchem"] = + N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas"); + packages["stackrel"] = + N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas"); + packages["stmaryrd"] = + N_("The LaTeX package stmaryrd is only used if symbols from the St Mary's Road symbol font for theoretical computer science are inserted into formulas"); + packages["undertilde"] = + N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'"); + } + return packages; +} + + AuthorList & BufferParams::authors() { return pimpl_->authorlist; @@ -426,28 +522,28 @@ IndicesList const & BufferParams::indiceslist() const Bullet & BufferParams::temp_bullet(lyx::size_type const index) { - LASSERT(index < 4, /**/); + LASSERT(index < 4, return pimpl_->temp_bullets[0]); return pimpl_->temp_bullets[index]; } Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const { - LASSERT(index < 4, /**/); + LASSERT(index < 4, return pimpl_->temp_bullets[0]); return pimpl_->temp_bullets[index]; } Bullet & BufferParams::user_defined_bullet(lyx::size_type const index) { - LASSERT(index < 4, /**/); + LASSERT(index < 4, return pimpl_->temp_bullets[0]); return pimpl_->user_defined_bullets[index]; } Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const { - LASSERT(index < 4, /**/); + LASSERT(index < 4, return pimpl_->temp_bullets[0]); return pimpl_->user_defined_bullets[index]; } @@ -496,6 +592,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; } @@ -507,32 +605,43 @@ string BufferParams::readToken(Lexer & lex, string const & token, lex.next(); string const classname = lex.getString(); // if there exists a local layout file, ignore the system one - // NOTE: in this case, the textclass (.cls file) is assumed to be available. + // NOTE: in this case, the textclass (.cls file) is assumed to + // be available. string tcp; LayoutFileList & bcl = LayoutFileList::get(); - if (tcp.empty() && !filepath.empty()) - tcp = bcl.addLocalLayout(classname, filepath.absFilename()); + if (!filepath.empty()) + tcp = bcl.addLocalLayout(classname, filepath.absFileName()); + // that returns non-empty if a "local" layout file is found. if (!tcp.empty()) setBaseClass(tcp); else setBaseClass(classname); - // We assume that a tex class exists for local or unknown layouts so this warning - // will only be given for system layouts. + // 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 (Class Availability) of the\n" + "User's Guide for 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") { - readLocalLayout(lex); + readLocalLayout(lex, false); + } else if (token == "\\begin_forced_local_layout") { + readLocalLayout(lex, true); } else if (token == "\\begin_modules") { readModules(lex); } else if (token == "\\begin_removed_modules") { @@ -551,14 +660,19 @@ string BufferParams::readToken(Lexer & lex, string const & token, master = lex.getString(); } else if (token == "\\suppress_date") { lex >> suppress_date; + } else if (token == "\\justification") { + lex >> justification; } else if (token == "\\language") { readLanguage(lex); + } else if (token == "\\language_package") { + lex.eatLine(); + lang_package = lex.getString(); } else if (token == "\\inputencoding") { lex >> inputenc; } else if (token == "\\graphics") { readGraphicsDriver(lex); } else if (token == "\\default_output_format") { - lex >> defaultOutputFormat; + lex >> default_output_format; } else if (token == "\\bibtex_command") { lex.eatLine(); bibtex_command = lex.getString(); @@ -570,27 +684,30 @@ string BufferParams::readToken(Lexer & lex, string const & token, fontenc = lex.getString(); } else if (token == "\\font_roman") { lex.eatLine(); - fontsRoman = lex.getString(); + fonts_roman = lex.getString(); } else if (token == "\\font_sans") { lex.eatLine(); - fontsSans = lex.getString(); + fonts_sans = lex.getString(); } else if (token == "\\font_typewriter") { lex.eatLine(); - fontsTypewriter = lex.getString(); + fonts_typewriter = lex.getString(); + } else if (token == "\\font_math") { + lex.eatLine(); + fonts_math = lex.getString(); } else if (token == "\\font_default_family") { - lex >> fontsDefaultFamily; - } else if (token == "\\use_xetex") { - lex >> useXetex; + lex >> fonts_default_family; + } else if (token == "\\use_non_tex_fonts") { + lex >> useNonTeXFonts; } else if (token == "\\font_sc") { - lex >> fontsSC; + lex >> fonts_expert_sc; } else if (token == "\\font_osf") { - lex >> fontsOSF; + lex >> fonts_old_figures; } else if (token == "\\font_sf_scale") { - lex >> fontsSansScale; + lex >> fonts_sans_scale; } else if (token == "\\font_tt_scale") { - lex >> fontsTypewriterScale; + lex >> fonts_typewriter_scale; } else if (token == "\\font_cjk") { - lex >> fontsCJK; + lex >> fonts_cjk; } else if (token == "\\paragraph_separation") { string parsep; lex >> parsep; @@ -601,11 +718,11 @@ string BufferParams::readToken(Lexer & lex, string const & token, 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; @@ -616,30 +733,31 @@ string BufferParams::readToken(Lexer & lex, string const & token, papersize = papersizetranslator().find(ppsize); } else if (token == "\\use_geometry") { lex >> use_geometry; - } else if (token == "\\use_amsmath") { - int use_ams; - lex >> use_ams; - use_amsmath = packagetranslator().find(use_ams); - } else if (token == "\\use_esint") { - 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_package") { + string package; + int use; + lex >> package; + lex >> use; + use_package(package, packagetranslator().find(use)); } else if (token == "\\cite_engine") { - string engine; - lex >> engine; - cite_engine_ = citeenginetranslator().find(engine); + lex.eatLine(); + vector engine = getVectorFromString(lex.getString()); + setCiteEngine(engine); + } else if (token == "\\cite_engine_type") { + string engine_type; + lex >> engine_type; + cite_engine_type_ = citeenginetypetranslator().find(engine_type); + } else if (token == "\\biblio_style") { + lex.eatLine(); + biblio_style = lex.getString(); } else if (token == "\\use_bibtopic") { lex >> use_bibtopic; } else if (token == "\\use_indices") { lex >> use_indices; } else if (token == "\\tracking_changes") { - lex >> trackChanges; + lex >> track_changes; } else if (token == "\\output_changes") { - lex >> outputChanges; + lex >> output_changes; } else if (token == "\\branch") { lex.eatLine(); docstring branch = lex.getDocString(); @@ -658,7 +776,7 @@ string BufferParams::readToken(Lexer & lex, string const & token, if (tok == "\\filename_suffix") { lex.next(); if (branch_ptr) - branch_ptr->setFilenameSuffix(lex.getInteger()); + branch_ptr->setFileNameSuffix(lex.getInteger()); } if (tok == "\\color") { lex.eatLine(); @@ -707,7 +825,7 @@ string BufferParams::readToken(Lexer & lex, string const & token, istringstream ss(lex.getString()); Author a; ss >> a; - author_map[a.buffer_id()] = pimpl_->authorlist.record(a); + author_map[a.bufferId()] = pimpl_->authorlist.record(a); } else if (token == "\\paperorientation") { string orient; lex >> orient; @@ -715,6 +833,21 @@ string BufferParams::readToken(Lexer & lex, string const & token, } 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); + lcolor.setColor("notefontcolor", color); + } else if (token == "\\boxbgcolor") { + lex.eatLine(); + string color = lex.getString(); + boxbgcolor = lyx::rgbFromHexName(color); + lcolor.setColor("boxbgcolor", color); } else if (token == "\\paperwidth") { lex >> paperwidth; } else if (token == "\\paperheight") { @@ -775,12 +908,30 @@ string BufferParams::readToken(Lexer & lex, string const & token, toktmp << endl; return toktmp; } - } else if (token == "\\html_use_mathml") { - lex >> html_use_mathml; + } 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_css_as_file") { + lex >> html_css_as_file; + } 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: " << + lyxerr << "BufferParams::readToken(): Unknown token: " << token << endl; return token; } @@ -812,40 +963,40 @@ void BufferParams::writeFile(ostream & os) const } // use the class options defined in the layout? - os << "\\use_default_options " + os << "\\use_default_options " << convert(use_default_options) << "\n"; // the master document if (!master.empty()) { os << "\\master " << master << '\n'; } - + // removed modules - if (!removedModules_.empty()) { + if (!removed_modules_.empty()) { os << "\\begin_removed_modules" << '\n'; - list::const_iterator it = removedModules_.begin(); - list::const_iterator en = removedModules_.end(); - for (; it != en; it++) + list::const_iterator it = removed_modules_.begin(); + list::const_iterator en = removed_modules_.end(); + for (; it != en; ++it) os << *it << '\n'; os << "\\end_removed_modules" << '\n'; } // the modules - if (!layoutModules_.empty()) { + if (!layout_modules_.empty()) { os << "\\begin_modules" << '\n'; - LayoutModuleList::const_iterator it = layoutModules_.begin(); - LayoutModuleList::const_iterator en = layoutModules_.end(); - for (; it != en; it++) + LayoutModuleList::const_iterator it = layout_modules_.begin(); + LayoutModuleList::const_iterator en = layout_modules_.end(); + for (; it != en; ++it) os << *it << '\n'; os << "\\end_modules" << '\n'; } // includeonly - if (!includedChildren_.empty()) { + if (!included_children_.empty()) { os << "\\begin_includeonly" << '\n'; - list::const_iterator it = includedChildren_.begin(); - list::const_iterator en = includedChildren_.end(); - for (; it != en; it++) + list::const_iterator it = included_children_.begin(); + list::const_iterator en = included_children_.end(); + for (; it != en; ++it) os << *it << '\n'; os << "\\end_includeonly" << '\n'; } @@ -853,34 +1004,48 @@ void BufferParams::writeFile(ostream & os) const << convert(maintain_unincluded_children) << '\n'; // local layout information + string const local_layout = getLocalLayout(false); if (!local_layout.empty()) { - // remove '\n' from the end + // remove '\n' from the end string const tmplocal = rtrim(local_layout, "\n"); os << "\\begin_local_layout\n" << tmplocal << "\n\\end_local_layout\n"; } + string const forced_local_layout = getLocalLayout(true); + if (!forced_local_layout.empty()) { + // remove '\n' from the end + string const tmplocal = rtrim(forced_local_layout, "\n"); + os << "\\begin_forced_local_layout\n" + << tmplocal + << "\n\\end_forced_local_layout\n"; + } // then the text parameters if (language != ignore_language) os << "\\language " << language->lang() << '\n'; - os << "\\inputencoding " << inputenc + os << "\\language_package " << lang_package + << "\n\\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\\font_roman " << fonts_roman + << "\n\\font_sans " << fonts_sans + << "\n\\font_typewriter " << fonts_typewriter + << "\n\\font_math " << fonts_math + << "\n\\font_default_family " << fonts_default_family + << "\n\\use_non_tex_fonts " << convert(useNonTeXFonts) + << "\n\\font_sc " << convert(fonts_expert_sc) + << "\n\\font_osf " << convert(fonts_old_figures) + << "\n\\font_sf_scale " << fonts_sans_scale + << "\n\\font_tt_scale " << fonts_typewriter_scale << '\n'; - if (!fontsCJK.empty()) { - os << "\\font_cjk " << fontsCJK << '\n'; - } - os << "\n\\graphics " << graphicsDriver << '\n'; - os << "\\default_output_format " << defaultOutputFormat << '\n'; + if (!fonts_cjk.empty()) { + os << "\\font_cjk " << fonts_cjk << '\n'; + } + os << "\\graphics " << graphics_driver << '\n'; + os << "\\default_output_format " << default_output_format << '\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'; @@ -893,25 +1058,51 @@ void BufferParams::writeFile(ostream & os) const pdfoptions().writeFile(os); os << "\\papersize " << string_papersize[papersize] - << "\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_geometry " << convert(use_geometry); + map const & packages = auto_packages(); + for (map::const_iterator it = packages.begin(); + it != packages.end(); ++it) + os << "\n\\use_package " << it->first << ' ' + << use_package(it->first); + + os << "\n\\cite_engine "; + + if (!cite_engine_.empty()) { + LayoutModuleList::const_iterator be = cite_engine_.begin(); + LayoutModuleList::const_iterator en = cite_engine_.end(); + for (LayoutModuleList::const_iterator it = be; it != en; ++it) { + if (it != be) + os << ','; + os << *it; + } + } else { + os << "basic"; + } + + os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_) + << "\n\\biblio_style " << biblio_style << "\n\\use_bibtopic " << convert(use_bibtopic) << "\n\\use_indices " << convert(use_indices) << "\n\\paperorientation " << string_orientation[orientation] << "\n\\suppress_date " << convert(suppress_date) + << "\n\\justification " << convert(justification) + << "\n\\use_refstyle " << use_refstyle << '\n'; - if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) + 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\\filename_suffix " << it->hasFileNameSuffix() << "\n\\color " << lyx::X11hexname(it->color()) << "\n\\end_branch" << "\n"; @@ -955,7 +1146,7 @@ void BufferParams::writeFile(ostream & os) const os << "\\footskip " << VSpace(footskip).asLyXCommand() << '\n'; if (!columnsep.empty()) - os << "\\columnsep " + os << "\\columnsep " << VSpace(columnsep).asLyXCommand() << '\n'; os << "\\secnumdepth " << secnumdepth << "\n\\tocdepth " << tocdepth @@ -990,10 +1181,18 @@ void BufferParams::writeFile(ostream & os) const } } - 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"; + os << "\\tracking_changes " << convert(track_changes) << '\n' + << "\\output_changes " << convert(output_changes) << '\n' + << "\\html_math_output " << html_math_output << '\n' + << "\\html_css_as_file " << html_css_as_file << '\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'; os << pimpl_->authorlist; } @@ -1003,13 +1202,17 @@ void BufferParams::validate(LaTeXFeatures & features) const { features.require(documentClass().requires()); - if (outputChanges) { + if (columns > 1 && language->rightToLeft()) + features.require("rtloutputdblcol"); + + if (output_changes) { bool dvipost = LaTeXFeatures::isAvailable("dvipost"); bool xcolorulem = LaTeXFeatures::isAvailable("ulem") && LaTeXFeatures::isAvailable("xcolor"); switch (features.runparams().flavor) { case OutputParams::LATEX: + case OutputParams::DVILUATEX: if (dvipost) { features.require("ct-dvipost"); features.require("dvipost"); @@ -1021,6 +1224,7 @@ void BufferParams::validate(LaTeXFeatures & features) const features.require("ct-none"); } break; + case OutputParams::LUATEX: case OutputParams::PDFLATEX: case OutputParams::XETEX: if (xcolorulem) { @@ -1028,7 +1232,7 @@ void BufferParams::validate(LaTeXFeatures & features) const features.require("ulem"); features.require("xcolor"); // improves color handling in PDF output - features.require("pdfcolmk"); + features.require("pdfcolmk"); } else { features.require("ct-none"); } @@ -1042,14 +1246,16 @@ void BufferParams::validate(LaTeXFeatures & features) const if (float_placement.find('H') != string::npos) features.require("float"); - // AMS Style is at document level - if (use_amsmath == package_on - || documentClass().provides("amsmath")) - features.require("amsmath"); - if (use_esint == package_on) - features.require("esint"); - if (use_mhchem == package_on) - features.require("mhchem"); + for (PackageMap::const_iterator it = use_packages.begin(); + it != use_packages.end(); ++it) { + if (it->first == "amsmath") { + // AMS Style is at document level + if (it->second == package_on || + features.isProvided("amsmath")) + features.require(it->first); + } else if (it->second == package_on) + features.require(it->first); + } // Document-level line spacing if (spacing().getSpace() != Spacing::Single && !spacing().isDefault()) @@ -1058,7 +1264,7 @@ void BufferParams::validate(LaTeXFeatures & features) const // the bullet shapes are buffer level not paragraph level // so they are tested here for (int i = 0; i < 4; ++i) { - if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i]) + if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i]) continue; int const font = user_defined_bullet(i).getFont(); if (font == 0) { @@ -1085,20 +1291,42 @@ void BufferParams::validate(LaTeXFeatures & features) const if (pdfoptions().colorlinks) features.require("color"); } + if (!listings_params.empty()) { + // 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"); + } + + // some languages are only available via polyglossia + if (features.runparams().flavor == OutputParams::XETEX + && (features.hasPolyglossiaExclusiveLanguages() + || useNonTeXFonts)) + features.require("polyglossia"); - if (useXetex) - features.require("xetex"); + if (useNonTeXFonts && fonts_math != "auto") + features.require("unicode-math"); - if (language->lang() == "vietnamese") - features.require("vietnamese"); - else if (language->lang() == "japanese") - features.require("japanese"); + if (!language->requires().empty()) + features.require(language->requires()); } -bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, - TexRow & texrow, FileName const & filepath) const +bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, + FileName const & filepath) const { + // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf + // !! To use the Fix-cm package, load it before \documentclass, and use the command + // \RequirePackage to do so, rather than the normal \usepackage + // Do not try to load any other package before the document class, unless you + // have a thorough understanding of the LATEX internals and know exactly what you + // are doing! + if (features.mustProvide("fix-cm")) + os << "\\RequirePackage{fix-cm}\n"; + os << "\\documentclass"; DocumentClass const & tclass = documentClass(); @@ -1111,11 +1339,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) { @@ -1138,9 +1370,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; } @@ -1177,33 +1431,18 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, features.useLanguage(default_language); ostringstream language_options; - bool const use_babel = features.useBabel(); - if (use_babel) { - language_options << features.getLanguages(); + bool const use_babel = features.useBabel() && !features.isProvided("babel"); + bool const use_polyglossia = features.usePolyglossia(); + bool const global = lyxrc.language_global_options; + if (use_babel || (use_polyglossia && global)) { + language_options << features.getBabelLanguages(); if (!language->babel().empty()) { if (!language_options.str().empty()) language_options << ','; language_options << language->babel(); } - // 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 && japan == string::npos - && latvian == string::npos && lithu == string::npos - && mongo == string::npos) + if (global && !features.needBabelLangOptions() + && !language_options.str().empty()) clsoptions << language_options.str() << ','; } @@ -1224,63 +1463,83 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, } os << '{' << from_ascii(tclass.latexname()) << "}\n"; - texrow.newline(); // end of \documentclass defs - if (useXetex) { + // if we use fontspec or newtxmath, we have to load the AMS packages here + string const ams = features.loadAMSPackages(); + bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1"); + bool const use_newtxmath = + theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getUsedPackage( + ot1, false, false) == "newtxmath"; + if ((useNonTeXFonts || use_newtxmath) && !ams.empty()) + os << from_ascii(ams); + + if (useNonTeXFonts) { os << "\\usepackage{fontspec}\n"; - texrow.newline(); + if (features.mustProvide("unicode-math") + && features.isAvailable("unicode-math")) + os << "\\usepackage{unicode-math}\n"; } // font selection must be done before loading fontenc.sty - string const fonts = - loadFonts(fontsRoman, fontsSans, - fontsTypewriter, fontsSC, fontsOSF, - fontsSansScale, fontsTypewriterScale, useXetex); - if (!fonts.empty()) { - os << from_ascii(fonts); - texrow.newline(); - } - if (fontsDefaultFamily != "default") + string const fonts = loadFonts(features); + if (!fonts.empty()) + os << from_utf8(fonts); + + if (fonts_default_family != "default") os << "\\renewcommand{\\familydefault}{\\" - << from_ascii(fontsDefaultFamily) << "}\n"; + << from_ascii(fonts_default_family) << "}\n"; // set font encoding // for arabic_arabi and farsi we also need to load the LAE and // LFE encoding - // XeTeX works without fontenc + // XeTeX and LuaTeX (with OS fonts) work without fontenc if (font_encoding() != "default" && language->lang() != "japanese" - && !useXetex) { + && !useNonTeXFonts && !features.isProvided("fontenc")) { + docstring extra_encoding; + if (features.mustProvide("textgreek")) + extra_encoding += from_ascii("LGR"); + if (features.mustProvide("textcyr")) { + if (!extra_encoding.empty()) + extra_encoding.push_back(','); + extra_encoding += from_ascii("T2A"); + } + if (!extra_encoding.empty() && !font_encoding().empty()) + extra_encoding.push_back(','); + 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(font_encoding()) + || language->lang() == "farsi" || fars != string::npos + || arab != string::npos) { + os << "\\usepackage[" << extra_encoding + << from_ascii(font_encoding()) << ",LFE,LAE]{fontenc}\n"; - texrow.newline(); } else { - os << "\\usepackage[" << from_ascii(font_encoding()) + os << "\\usepackage[" << extra_encoding + << from_ascii(font_encoding()) << "]{fontenc}\n"; - texrow.newline(); } } // handle inputenc etc. - writeEncodingPreamble(os, features, texrow); + writeEncodingPreamble(os, features); // includeonly - if (!features.runparams().includeall && !includedChildren_.empty()) { + if (!features.runparams().includeall && !included_children_.empty()) { os << "\\includeonly{"; - list::const_iterator it = includedChildren_.begin(); + list::const_iterator it = included_children_.begin(); + list::const_iterator en = included_children_.end(); bool first = true; - for (; it != includedChildren_.end() ; ++it) { + for (; it != en; ++it) { string incfile = *it; - FileName inc = makeAbsPath(incfile, filepath.absFilename()); - string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")). - mangledFilename(); + 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 + // \includeonly doesn't want an extension incfile = changeExtension(incfile, string()); - incfile = latex_path(incfile); + incfile = support::latex_path(incfile); if (!incfile.empty()) { if (!first) os << ","; @@ -1291,28 +1550,7 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, os << "}\n"; } - 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); - // 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') - texrow.newline(); - os << "}\n"; - texrow.newline(); - } - if (!tclass.provides("geometry") + if (!features.isProvided("geometry") && (use_geometry || nonstandard_papersize)) { odocstringstream ods; if (!getGraphicsDriver("geometry").empty()) @@ -1337,6 +1575,15 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, case PAPER_USEXECUTIVE: ods << ",executivepaper"; break; + case PAPER_A0: + ods << ",a0paper"; + break; + case PAPER_A1: + ods << ",a1paper"; + break; + case PAPER_A2: + ods << ",a2paper"; + break; case PAPER_A3: ods << ",a3paper"; break; @@ -1346,6 +1593,18 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, case PAPER_A5: 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: ods << ",b3paper"; break; @@ -1355,98 +1614,120 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, case PAPER_B5: ods << ",b5paper"; break; - default: - // default papersize ie PAPER_DEFAULT - switch (lyxrc.default_papersize) { - case PAPER_DEFAULT: // keep compiler happy - case PAPER_USLETTER: - ods << ",letterpaper"; - break; - case PAPER_USLEGAL: - ods << ",legalpaper"; - break; - case PAPER_USEXECUTIVE: - ods << ",executivepaper"; - break; - case PAPER_A3: - ods << ",a3paper"; - break; - case PAPER_A4: - ods << ",a4paper"; - break; - case PAPER_A5: - ods << ",a5paper"; - break; - case PAPER_B5: - ods << ",b5paper"; - break; - case PAPER_B3: - case PAPER_B4: - case PAPER_CUSTOM: - 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; + case PAPER_DEFAULT: + 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()) - 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) { + // 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"; + } + } else if (orientation == ORIENTATION_LANDSCAPE + || papersize != PAPER_DEFAULT) { features.require("papersize"); } - if (tokenPos(tclass.opt_pagestyle(), - '|', pagestyle) >= 0) { - if (pagestyle == "fancy") { + if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) { + if (pagestyle == "fancy") os << "\\usepackage{fancyhdr}\n"; - texrow.newline(); - } os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n"; - texrow.newline(); } - // only output when the background color is not white - if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) { + // 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 + // 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()) { os << "\\setcounter{secnumdepth}{" << secnumdepth << "}\n"; - texrow.newline(); } if (tocdepth != tclass.tocdepth()) { os << "\\setcounter{tocdepth}{" << tocdepth << "}\n"; - texrow.newline(); } } @@ -1471,22 +1752,29 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, os << "\\setlength{\\parskip}{\\medskipamount}\n"; 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()) + << from_utf8(getIndentation().asLatexCommand()) << "}\n"; - texrow.newline(); } } // Now insert the LyX specific LaTeX commands... docstring lyxpreamble; + features.resolveAlternatives(); + + 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 @@ -1495,16 +1783,20 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, // 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 we use hyperref, jurabib, japanese, varioref or vietnamese, + // we have to call babel before 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'; + && (features.isRequired("jurabib") + || features.isRequired("hyperref") + || features.isRequired("varioref") + || features.isRequired("vietnamese") + || features.isRequired("japanese"))) { + // FIXME UNICODE + lyxpreamble += from_utf8(features.getBabelPresettings()); + lyxpreamble += from_utf8(babelCall(language_options.str(), + features.needBabelLangOptions())) + '\n'; + lyxpreamble += from_utf8(features.getBabelPostsettings()); } // The optional packages; @@ -1515,16 +1807,27 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, IndicesList::const_iterator iit = indiceslist().begin(); IndicesList::const_iterator iend = indiceslist().end(); for (; iit != iend; ++iit) { + pair indexname_latex = + features.runparams().encoding->latexString(iit->index(), + features.runparams().dryrun); + if (!indexname_latex.second.empty()) { + // issue a warning about omitted characters + // FIXME: should be passed to the error dialog + frontend::Alert::warning(_("Uncodable characters"), + bformat(_("The following characters that are used in an index name are not\n" + "representable in the current encoding and therefore have been omitted:\n%1$s."), + indexname_latex.second)); + } lyxpreamble += "\\newindex["; - lyxpreamble += iit->index(); + lyxpreamble += indexname_latex.first; lyxpreamble += "]{"; - lyxpreamble += iit->shortcut(); + lyxpreamble += escape(iit->shortcut()); lyxpreamble += "}\n"; } } // Line spacing - lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace"))); + lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace"))); // PDF support. // * Hyperref manual: "Make sure it comes last of your loaded @@ -1534,13 +1837,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 explicitly 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(); - } - + // pass what we have to stream here, since we need + // to access the stream itself in PDFOptions. + os << lyxpreamble; + + OutputParams tmp_params = features.runparams(); + pdfoptions().writeLaTeX(tmp_params, os, + features.isProvided("hyperref")); + // set back for the rest + lyxpreamble.clear(); + // correctly break URLs with hyperref and dvi output + if (features.runparams().flavor == OutputParams::LATEX + && features.isAvailable("breakurl")) + lyxpreamble += "\\usepackage{breakurl}\n"; + } else if (features.isRequired("nameref")) + // hyperref loads this automatically + lyxpreamble += "\\usepackage{nameref}\n"; + + // bibtopic needs to be loaded after hyperref. + // the dot provides the aux file naming which LyX can detect. + if (features.mustProvide("bibtopic")) + lyxpreamble += "\\usepackage[dot]{bibtopic}\n"; + // Will be surrounded by \makeatletter and \makeatother when not empty docstring atlyxpreamble; @@ -1572,6 +1892,13 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, "User specified LaTeX commands.\n" + from_utf8(preamble) + '\n'; + // footmisc must be loaded after setspace + // Load it here to avoid clashes with footmisc loaded in the user + // preamble. For that reason we also pass the options via + // \PassOptionsToPackage in getPreamble() and not here. + if (features.mustProvide("footmisc")) + atlyxpreamble += "\\usepackage{footmisc}\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 @@ -1628,37 +1955,74 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, + 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. + // Jurabib, hyperref, varioref and listings (bug 8995) have to be + // called after babel, though. if (use_babel && !features.isRequired("jurabib") && !features.isRequired("hyperref") + && !features.isRequired("varioref") && !features.isRequired("vietnamese") && !features.isRequired("japanese")) { // FIXME UNICODE - lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n'; - lyxpreamble += from_utf8(features.getBabelOptions()) + '\n'; + lyxpreamble += from_utf8(features.getBabelPresettings()); + lyxpreamble += from_utf8(babelCall(language_options.str(), + features.needBabelLangOptions())) + '\n'; + lyxpreamble += from_utf8(features.getBabelPostsettings()); + } + if (!listings_params.empty() || features.isRequired("listings")) + lyxpreamble += "\\usepackage{listings}\n"; + if (!listings_params.empty()) { + lyxpreamble += "\\lstset{"; + // do not test validity because listings_params is + // supposed to be valid + string par = + InsetListingsParams(listings_params).separatedParams(true); + lyxpreamble += from_utf8(par); + lyxpreamble += "}\n"; + } + + // xunicode needs to be loaded at least after amsmath, amssymb, + // esint and the other packages that provide special glyphs + if (features.runparams().flavor == OutputParams::XETEX + && useNonTeXFonts) + lyxpreamble += "\\usepackage{xunicode}\n"; + + // Polyglossia must be loaded last + if (use_polyglossia) { + // call the package + lyxpreamble += "\\usepackage{polyglossia}\n"; + // set the main language + lyxpreamble += "\\setdefaultlanguage"; + if (!language->polyglossiaOpts().empty()) + lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]"; + lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n"; + // now setup the other languages + std::map const polylangs = + features.getPolyglossiaLanguages(); + for (std::map::const_iterator mit = polylangs.begin(); + mit != polylangs.end() ; ++mit) { + lyxpreamble += "\\setotherlanguage"; + if (!mit->second.empty()) + lyxpreamble += "[" + from_ascii(mit->second) + "]"; + lyxpreamble += "{" + from_ascii(mit->first) + "}\n"; + } + } + + // Load custom language package here + if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) { + if (lang_package == "default") + lyxpreamble += from_utf8(lyxrc.language_custom_package); + else + lyxpreamble += from_utf8(lang_package); + lyxpreamble += '\n'; } - docstring const i18npreamble = features.getTClassI18nPreamble(use_babel); + docstring const i18npreamble = + features.getTClassI18nPreamble(use_babel, use_polyglossia); 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(); - } - 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; } @@ -1694,18 +2058,20 @@ bool BufferParams::hasClassDefaults() const DocumentClass const & BufferParams::documentClass() const { - return *doc_class_; + return *doc_class_.get(); } -DocumentClass const * BufferParams::documentClassPtr() const { +DocumentClassConstPtr BufferParams::documentClassPtr() const +{ return doc_class_; } -void BufferParams::setDocumentClass(DocumentClass const * const tc) { +void BufferParams::setDocumentClass(DocumentClassConstPtr tc) +{ // evil, but this function is evil - doc_class_ = const_cast(tc); + doc_class_ = const_pointer_cast(tc); } @@ -1714,11 +2080,12 @@ 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."), + docstring s = + 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); @@ -1726,15 +2093,19 @@ 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."), + docstring s = + 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; - layoutModules_.adaptToBaseClass(baseClass(), removedModules_); + layout_modules_.adaptToBaseClass(baseClass(), removed_modules_); return true; } @@ -1743,7 +2114,7 @@ LayoutFile const * BufferParams::baseClass() const { if (LayoutFileList::get().haveClass(pimpl_->baseClass_)) return &(LayoutFileList::get()[pimpl_->baseClass_]); - else + else return 0; } @@ -1754,52 +2125,275 @@ LayoutFileIndex const & BufferParams::baseClassID() const } -void BufferParams::makeDocumentClass() +void BufferParams::makeDocumentClass(bool const clone) { if (!baseClass()) return; - doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_)); + LayoutModuleList mods; + LayoutModuleList::iterator it = layout_modules_.begin(); + LayoutModuleList::iterator en = layout_modules_.end(); + for (; it != en; ++it) + mods.push_back(*it); - 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); - } + it = cite_engine_.begin(); + en = cite_engine_.end(); + for (; it != en; ++it) + mods.push_back(*it); + + doc_class_ = getDocumentClass(*baseClass(), mods, clone); + + TextClass::ReturnValues success = TextClass::OK; + if (!forced_local_layout_.empty()) + success = doc_class_->read(forced_local_layout_, TextClass::MODULE); + if (!local_layout_.empty() && + (success == TextClass::OK || success == TextClass::OK_OLDFORMAT)) + success = doc_class_->read(local_layout_, TextClass::MODULE); + if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) { + docstring const msg = _("Error reading internal layout information"); + frontend::Alert::warning(_("Read Error"), msg); } } -bool BufferParams::moduleCanBeAdded(string const & modName) const + +bool BufferParams::layoutModuleCanBeAdded(string const & modName) const +{ + return layout_modules_.moduleCanBeAdded(modName, baseClass()); +} + + +bool BufferParams::citationModuleCanBeAdded(string const & modName) const { - return layoutModules_.moduleCanBeAdded(modName, baseClass()); + return cite_engine_.moduleCanBeAdded(modName, baseClass()); +} + + +std::string BufferParams::getLocalLayout(bool forced) const +{ + if (forced) + return doc_class_->forcedLayouts(); + else + return local_layout_; +} + + +void BufferParams::setLocalLayout(string const & layout, bool forced) +{ + if (forced) + forced_local_layout_ = layout; + else + local_layout_ = layout; } bool BufferParams::addLayoutModule(string const & modName) { - LayoutModuleList::const_iterator it = layoutModules_.begin(); - LayoutModuleList::const_iterator end = layoutModules_.end(); - for (; it != end; it++) - if (*it == modName) + LayoutModuleList::const_iterator it = layout_modules_.begin(); + LayoutModuleList::const_iterator end = layout_modules_.end(); + for (; it != end; ++it) + if (*it == modName) return false; - layoutModules_.push_back(modName); + layout_modules_.push_back(modName); return true; } +string BufferParams::bufferFormat() const +{ + string format = documentClass().outputFormat(); + if (format == "latex") { + if (useNonTeXFonts) + return "xetex"; + if (encoding().package() == Encoding::japanese) + return "platex"; + } + return format; +} + + +bool BufferParams::isExportable(string const & format) const +{ + vector backs = backends(); + for (vector::const_iterator it = backs.begin(); + it != backs.end(); ++it) + if (theConverters().isReachable(*it, format)) + return true; + return false; +} + + +vector BufferParams::exportableFormats(bool only_viewable) const +{ + vector const backs = backends(); + set excludes; + if (useNonTeXFonts) { + excludes.insert("latex"); + excludes.insert("pdflatex"); + } + vector result = + theConverters().getReachable(backs[0], only_viewable, true, excludes); + for (vector::const_iterator it = backs.begin() + 1; + it != backs.end(); ++it) { + vector r = + theConverters().getReachable(*it, only_viewable, false, excludes); + result.insert(result.end(), r.begin(), r.end()); + } + return result; +} + + +bool BufferParams::isExportableFormat(string const & format) const +{ + typedef vector Formats; + Formats formats; + formats = exportableFormats(true); + Formats::const_iterator fit = formats.begin(); + Formats::const_iterator end = formats.end(); + for (; fit != end ; ++fit) { + if ((*fit)->name() == format) + return true; + } + return false; +} + + +vector BufferParams::backends() const +{ + vector v; + string const buffmt = bufferFormat(); + + // FIXME: Don't hardcode format names here, but use a flag + if (buffmt == "latex") { + if (!useNonTeXFonts) { + v.push_back("pdflatex"); + v.push_back("latex"); + } + v.push_back("luatex"); + v.push_back("dviluatex"); + v.push_back("xetex"); + } else if (buffmt == "xetex") { + v.push_back("xetex"); + // FIXME: need to test all languages (bug 8205) + if (!language || !language->isPolyglossiaExclusive()) { + v.push_back("luatex"); + v.push_back("dviluatex"); + } + } else + v.push_back(buffmt); + + v.push_back("xhtml"); + v.push_back("text"); + v.push_back("lyx"); + return v; +} + + +OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const +{ + string const dformat = (format.empty() || format == "default") ? + getDefaultOutputFormat() : format; + DefaultFlavorCache::const_iterator it = + default_flavors_.find(dformat); + + if (it != default_flavors_.end()) + return it->second; + + OutputParams::FLAVOR result = OutputParams::LATEX; + + // FIXME It'd be better not to hardcode this, but to do + // something with formats. + if (dformat == "xhtml") + result = OutputParams::HTML; + else if (dformat == "text") + result = OutputParams::TEXT; + else if (dformat == "lyx") + result = OutputParams::LYX; + else if (dformat == "pdflatex") + result = OutputParams::PDFLATEX; + else if (dformat == "xetex") + result = OutputParams::XETEX; + else if (dformat == "luatex") + result = OutputParams::LUATEX; + else if (dformat == "dviluatex") + result = OutputParams::DVILUATEX; + else { + // Try to determine flavor of default output format + vector backs = backends(); + if (find(backs.begin(), backs.end(), dformat) == backs.end()) { + // Get shortest path to format + Graph::EdgePath path; + for (vector::const_iterator it = backs.begin(); + it != backs.end(); ++it) { + Graph::EdgePath p = theConverters().getPath(*it, dformat); + if (!p.empty() && (path.empty() || p.size() < path.size())) { + path = p; + } + } + if (!path.empty()) + result = theConverters().getFlavor(path); + } + } + // cache this flavor + default_flavors_[dformat] = result; + return result; +} + + +string BufferParams::getDefaultOutputFormat() const +{ + if (!default_output_format.empty() + && default_output_format != "default") + return default_output_format; + if (isDocBook() + || encoding().package() == Encoding::japanese) { + vector const formats = exportableFormats(true); + if (formats.empty()) + return string(); + // return the first we find + return formats.front()->name(); + } + if (useNonTeXFonts) + return lyxrc.default_otf_view_format; + return lyxrc.default_view_format; +} + Font const BufferParams::getFont() const { FontInfo f = documentClass().defaultfont(); - if (fontsDefaultFamily == "rmdefault") + if (fonts_default_family == "rmdefault") f.setFamily(ROMAN_FAMILY); - else if (fontsDefaultFamily == "sfdefault") + else if (fonts_default_family == "sfdefault") f.setFamily(SANS_FAMILY); - else if (fontsDefaultFamily == "ttdefault") + else if (fonts_default_family == "ttdefault") f.setFamily(TYPEWRITER_FAMILY); return Font(f, language); } +InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const +{ + return quoteslangtranslator().find(qs); +} + + +bool BufferParams::isLatex() const +{ + return documentClass().outputType() == LATEX; +} + + +bool BufferParams::isLiterate() const +{ + return documentClass().outputType() == LITERATE; +} + + +bool BufferParams::isDocBook() const +{ + return documentClass().outputType() == DOCBOOK; +} + + void BufferParams::readPreamble(Lexer & lex) { if (lex.getString() != "\\begin_preamble") @@ -1810,13 +2404,31 @@ void BufferParams::readPreamble(Lexer & lex) } -void BufferParams::readLocalLayout(Lexer & lex) +void BufferParams::readLocalLayout(Lexer & lex, bool forced) { - if (lex.getString() != "\\begin_local_layout") + string const expected = forced ? "\\begin_forced_local_layout" : + "\\begin_local_layout"; + if (lex.getString() != expected) lyxerr << "Error (BufferParams::readLocalLayout):" "consistency check failed." << endl; - local_layout = lex.getLongString("\\end_local_layout"); + if (forced) + forced_local_layout_ = + lex.getLongString("\\end_forced_local_layout"); + else + local_layout_ = lex.getLongString("\\end_local_layout"); +} + + +bool BufferParams::setLanguage(string const & lang) +{ + Language const *new_language = languages.getLanguage(lang); + if (!new_language) { + // Language lang was not found + return false; + } + language = new_language; + return true; } @@ -1827,8 +2439,7 @@ void BufferParams::readLanguage(Lexer & lex) string const tmptok = lex.getString(); // check if tmptok is part of tex_babel in tex-defs.h - language = languages.getLanguage(tmptok); - if (!language) { + if (!setLanguage(tmptok)) { // Language tmptok was not found language = default_language; lyxerr << "Warning: Setting language `" @@ -1840,7 +2451,7 @@ void BufferParams::readLanguage(Lexer & lex) void BufferParams::readGraphicsDriver(Lexer & lex) { - if (!lex.next()) + if (!lex.next()) return; string const tmptok = lex.getString(); @@ -1850,14 +2461,14 @@ void BufferParams::readGraphicsDriver(Lexer & lex) string const test = tex_graphics[n++]; if (test == tmptok) { - graphicsDriver = tmptok; + graphics_driver = tmptok; break; } if (test.empty()) { lex.printError( "Warning: graphics driver `$$Token' not recognized!\n" " Setting graphics driver to `default'.\n"); - graphicsDriver = "default"; + graphics_driver = "default"; break; } } @@ -1866,7 +2477,7 @@ void BufferParams::readGraphicsDriver(Lexer & lex) void BufferParams::readBullets(Lexer & lex) { - if (!lex.next()) + if (!lex.next()) return; int const index = lex.getInteger(); @@ -1886,7 +2497,7 @@ void BufferParams::readBullets(Lexer & lex) void BufferParams::readBulletsLaTeX(Lexer & lex) { // The bullet class should be able to read this. - if (!lex.next()) + if (!lex.next()) return; int const index = lex.getInteger(); lex.next(true); @@ -1925,22 +2536,22 @@ void BufferParams::readRemovedModules(Lexer & lex) string mod = lex.getString(); if (mod == "\\end_removed_modules") break; - removedModules_.push_back(mod); + removed_modules_.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 + // 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(); + list::const_iterator rit = removed_modules_.begin(); + list::const_iterator const ren = removed_modules_.end(); + for (; rit != ren; ++rit) { + LayoutModuleList::iterator const mit = layout_modules_.begin(); + LayoutModuleList::iterator const men = layout_modules_.end(); LayoutModuleList::iterator found = find(mit, men, *rit); if (found == men) continue; - layoutModules_.erase(found); + layout_modules_.erase(found); } } @@ -1956,7 +2567,7 @@ void BufferParams::readIncludeonly(Lexer & lex) string child = lex.getString(); if (child == "\\end_includeonly") break; - includedChildren_.push_back(child); + included_children_.push_back(child); lex.eatLine(); } } @@ -1964,11 +2575,7 @@ void BufferParams::readIncludeonly(Lexer & lex) string BufferParams::paperSizeName(PapersizePurpose purpose) const { - char real_papersize = papersize; - if (real_papersize == PAPER_DEFAULT) - real_papersize = lyxrc.default_papersize; - - switch (real_papersize) { + switch (papersize) { case PAPER_DEFAULT: // could be anything, so don't guess return string(); @@ -1986,14 +2593,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"; @@ -2003,10 +2638,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) @@ -2027,6 +2721,14 @@ string const BufferParams::dvips_options() const { string result; + // If the class loads the geometry package, we do not know which + // paper size is used, since we do not set it (bug 7013). + // Therefore we must not specify any argument here. + // dvips gets the correct paper size via DVI specials in this case + // (if the class uses the geometry package correctly). + if (documentClass().provides("geometry")) + return result; + if (use_geometry && papersize == PAPER_CUSTOM && !lyxrc.print_paper_dimension_flag.empty() @@ -2060,36 +2762,19 @@ string const BufferParams::font_encoding() const } -string BufferParams::babelCall(string const & lang_opts) const +string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const { - string lang_pack = lyxrc.language_package; - if (lang_pack != "\\usepackage{babel}") - return lang_pack; - // suppress the babel call when there is no babel language defined + // suppress the babel call if there is no BabelName defined // for the document language in the lib/languages file and if no // other languages are used (lang_opts is then empty) if (lang_opts.empty()) return string(); - // 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 - // 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) + // either a specific language (AsBabelOptions setting in + // lib/languages) or the prefs require the languages to + // be submitted to babel itself (not the class). + if (langoptions) return "\\usepackage[" + lang_opts + "]{babel}"; - return lang_pack; + return "\\usepackage{babel}"; } @@ -2098,12 +2783,12 @@ 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") + if (graphics_driver == "dvips" + || graphics_driver == "dvipdfm" + || graphics_driver == "pdftex" + || graphics_driver == "vtex") + result = from_ascii(graphics_driver); + else if (graphics_driver == "dvipdfmx") result = from_ascii("dvipdfm"); } @@ -2111,11 +2796,23 @@ docstring BufferParams::getGraphicsDriver(string const & package) const } -void BufferParams::writeEncodingPreamble(odocstream & os, - LaTeXFeatures & features, TexRow & texrow) const +void BufferParams::writeEncodingPreamble(otexstream & os, + LaTeXFeatures & features) const { - if (useXetex) + // XeTeX does not need this + if (features.runparams().flavor == OutputParams::XETEX) return; + // LuaTeX neither, but with tex fonts, we need to load + // the luainputenc package. + if (features.runparams().flavor == OutputParams::LUATEX + || features.runparams().flavor == OutputParams::DVILUATEX) { + if (!useNonTeXFonts && inputenc != "default" + && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc) + || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) { + os << "\\usepackage[utf8]{luainputenc}\n"; + } + return; + } if (inputenc == "auto") { string const doc_encoding = language->encoding()->latexName(); @@ -2130,9 +2827,6 @@ void BufferParams::writeEncodingPreamble(odocstream & os, // 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 (package == Encoding::japanese) - features.require("japanese"); - if ((!encodings.empty() || package == Encoding::inputenc) && !features.isRequired("japanese")) { os << "\\usepackage["; @@ -2150,7 +2844,6 @@ void BufferParams::writeEncodingPreamble(odocstream & os, os << from_ascii(doc_encoding); } os << "]{inputenc}\n"; - texrow.newline(); } if (package == Encoding::CJK || features.mustProvide("CJK")) { if (language->encoding()->name() == "utf8-cjk" @@ -2158,7 +2851,6 @@ void BufferParams::writeEncodingPreamble(odocstream & os, os << "\\usepackage{CJKutf8}\n"; else os << "\\usepackage{CJK}\n"; - texrow.newline(); } } else if (inputenc != "default") { switch (encoding().package()) { @@ -2169,9 +2861,8 @@ void BufferParams::writeEncodingPreamble(odocstream & os, // do not load inputenc if japanese is used if (features.isRequired("japanese")) break; - os << "\\usepackage[" << from_ascii(inputenc) + os << "\\usepackage[" << from_ascii(encoding().latexName()) << "]{inputenc}\n"; - texrow.newline(); break; case Encoding::CJK: if (encoding().name() == "utf8-cjk" @@ -2179,17 +2870,17 @@ void BufferParams::writeEncodingPreamble(odocstream & os, os << "\\usepackage{CJKutf8}\n"; else os << "\\usepackage{CJK}\n"; - texrow.newline(); break; } - } - - // 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(); + // Load the CJK package if needed by a secondary language. + // If the main encoding is some variant of UTF8, use CJKutf8. + if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) { + if (encoding().iconvName() == "UTF-8" + && LaTeXFeatures::isAvailable("CJKutf8")) + os << "\\usepackage{CJKutf8}\n"; + else + os << "\\usepackage{CJK}\n"; + } } } @@ -2205,170 +2896,95 @@ string const BufferParams::parseFontName(string const & name) const } -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, - bool const & xetex) const +string const BufferParams::loadFonts(LaTeXFeatures & features) const { - /* The LaTeX font world is in a flux. In the PSNFSS font interface, - several packages have been replaced by others, that might not - be installed on every system. We have to take care for that - (see psnfss.pdf). We try to support all psnfss fonts as well - as the fonts that have become de facto standard in the LaTeX - world (e.g. Latin Modern). We do not support obsolete fonts - (like PSLatex). In general, it should be possible to mix any - rm font with any sf or tt font, respectively. (JSpitzm) - TODO: - -- separate math fonts. - */ - - if (rm == "default" && sf == "default" && tt == "default") + if (fonts_roman == "default" && fonts_sans == "default" + && fonts_typewriter == "default" + && (fonts_math == "default" || fonts_math == "auto")) //nothing to do return string(); 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]{" + /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle + * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/ + * Mapping=tex-text option assures TeX ligatures (such as "--") + * are resolved. Note that tt does not use these ligatures. + * TODO: + * -- add more GUI options? + * -- add more fonts (fonts for other scripts) + * -- if there's a way to find out if a font really supports + * OldStyle, enable/disable the widget accordingly. + */ + if (useNonTeXFonts && features.isAvailable("fontspec")) { + // "Mapping=tex-text" and "Ligatures=TeX" are equivalent. + // However, until v.2 (2010/07/11) fontspec only knew + // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX" + // was introduced for both XeTeX and LuaTeX (LuaTeX + // didn't understand "Mapping=tex-text", while XeTeX + // understood both. With most recent versions, both + // variants are understood by both engines. However, + // we want to provide support for at least TeXLive 2009 + // (for XeTeX; LuaTeX is only supported as of v.2) + string const texmapping = + (features.runparams().flavor == OutputParams::XETEX) ? + "Mapping=tex-text" : "Ligatures=TeX"; + if (fonts_roman != "default") { + os << "\\setmainfont[" << texmapping; + if (fonts_old_figures) + os << ",Numbers=OldStyle"; + os << "]{" << parseFontName(fonts_roman) << "}\n"; + } + if (fonts_sans != "default") { + string const sans = parseFontName(fonts_sans); + if (fonts_sans_scale != 100) + os << "\\setsansfont[Scale=" + << float(fonts_sans_scale) / 100 + << "," << texmapping << "]{" << sans << "}\n"; else - os << "\\setsansfont[Mapping=tex-text]{" + os << "\\setsansfont[" << texmapping << "]{" << sans << "}\n"; } - if (tt != "default") { - string const mono = parseFontName(tt); - if (ttscale != 100) - os << "\\setmonofont[Scale=" - << float(sfscale) / 100 + if (fonts_typewriter != "default") { + string const mono = parseFontName(fonts_typewriter); + if (fonts_typewriter_scale != 100) + os << "\\setmonofont[Scale=" + << float(fonts_typewriter_scale) / 100 << "]{" << mono << "}\n"; else - os << "\\setmonofont[Mapping=tex-text]{" + os << "\\setmonofont{" << mono << "}\n"; } - if (osf) - os << "\\defaultfontfeatures{Numbers=OldStyle}\n"; return os.str(); } + // Tex Fonts + bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1"); + bool const dryrun = features.runparams().dryrun; + bool const complete = (fonts_sans == "default" && fonts_typewriter == "default"); + bool const nomath = (fonts_math == "default"); + // ROMAN FONTS - // Computer Modern (must be explicitly selectable -- there might be classes - // that define a different default font! - if (rm == "cmr") { - os << "\\renewcommand{\\rmdefault}{cmr}\n"; - // osf for Computer Modern needs eco.sty - if (osf) - os << "\\usepackage{eco}\n"; - } - // Latin Modern Roman - else if (rm == "lmodern") - os << "\\usepackage{lmodern}\n"; - // AE - else if (rm == "ae") { - // not needed when using OT1 font encoding. - if (font_encoding() != "default") - os << "\\usepackage{ae,aecompl}\n"; - } - // Times - else if (rm == "times") { - // try to load the best available package - if (LaTeXFeatures::isAvailable("mathptmx")) - os << "\\usepackage{mathptmx}\n"; - else if (LaTeXFeatures::isAvailable("mathptm")) - os << "\\usepackage{mathptm}\n"; - else - os << "\\usepackage{times}\n"; - } - // Palatino - else if (rm == "palatino") { - // try to load the best available package - if (LaTeXFeatures::isAvailable("mathpazo")) { - os << "\\usepackage"; - if (osf || sc) { - os << '['; - if (!osf) - os << "sc"; - else - // "osf" includes "sc"! - os << "osf"; - os << ']'; - } - os << "{mathpazo}\n"; - } - else if (LaTeXFeatures::isAvailable("mathpple")) - os << "\\usepackage{mathpple}\n"; - else - os << "\\usepackage{palatino}\n"; - } - // Utopia - else if (rm == "utopia") { - // fourier supersedes utopia.sty, but does - // not work with OT1 encoding. - if (LaTeXFeatures::isAvailable("fourier") - && font_encoding() != "default") { - os << "\\usepackage"; - if (osf || sc) { - os << '['; - if (sc) - os << "expert"; - if (osf && sc) - os << ','; - if (osf) - os << "oldstyle"; - os << ']'; - } - os << "{fourier}\n"; - } - else - os << "\\usepackage{utopia}\n"; - } - // Bera (complete fontset) - else if (rm == "bera" && sf == "default" && tt == "default") - os << "\\usepackage{bera}\n"; - // everything else - else if (rm != "default") - os << "\\usepackage" << "{" << rm << "}\n"; + os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode( + dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, + nomath); // SANS SERIF - // Helvetica, Bera Sans - if (sf == "helvet" || sf == "berasans") { - if (sfscale != 100) - os << "\\usepackage[scaled=" << float(sfscale) / 100 - << "]{" << sf << "}\n"; - else - os << "\\usepackage{" << sf << "}\n"; - } - // Avant Garde - else if (sf == "avant") - os << "\\usepackage{" << sf << "}\n"; - // Computer Modern, Latin Modern, CM Bright - else if (sf != "default") - os << "\\renewcommand{\\sfdefault}{" << sf << "}\n"; - - // monospaced/typewriter - // Courier, LuxiMono - if (tt == "luximono" || tt == "beramono") { - if (ttscale != 100) - os << "\\usepackage[scaled=" << float(ttscale) / 100 - << "]{" << tt << "}\n"; - else - os << "\\usepackage{" << tt << "}\n"; - } - // Courier - else if (tt == "courier" ) - os << "\\usepackage{" << tt << "}\n"; - // Computer Modern, Latin Modern, CM Bright - else if (tt != "default") - os << "\\renewcommand{\\ttdefault}{" << tt << "}\n"; + os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode( + dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, + nomath, fonts_sans_scale); + + // MONOSPACED/TYPEWRITER + os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode( + dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, + nomath, fonts_typewriter_scale); + + // MATH + os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode( + dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, + nomath); return os.str(); } @@ -2376,11 +2992,15 @@ string const BufferParams::loadFonts(string const & rm, Encoding const & BufferParams::encoding() const { - if (useXetex) - return *(encodings.fromLaTeXName("utf8-plain")); + // FIXME: actually, we should check for the flavor + // or runparams.isFullyUnicode() here: + // This check will not work with XeTeX/LuaTeX and tex fonts. + // Thus we have to reset the encoding in Buffer::makeLaTeXFile. + if (useNonTeXFonts) + return *(encodings.fromLyXName("utf8-plain")); if (inputenc == "auto" || inputenc == "default") return *language->encoding(); - Encoding const * const enc = encodings.fromLaTeXName(inputenc); + Encoding const * const enc = encodings.fromLyXName(inputenc); if (enc) return *enc; LYXERR0("Unknown inputenc value `" << inputenc @@ -2389,20 +3009,75 @@ Encoding const & BufferParams::encoding() const } -CiteEngine BufferParams::citeEngine() const +bool BufferParams::addCiteEngine(string const & engine) +{ + LayoutModuleList::const_iterator it = cite_engine_.begin(); + LayoutModuleList::const_iterator en = cite_engine_.end(); + for (; it != en; ++it) + if (*it == engine) + return false; + cite_engine_.push_back(engine); + return true; +} + + +bool BufferParams::addCiteEngine(vector const & engine) +{ + vector::const_iterator it = engine.begin(); + vector::const_iterator en = engine.end(); + bool ret = true; + for (; it != en; ++it) + if (!addCiteEngine(*it)) + ret = false; + return ret; +} + + +string const & BufferParams::defaultBiblioStyle() const +{ + return documentClass().defaultBiblioStyle(); +} + + +bool const & BufferParams::fullAuthorList() const +{ + return documentClass().fullAuthorList(); +} + + +void BufferParams::setCiteEngine(string const & engine) +{ + clearCiteEngine(); + addCiteEngine(engine); +} + + +void BufferParams::setCiteEngine(vector const & engine) +{ + clearCiteEngine(); + addCiteEngine(engine); +} + + +vector BufferParams::citeCommands() const { - // FIXME the class should provide the numerical/ - // authoryear choice - if (documentClass().provides("natbib") - && cite_engine_ != ENGINE_NATBIB_NUMERICAL) - return ENGINE_NATBIB_AUTHORYEAR; - return cite_engine_; + static CitationStyle const default_style; + vector commands = + documentClass().citeCommands(citeEngineType()); + if (commands.empty()) + commands.push_back(default_style.cmd); + return commands; } -void BufferParams::setCiteEngine(CiteEngine cite_engine) +vector BufferParams::citeStyles() const { - cite_engine_ = cite_engine; + static CitationStyle const default_style; + vector styles = + documentClass().citeStyles(citeEngineType()); + if (styles.empty()) + styles.push_back(default_style); + return styles; } } // namespace lyx