X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferParams.cpp;h=50870c57b2e826065de252e82530658e374b7e26;hb=e335c764b47f8154973be212b446d9c13972cdf3;hp=6ecc68abd9334a0549620d27436c05fa7c962a34;hpb=1d3a85fe37737b9f8de06f2e0299330908cb916d;p=lyx.git diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index 6ecc68abd9..50870c57b2 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -38,6 +38,7 @@ #include "LyXRC.h" #include "OutputParams.h" #include "Spacing.h" +#include "texstream.h" #include "TexRow.h" #include "VSpace.h" #include "PDFOptions.h" @@ -304,6 +305,35 @@ SpaceTranslator const & spacetranslator() return translator; } + +bool inSystemDir(FileName const & document_dir, string & system_dir) +{ + // A document is assumed to be in a system LyX directory (not + // necessarily the system directory of the running instance) + // if both "configure.py" and "chkconfig.ltx" are found in + // either document_dir/../ or document_dir/../../. + // If true, the system directory path is returned in system_dir + // with a trailing path separator. + + string const msg = "Checking whether document is in a system dir..."; + + string dir = document_dir.absFileName(); + + for (int i = 0; i < 2; ++i) { + dir = addPath(dir, ".."); + if (!fileSearch(dir, "configure.py").empty() && + !fileSearch(dir, "chkconfig.ltx").empty()) { + LYXERR(Debug::FILES, msg << " yes"); + system_dir = addPath(FileName(dir).realPath(), ""); + return true; + } + } + + LYXERR(Debug::FILES, msg << " no"); + system_dir = string(); + return false; +} + } // anon namespace @@ -325,11 +355,16 @@ public: VSpace defskip; PDFOptions pdfoptions; LayoutFileIndex baseClass_; + FormatList exportableFormatList; + FormatList viewableFormatList; + bool isViewCacheValid; + bool isExportCacheValid; }; BufferParams::Impl::Impl() - : defskip(VSpace::MEDSKIP), baseClass_(string("")) + : defskip(VSpace::MEDSKIP), baseClass_(string("")), + isViewCacheValid(false), isExportCacheValid(false) { // set initial author // FIXME UNICODE @@ -369,6 +404,7 @@ BufferParams::BufferParams() biblio_style = "plain"; use_bibtopic = false; use_indices = false; + save_transient_properties = true; track_changes = false; output_changes = false; use_default_options = true; @@ -387,6 +423,7 @@ BufferParams::BufferParams() fonts_math[1] = "auto"; fonts_default_family = "default"; useNonTeXFonts = false; + use_microtype = false; fonts_expert_sc = false; fonts_old_figures = false; fonts_sans_scale[0] = 100; @@ -429,6 +466,9 @@ BufferParams::BufferParams() output_sync = false; use_refstyle = true; + + // map current author + author_map_[pimpl_->authorlist.get(0).bufferId()] = 0; } @@ -504,6 +544,12 @@ AuthorList const & BufferParams::authors() const } +void BufferParams::addAuthor(Author a) +{ + author_map_[a.bufferId()] = pimpl_->authorlist.record(a); +} + + BranchList & BufferParams::branchlist() { return pimpl_->branchlist; @@ -664,13 +710,19 @@ string BufferParams::readToken(Lexer & lex, string const & token, frontend::Alert::warning(_("Document class not available"), msg, true); } + } else if (token == "\\save_transient_properties") { + lex >> save_transient_properties; } else if (token == "\\origin") { lex.eatLine(); origin = lex.getString(); string const sysdirprefix = "/systemlyxdir/"; if (prefixIs(origin, sysdirprefix)) { - origin.replace(0, sysdirprefix.length() - 1, - package().system_support().absFileName()); + string docsys; + if (inSystemDir(filepath, docsys)) + origin.replace(0, sysdirprefix.length() - 1, docsys); + else + origin.replace(0, sysdirprefix.length() - 1, + package().system_support().absFileName()); } } else if (token == "\\begin_preamble") { readPreamble(lex); @@ -759,6 +811,8 @@ string BufferParams::readToken(Lexer & lex, string const & token, lex >> fonts_typewriter_scale[1]; } else if (token == "\\font_cjk") { lex >> fonts_cjk; + } else if (token == "\\use_microtype") { + lex >> use_microtype; } else if (token == "\\paragraph_separation") { string parsep; lex >> parsep; @@ -876,7 +930,7 @@ string BufferParams::readToken(Lexer & lex, string const & token, istringstream ss(lex.getString()); Author a; ss >> a; - author_map[a.bufferId()] = pimpl_->authorlist.record(a); + addAuthor(a); } else if (token == "\\paperorientation") { string orient; lex >> orient; @@ -1006,12 +1060,21 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const // The top of the file is written by the buffer. // Prints out the buffer info into the .lyx file given by file - // the document directory - string filepath = buf->filePath(); - string const sysdir = package().system_support().absFileName(); - if (prefixIs(filepath, sysdir)) - filepath.replace(0, sysdir.length(), "/systemlyxdir/"); - else if (!lyxrc.save_origin) + os << "\\save_transient_properties " + << convert(save_transient_properties) << '\n'; + + // the document directory (must end with a path separator) + // realPath() is used to resolve symlinks, while addPath(..., "") + // ensures a trailing path separator. + string docsys; + string filepath = addPath(buf->fileName().onlyPath().realPath(), ""); + string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys + : addPath(package().system_support().realPath(), ""); + string const relpath = + to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir))); + if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath)) + filepath = addPath("/systemlyxdir", relpath); + else if (!save_transient_properties || !lyxrc.save_origin) filepath = "unavailable"; os << "\\origin " << quoteIfNeeded(filepath) << '\n'; @@ -1024,9 +1087,9 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const // then the preamble if (!preamble.empty()) { // remove '\n' from the end of preamble - string const tmppreamble = rtrim(preamble, "\n"); + docstring const tmppreamble = rtrim(preamble, "\n"); os << "\\begin_preamble\n" - << tmppreamble + << to_utf8(tmppreamble) << "\n\\end_preamble\n"; } @@ -1077,20 +1140,20 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const << convert(maintain_unincluded_children) << '\n'; // local layout information - string const local_layout = getLocalLayout(false); + docstring const local_layout = getLocalLayout(false); if (!local_layout.empty()) { // remove '\n' from the end - string const tmplocal = rtrim(local_layout, "\n"); + docstring const tmplocal = rtrim(local_layout, "\n"); os << "\\begin_local_layout\n" - << tmplocal + << to_utf8(tmplocal) << "\n\\end_local_layout\n"; } - string const forced_local_layout = getLocalLayout(true); + docstring const forced_local_layout = getLocalLayout(true); if (!forced_local_layout.empty()) { // remove '\n' from the end - string const tmplocal = rtrim(forced_local_layout, "\n"); + docstring const tmplocal = rtrim(forced_local_layout, "\n"); os << "\\begin_forced_local_layout\n" - << tmplocal + << to_utf8(tmplocal) << "\n\\end_forced_local_layout\n"; } @@ -1120,6 +1183,7 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const if (!fonts_cjk.empty()) { os << "\\font_cjk " << fonts_cjk << '\n'; } + os << "\\use_microtype " << convert(use_microtype) << '\n'; os << "\\graphics " << graphics_driver << '\n'; os << "\\default_output_format " << default_output_format << '\n'; os << "\\output_sync " << output_sync << '\n'; @@ -1260,9 +1324,15 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const } } - os << "\\tracking_changes " << convert(track_changes) << '\n' - << "\\output_changes " << convert(output_changes) << '\n' - << "\\html_math_output " << html_math_output << '\n' + os << "\\tracking_changes " + << (save_transient_properties ? convert(track_changes) : "false") + << '\n'; + + os << "\\output_changes " + << (save_transient_properties ? convert(output_changes) : "false") + << '\n'; + + os << "\\html_math_output " << html_math_output << '\n' << "\\html_css_as_file " << html_css_as_file << '\n' << "\\html_be_strict " << convert(html_be_strict) << '\n'; @@ -1381,14 +1451,14 @@ void BufferParams::validate(LaTeXFeatures & features) const } // some languages are only available via polyglossia - if ((features.runparams().flavor == OutputParams::XETEX - || features.runparams().flavor == OutputParams::LUATEX) - && (features.hasPolyglossiaExclusiveLanguages() - || useNonTeXFonts)) - features.require("polyglossia"); + if (features.hasPolyglossiaExclusiveLanguages()) + features.require("polyglossia"); if (useNonTeXFonts && fontsMath() != "auto") features.require("unicode-math"); + + if (use_microtype) + features.require("microtype"); if (!language->requires().empty()) features.require(language->requires()); @@ -1560,7 +1630,8 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, os << from_ascii(ams); if (useNonTeXFonts) { - os << "\\usepackage{fontspec}\n"; + if (!features.isProvided("fontspec")) + os << "\\usepackage{fontspec}\n"; if (features.mustProvide("unicode-math") && features.isAvailable("unicode-math")) os << "\\usepackage{unicode-math}\n"; @@ -1833,20 +1904,20 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, } // Now insert the LyX specific LaTeX commands... - docstring lyxpreamble; features.resolveAlternatives(); + features.expandMultiples(); if (output_sync) { if (!output_sync_macro.empty()) - lyxpreamble += from_utf8(output_sync_macro) +"\n"; + os << from_utf8(output_sync_macro) +"\n"; else if (features.runparams().flavor == OutputParams::LATEX) - lyxpreamble += "\\usepackage[active]{srcltx}\n"; + os << "\\usepackage[active]{srcltx}\n"; else if (features.runparams().flavor == OutputParams::PDFLATEX) - lyxpreamble += "\\synctex=-1\n"; + os << "\\synctex=-1\n"; } // The package options (via \PassOptionsToPackage) - lyxpreamble += from_ascii(features.getPackageOptions()); + os << from_ascii(features.getPackageOptions()); // due to interferences with babel and hyperref, the color package has to // be loaded (when it is not already loaded) before babel when hyperref @@ -1854,7 +1925,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, // 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()); + os << from_ascii(features.getColorOptions()); // If we use hyperref, jurabib, japanese, varioref or vietnamese, // we have to call babel before @@ -1864,15 +1935,15 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, || features.isRequired("varioref") || features.isRequired("vietnamese") || features.isRequired("japanese"))) { + os << features.getBabelPresettings(); // FIXME UNICODE - lyxpreamble += from_utf8(features.getBabelPresettings()); - lyxpreamble += from_utf8(babelCall(language_options.str(), - features.needBabelLangOptions())) + '\n'; - lyxpreamble += from_utf8(features.getBabelPostsettings()); + os << from_utf8(babelCall(language_options.str(), + features.needBabelLangOptions())) + '\n'; + os << features.getBabelPostsettings(); } // The optional packages; - lyxpreamble += from_ascii(features.getPackages()); + os << from_ascii(features.getPackages()); // Additional Indices if (features.isRequired("splitidx")) { @@ -1890,16 +1961,16 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, "representable in the current encoding and therefore have been omitted:\n%1$s."), indexname_latex.second)); } - lyxpreamble += "\\newindex["; - lyxpreamble += indexname_latex.first; - lyxpreamble += "]{"; - lyxpreamble += escape(iit->shortcut()); - lyxpreamble += "}\n"; + os << "\\newindex["; + os << indexname_latex.first; + os << "]{"; + os << escape(iit->shortcut()); + os << "}\n"; } } // Line spacing - lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace"))); + os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace"))); // PDF support. // * Hyperref manual: "Make sure it comes last of your loaded @@ -1911,66 +1982,62 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, // avoid errors with algorithm floats. // use hyperref explicitly if it is required if (features.isRequired("hyperref")) { - // 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"; + os << "\\usepackage{breakurl}\n"; } else if (features.isRequired("nameref")) // hyperref loads this automatically - lyxpreamble += "\\usepackage{nameref}\n"; + os << "\\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"; + os << "\\usepackage[dot]{bibtopic}\n"; // Will be surrounded by \makeatletter and \makeatother when not empty - docstring atlyxpreamble; + otexstringstream atlyxpreamble; // Some macros LyX will need - docstring tmppreamble(features.getMacros()); - - if (!tmppreamble.empty()) - atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " - "LyX specific LaTeX commands.\n" - + tmppreamble + '\n'; - + { + TexString tmppreamble = features.getMacros(); + if (!tmppreamble.str.empty()) + atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " + "LyX specific LaTeX commands.\n" + << move(tmppreamble) + << '\n'; + } // the text class specific preamble - tmppreamble = features.getTClassPreamble(); - if (!tmppreamble.empty()) - atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " - "Textclass specific LaTeX commands.\n" - + tmppreamble + '\n'; - + { + docstring tmppreamble = features.getTClassPreamble(); + if (!tmppreamble.empty()) + atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " + "Textclass specific LaTeX commands.\n" + << tmppreamble + << '\n'; + } // suppress date if selected // use \@ifundefined because we cannot be sure that every document class // has a \date command if (suppress_date) - atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n"; + atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n"; /* the user-defined preamble */ if (!containsOnly(preamble, " \n\t")) { // FIXME UNICODE - atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " - "User specified LaTeX commands.\n"; + atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " + "User specified LaTeX commands.\n"; // Check if the user preamble contains uncodable glyphs - docstring const u_preamble = from_utf8(preamble); odocstringstream user_preamble; docstring uncodable_glyphs; Encoding const * const enc = features.runparams().encoding; if (enc) { - for (size_t n = 0; n < u_preamble.size(); ++n) { - char_type c = u_preamble[n]; + for (size_t n = 0; n < preamble.size(); ++n) { + char_type c = preamble[n]; if (!enc->encodable(c)) { docstring const glyph(1, c); LYXERR0("Uncodable character '" @@ -1987,7 +2054,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, user_preamble.put(c); } } else - user_preamble << u_preamble; + user_preamble << preamble; // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs if (!features.runparams().dryrun && !uncodable_glyphs.empty()) { @@ -2005,7 +2072,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, "preamble code accordingly."), uncodable_glyphs)); } - atlyxpreamble += user_preamble.str() + '\n'; + atlyxpreamble << user_preamble.str() << '\n'; } // footmisc must be loaded after setspace @@ -2013,7 +2080,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, // preamble. For that reason we also pass the options via // \PassOptionsToPackage in getPreamble() and not here. if (features.mustProvide("footmisc")) - atlyxpreamble += "\\usepackage{footmisc}\n"; + atlyxpreamble << "\\usepackage{footmisc}\n"; // subfig loads internally the LaTeX package "caption". As // caption is a very popular package, users will load it in @@ -2025,11 +2092,10 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, // koma's own caption commands are used instead of caption. We // use \PassOptionsToPackage here because the user could have // already loaded subfig in the preamble. - if (features.isRequired("subfig")) { - atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n" - " \\PassOptionsToPackage{caption=false}{subfig}}\n" - "\\usepackage{subfig}\n"; - } + if (features.mustProvide("subfig")) + atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n" + " \\PassOptionsToPackage{caption=false}{subfig}}\n" + "\\usepackage{subfig}\n"; // Itemize bullet settings need to be last in case the user // defines their own bullets that use a package included @@ -2064,11 +2130,12 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, } if (!bullets_def.empty()) - atlyxpreamble += bullets_def + "}\n\n"; + atlyxpreamble << bullets_def << "}\n\n"; if (!atlyxpreamble.empty()) - lyxpreamble += "\n\\makeatletter\n" - + atlyxpreamble + "\\makeatother\n\n"; + os << "\n\\makeatletter\n" + << atlyxpreamble.release() + << "\\makeatother\n\n"; // We try to load babel late, in case it interferes with other packages. // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be @@ -2078,68 +2145,67 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, && !features.isRequired("varioref") && !features.isRequired("vietnamese") && !features.isRequired("japanese")) { + os << features.getBabelPresettings(); // FIXME UNICODE - lyxpreamble += from_utf8(features.getBabelPresettings()); - lyxpreamble += from_utf8(babelCall(language_options.str(), - features.needBabelLangOptions())) + '\n'; - lyxpreamble += from_utf8(features.getBabelPostsettings()); + os << from_utf8(babelCall(language_options.str(), + features.needBabelLangOptions())) + '\n'; + os << features.getBabelPostsettings(); } if (features.isRequired("bicaption")) - lyxpreamble += "\\usepackage{bicaption}\n"; - if (!listings_params.empty() || features.isRequired("listings")) - lyxpreamble += "\\usepackage{listings}\n"; + os << "\\usepackage{bicaption}\n"; + if (!listings_params.empty() || features.mustProvide("listings")) + os << "\\usepackage{listings}\n"; if (!listings_params.empty()) { - lyxpreamble += "\\lstset{"; + os << "\\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"; + os << from_utf8(par); + os << "}\n"; } // xunicode needs to be loaded at least after amsmath, amssymb, // esint and the other packages that provide special glyphs + // The package only supports XeTeX currently. if (features.runparams().flavor == OutputParams::XETEX && useNonTeXFonts) - lyxpreamble += "\\usepackage{xunicode}\n"; + os << "\\usepackage{xunicode}\n"; // Polyglossia must be loaded last if (use_polyglossia) { // call the package - lyxpreamble += "\\usepackage{polyglossia}\n"; + os << "\\usepackage{polyglossia}\n"; // set the main language - lyxpreamble += "\\setdefaultlanguage"; + os << "\\setdefaultlanguage"; if (!language->polyglossiaOpts().empty()) - lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]"; - lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n"; + os << "[" << from_ascii(language->polyglossiaOpts()) << "]"; + os << "{" << 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"; + os << "\\setotherlanguage"; if (!mit->second.empty()) - lyxpreamble += "[" + from_ascii(mit->second) + "]"; - lyxpreamble += "{" + from_ascii(mit->first) + "}\n"; + os << "[" << from_ascii(mit->second) << "]"; + os << "{" << 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); + os << from_utf8(lyxrc.language_custom_package); else - lyxpreamble += from_utf8(lang_package); - lyxpreamble += '\n'; + os << from_utf8(lang_package); + os << '\n'; } docstring const i18npreamble = features.getTClassI18nPreamble(use_babel, use_polyglossia); if (!i18npreamble.empty()) - lyxpreamble += i18npreamble + '\n'; - - os << lyxpreamble; + os << i18npreamble + '\n'; return use_babel; } @@ -2176,7 +2242,7 @@ bool BufferParams::hasClassDefaults() const DocumentClass const & BufferParams::documentClass() const { - return *doc_class_.get(); + return *doc_class_; } @@ -2190,6 +2256,7 @@ void BufferParams::setDocumentClass(DocumentClassConstPtr tc) { // evil, but this function is evil doc_class_ = const_pointer_cast(tc); + invalidateConverterCache(); } @@ -2248,6 +2315,7 @@ void BufferParams::makeDocumentClass(bool const clone) if (!baseClass()) return; + invalidateConverterCache(); LayoutModuleList mods; LayoutModuleList::iterator it = layout_modules_.begin(); LayoutModuleList::iterator en = layout_modules_.end(); @@ -2263,10 +2331,11 @@ void BufferParams::makeDocumentClass(bool const clone) TextClass::ReturnValues success = TextClass::OK; if (!forced_local_layout_.empty()) - success = doc_class_->read(forced_local_layout_, TextClass::MODULE); + success = doc_class_->read(to_utf8(forced_local_layout_), + TextClass::MODULE); if (!local_layout_.empty() && (success == TextClass::OK || success == TextClass::OK_OLDFORMAT)) - success = doc_class_->read(local_layout_, TextClass::MODULE); + success = doc_class_->read(to_utf8(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); @@ -2286,16 +2355,16 @@ bool BufferParams::citationModuleCanBeAdded(string const & modName) const } -std::string BufferParams::getLocalLayout(bool forced) const +docstring BufferParams::getLocalLayout(bool forced) const { if (forced) - return doc_class_->forcedLayouts(); + return from_utf8(doc_class_->forcedLayouts()); else return local_layout_; } -void BufferParams::setLocalLayout(string const & layout, bool forced) +void BufferParams::setLocalLayout(docstring const & layout, bool forced) { if (forced) forced_local_layout_ = layout; @@ -2318,60 +2387,50 @@ bool BufferParams::addLayoutModule(string const & modName) string BufferParams::bufferFormat() const { - string format = documentClass().outputFormat(); - if (format == "latex") { - if (useNonTeXFonts) - return "xetex"; // FIXME: why not "luatex"? - if (encoding().package() == Encoding::japanese) - return "platex"; - } - return format; + return documentClass().outputFormat(); } -bool BufferParams::isExportable(string const & format) const +bool BufferParams::isExportable(string const & format, bool need_viewable) const { - vector backs = backends(); - for (vector::const_iterator it = backs.begin(); - it != backs.end(); ++it) - if (theConverters().isReachable(*it, format)) + FormatList const & formats = exportableFormats(need_viewable); + FormatList::const_iterator fit = formats.begin(); + FormatList::const_iterator end = formats.end(); + for (; fit != end ; ++fit) { + if ((*fit)->name() == format) return true; + } return false; } -vector BufferParams::exportableFormats(bool only_viewable) const +FormatList const & BufferParams::exportableFormats(bool only_viewable) const { + FormatList & cached = only_viewable ? + pimpl_->viewableFormatList : pimpl_->exportableFormatList; + bool & valid = only_viewable ? + pimpl_->isViewCacheValid : pimpl_->isExportCacheValid; + if (valid) + return cached; + vector const backs = backends(); set excludes; if (useNonTeXFonts) { excludes.insert("latex"); excludes.insert("pdflatex"); } - vector result = + FormatList 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); + FormatList 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; + sort(result.begin(), result.end(), Format::formatSorter); + cached = result; + valid = true; + return cached; } @@ -2382,17 +2441,14 @@ vector BufferParams::backends() const // 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()) { + if (encoding().package() == Encoding::japanese) + v.push_back("platex"); + else { + if (!useNonTeXFonts) { + v.push_back("pdflatex"); + v.push_back("latex"); + } + v.push_back("xetex"); v.push_back("luatex"); v.push_back("dviluatex"); } @@ -2464,7 +2520,7 @@ string BufferParams::getDefaultOutputFormat() const return default_output_format; if (isDocBook() || encoding().package() == Encoding::japanese) { - vector const formats = exportableFormats(true); + FormatList const & formats = exportableFormats(true); if (formats.empty()) return string(); // return the first we find @@ -2518,7 +2574,7 @@ void BufferParams::readPreamble(Lexer & lex) lyxerr << "Error (BufferParams::readPreamble):" "consistency check failed." << endl; - preamble = lex.getLongString("\\end_preamble"); + preamble = lex.getLongString(from_ascii("\\end_preamble")); } @@ -2532,9 +2588,9 @@ void BufferParams::readLocalLayout(Lexer & lex, bool forced) if (forced) forced_local_layout_ = - lex.getLongString("\\end_forced_local_layout"); + lex.getLongString(from_ascii("\\end_forced_local_layout")); else - local_layout_ = lex.getLongString("\\end_local_layout"); + local_layout_ = lex.getLongString(from_ascii("\\end_local_layout")); } @@ -2941,15 +2997,13 @@ docstring BufferParams::getGraphicsDriver(string const & package) const void BufferParams::writeEncodingPreamble(otexstream & os, LaTeXFeatures & features) const { - // "inputenc" package not required with non-TeX fonts. - if (useNonTeXFonts) - return; - // "inputenc" fails with XeTeX (even in 8-bit compatiblitly mode) and with TeX fonts, - // (this is a bug in the "inputenc" package see #9740). - if (features.runparams().flavor == OutputParams::XETEX) + // XeTeX/LuaTeX: (see also #9740) + // With Unicode fonts we use utf8-plain without encoding package. + // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails. + // XeTeX must use ASCII encoding (see Buffer.cpp), + // for LuaTeX, we load "luainputenc" (see below). + if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX) return; - // For LuaTeX with TeX fonts, we can load - // the "luainputenc" package with the specified encoding(s) (see below). if (inputenc == "auto") { string const doc_encoding = @@ -2957,10 +3011,12 @@ void BufferParams::writeEncodingPreamble(otexstream & os, Encoding::Package const package = language->encoding()->package(); - // Create a list with all the input encodings used - // in the document - set encodings = - features.getEncodingSet(doc_encoding); + // Create list of inputenc options: + set encodings; + // luainputenc fails with more than one encoding + if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts + // list all input encodings used in the document + encodings = features.getEncodingSet(doc_encoding); // If the "japanese" package (i.e. pLaTeX) is used, // inputenc must be omitted. @@ -3141,11 +3197,13 @@ string const BufferParams::loadFonts(LaTeXFeatures & features) const Encoding const & BufferParams::encoding() const { - // FIXME: additionally, we must check for runparams().flavor == XeTeX - // or runparams.isFullUnicode() to care for the combination - // of XeTeX and TeX-fonts (see #9740). - // Currently, we reset the encoding in Buffer::makeLaTeXFile - // (for export) and Buffer::writeLaTeXSource (for preview). + // Main encoding for LaTeX output. + // + // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740). + // As the "flavor" is only known once export started, this + // cannot be handled here. Instead, runparams.encoding is set + // to ASCII in Buffer::makeLaTeXFile (for export) + // and Buffer::writeLaTeXSource (for preview). if (useNonTeXFonts) return *(encodings.fromLyXName("utf8-plain")); if (inputenc == "auto" || inputenc == "default") @@ -3230,4 +3288,10 @@ vector BufferParams::citeStyles() const return styles; } +void BufferParams::invalidateConverterCache() const +{ + pimpl_->isExportCacheValid = false; + pimpl_->isViewCacheValid = false; +} + } // namespace lyx