#include "Buffer.h"
#include "buffer_funcs.h"
#include "Bullet.h"
+#include "CiteEnginesList.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 "Length.h"
#include "ModuleList.h"
#include "Font.h"
#include "Lexer.h"
#include "LyXRC.h"
#include "OutputParams.h"
#include "Spacing.h"
+#include "texstream.h"
#include "TexRow.h"
#include "VSpace.h"
#include "PDFOptions.h"
};
-static char const * const string_quotes_language[] = {
- "english", "swedish", "german", "polish", "french", "danish", ""
+static char const * const string_quotes_style[] = {
+ "english", "swedish", "german", "polish", "swiss", "danish", "plain",
+ "british", "swedishg", "french", "frenchin", "russian", "cjk", "cjkangle", ""
};
}
-// Quotes language
-typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
+// Quotes style
+typedef Translator<string, InsetQuotesParams::QuoteStyle> QuotesStyleTranslator;
-QuotesLangTranslator const init_quoteslangtranslator()
+QuotesStyleTranslator const init_quotesstyletranslator()
{
- QuotesLangTranslator translator
- (string_quotes_language[0], InsetQuotes::EnglishQuotes);
- translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
- translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
- translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
- translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
- translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
+ QuotesStyleTranslator translator
+ (string_quotes_style[0], InsetQuotesParams::EnglishQuotes);
+ translator.addPair(string_quotes_style[1], InsetQuotesParams::SwedishQuotes);
+ translator.addPair(string_quotes_style[2], InsetQuotesParams::GermanQuotes);
+ translator.addPair(string_quotes_style[3], InsetQuotesParams::PolishQuotes);
+ translator.addPair(string_quotes_style[4], InsetQuotesParams::SwissQuotes);
+ translator.addPair(string_quotes_style[5], InsetQuotesParams::DanishQuotes);
+ translator.addPair(string_quotes_style[6], InsetQuotesParams::PlainQuotes);
+ translator.addPair(string_quotes_style[7], InsetQuotesParams::BritishQuotes);
+ translator.addPair(string_quotes_style[8], InsetQuotesParams::SwedishGQuotes);
+ translator.addPair(string_quotes_style[9], InsetQuotesParams::FrenchQuotes);
+ translator.addPair(string_quotes_style[10], InsetQuotesParams::FrenchINQuotes);
+ translator.addPair(string_quotes_style[11], InsetQuotesParams::RussianQuotes);
+ translator.addPair(string_quotes_style[12], InsetQuotesParams::CJKQuotes);
+ translator.addPair(string_quotes_style[13], InsetQuotesParams::CJKAngleQuotes);
return translator;
}
-QuotesLangTranslator const & quoteslangtranslator()
+QuotesStyleTranslator const & quotesstyletranslator()
{
- static QuotesLangTranslator const translator =
- init_quoteslangtranslator();
+ static QuotesStyleTranslator const translator =
+ init_quotesstyletranslator();
return translator;
}
}
-// Cite engine
-typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
-
-
-CiteEngineTypeTranslator const init_citeenginetypetranslator()
-{
- CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
- translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
- translator.addPair("default", ENGINE_TYPE_DEFAULT);
- return translator;
-}
-
-
-CiteEngineTypeTranslator const & citeenginetypetranslator()
-{
- static CiteEngineTypeTranslator const translator =
- init_citeenginetypetranslator();
- return translator;
-}
-
-
// Spacing
typedef Translator<string, Spacing::Space> SpaceTranslator;
return translator;
}
-} // anon namespace
+
+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;
+}
+
+} // namespace
class BufferParams::Impl
Bullet user_defined_bullets[4];
IndicesList indiceslist;
Spacing spacing;
+ Length parindent;
+ Length mathindent;
/** This is the amount of space used for paragraph_separation "skip",
* and for detached paragraphs in "indented" documents.
*/
- HSpace indentation;
VSpace defskip;
PDFOptions pdfoptions;
LayoutFileIndex baseClass_;
+ 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
cite_engine_type_ = ENGINE_TYPE_DEFAULT;
makeDocumentClass();
paragraph_separation = ParagraphIndentSeparation;
- quotes_language = InsetQuotes::EnglishQuotes;
+ is_math_indent = false;
+ math_numbering_side = DEFAULT;
+ quotes_style = InsetQuotesParams::EnglishQuotes;
+ dynamic_quotes = false;
fontsize = "default";
/* PaperLayout */
use_geometry = false;
biblio_style = "plain";
use_bibtopic = false;
+ multibib = string();
use_indices = false;
save_transient_properties = true;
track_changes = false;
fonts_math[1] = "auto";
fonts_default_family = "default";
useNonTeXFonts = false;
+ use_microtype = false;
+ use_dash_ligatures = true;
fonts_expert_sc = false;
fonts_old_figures = false;
fonts_sans_scale[0] = 100;
html_css_as_file = false;
display_pixel_ratio = 1.0;
+ shell_escape = false;
output_sync = false;
use_refstyle = true;
+ use_minted = false;
// map current author
author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
}
+bool BufferParams::useBibtopic() const
+{
+ if (useBiblatex())
+ return false;
+ return (use_bibtopic || (!multibib.empty() && multibib != "child"));
+}
+
+
AuthorList & BufferParams::authors()
{
return pimpl_->authorlist;
}
-HSpace const & BufferParams::getIndentation() const
+Length const & BufferParams::getMathIndent() const
+{
+ return pimpl_->mathindent;
+}
+
+
+void BufferParams::setMathIndent(Length const & indent)
{
- return pimpl_->indentation;
+ pimpl_->mathindent = indent;
}
-void BufferParams::setIndentation(HSpace const & indent)
+Length const & BufferParams::getParIndent() const
{
- pimpl_->indentation = indent;
+ return pimpl_->parindent;
+}
+
+
+void BufferParams::setParIndent(Length const & indent)
+{
+ pimpl_->parindent = indent;
}
}
+BufferParams::MathNumber BufferParams::getMathNumber() const
+{
+ if (math_numbering_side != DEFAULT)
+ return math_numbering_side;
+ // FIXME: do not hardcode language here
+ else if (language->lang() == "arabic_arabi"
+ || documentClass().provides("leqno"))
+ return LEFT;
+ else
+ return RIGHT;
+}
+
+
string BufferParams::readToken(Lexer & lex, string const & token,
FileName const & filepath)
{
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);
lex >> fonts_typewriter_scale[1];
} else if (token == "\\font_cjk") {
lex >> fonts_cjk;
+ } else if (token == "\\use_microtype") {
+ lex >> use_microtype;
+ } else if (token == "\\use_dash_ligatures") {
+ lex >> use_dash_ligatures;
} else if (token == "\\paragraph_separation") {
string parsep;
lex >> parsep;
paragraph_separation = parseptranslator().find(parsep);
} else if (token == "\\paragraph_indentation") {
lex.next();
- string indentation = lex.getString();
- pimpl_->indentation = HSpace(indentation);
+ string parindent = lex.getString();
+ if (parindent == "default")
+ pimpl_->parindent = Length();
+ else
+ pimpl_->parindent = Length(parindent);
} else if (token == "\\defskip") {
lex.next();
string const defskip = lex.getString();
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;
- quotes_language = quoteslangtranslator().find(quotes_lang);
+ } else if (token == "\\is_math_indent") {
+ lex >> is_math_indent;
+ } else if (token == "\\math_indentation") {
+ lex.next();
+ string mathindent = lex.getString();
+ if (mathindent == "default")
+ pimpl_->mathindent = Length();
+ else
+ pimpl_->mathindent = Length(mathindent);
+ } else if (token == "\\math_numbering_side") {
+ string tmp;
+ lex >> tmp;
+ if (tmp == "left")
+ math_numbering_side = LEFT;
+ else if (tmp == "right")
+ math_numbering_side = RIGHT;
+ else
+ math_numbering_side = DEFAULT;
+ } else if (token == "\\quotes_style") {
+ string qstyle;
+ lex >> qstyle;
+ quotes_style = quotesstyletranslator().find(qstyle);
+ } else if (token == "\\dynamic_quotes") {
+ lex >> dynamic_quotes;
} else if (token == "\\papersize") {
string ppsize;
lex >> ppsize;
} else if (token == "\\cite_engine_type") {
string engine_type;
lex >> engine_type;
- cite_engine_type_ = citeenginetypetranslator().find(engine_type);
+ cite_engine_type_ = theCiteEnginesList.getType(engine_type);
} else if (token == "\\biblio_style") {
lex.eatLine();
biblio_style = lex.getString();
+ } else if (token == "\\biblio_options") {
+ lex.eatLine();
+ biblio_opts = trim(lex.getString());
+ } else if (token == "\\biblatex_bibstyle") {
+ lex.eatLine();
+ biblatex_bibstyle = trim(lex.getString());
+ } else if (token == "\\biblatex_citestyle") {
+ lex.eatLine();
+ biblatex_citestyle = trim(lex.getString());
} else if (token == "\\use_bibtopic") {
lex >> use_bibtopic;
+ } else if (token == "\\multibib") {
+ lex >> multibib;
} else if (token == "\\use_indices") {
lex >> use_indices;
} else if (token == "\\tracking_changes") {
lex >> output_sync_macro;
} else if (token == "\\use_refstyle") {
lex >> use_refstyle;
+ } else if (token == "\\use_minted") {
+ lex >> use_minted;
} else {
lyxerr << "BufferParams::readToken(): Unknown token: " <<
token << endl;
return "\"" + str + "\"";
return str;
}
-}
+} // namespace
void BufferParams::writeFile(ostream & os, Buffer const * buf) const
// 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 = addPath(package().system_support().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 (!lyxrc.save_origin)
+ else if (!save_transient_properties || !lyxrc.save_origin)
filepath = "unavailable";
os << "\\origin " << quoteIfNeeded(filepath) << '\n';
// 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";
}
<< convert<string>(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";
}
if (!fonts_cjk.empty()) {
os << "\\font_cjk " << fonts_cjk << '\n';
}
+ os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
+ os << "\\use_dash_ligatures " << convert<string>(use_dash_ligatures) << '\n';
os << "\\graphics " << graphics_driver << '\n';
os << "\\default_output_format " << default_output_format << '\n';
os << "\\output_sync " << output_sync << '\n';
os << "basic";
}
- os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
- << "\n\\biblio_style " << biblio_style
- << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
+ os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_);
+
+ if (!biblio_style.empty())
+ os << "\n\\biblio_style " << biblio_style;
+ if (!biblio_opts.empty())
+ os << "\n\\biblio_options " << biblio_opts;
+ if (!biblatex_bibstyle.empty())
+ os << "\n\\biblatex_bibstyle " << biblatex_bibstyle;
+ if (!biblatex_citestyle.empty())
+ os << "\n\\biblatex_citestyle " << biblatex_citestyle;
+ if (!multibib.empty())
+ os << "\n\\multibib " << multibib;
+
+ os << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
<< "\n\\use_indices " << convert<string>(use_indices)
<< "\n\\paperorientation " << string_orientation[orientation]
<< "\n\\suppress_date " << convert<string>(suppress_date)
<< "\n\\justification " << convert<string>(justification)
<< "\n\\use_refstyle " << use_refstyle
+ << "\n\\use_minted " << use_minted
<< '\n';
if (isbackgroundcolor == true)
os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
<< "\n\\paragraph_separation "
<< string_paragraph_separation[paragraph_separation];
if (!paragraph_separation)
- os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
+ os << "\n\\paragraph_indentation "
+ << (getParIndent().empty() ? "default" : getParIndent().asString());
else
os << "\n\\defskip " << getDefSkip().asLyXCommand();
- os << "\n\\quotes_language "
- << string_quotes_language[quotes_language]
+ os << "\n\\is_math_indent " << is_math_indent;
+ if (is_math_indent)
+ os << "\n\\math_indentation "
+ << (getMathIndent().empty() ? "default" : getMathIndent().asString());
+ os << "\n\\math_numbering_side ";
+ switch(math_numbering_side) {
+ case LEFT:
+ os << "left";
+ break;
+ case RIGHT:
+ os << "right";
+ break;
+ case DEFAULT:
+ os << "default";
+ }
+ os << "\n\\quotes_style "
+ << string_quotes_style[quotes_style]
+ << "\n\\dynamic_quotes " << dynamic_quotes
<< "\n\\papercolumns " << columns
<< "\n\\papersides " << sides
<< "\n\\paperpagestyle " << pagestyle << '\n';
// some languages are only available via polyglossia
if (features.hasPolyglossiaExclusiveLanguages())
- features.require("polyglossia");
+ 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());
}
&& orientation == ORIENTATION_LANDSCAPE)
clsoptions << "landscape,";
+ if (is_math_indent)
+ clsoptions << "fleqn,";
+
+ switch(math_numbering_side) {
+ case LEFT:
+ clsoptions << "leqno,";
+ break;
+ case RIGHT:
+ clsoptions << "reqno,";
+ features.require("amsmath");
+ break;
+ case DEFAULT:
+ break;
+ }
+
// language should be a parameter to \documentclass
if (language->babel() == "hebrew"
&& default_language->babel() != "hebrew")
// 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 ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
bool const use_newtxmath =
theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
ot1, false, false) == "newtxmath";
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";
// set font encoding
// XeTeX and LuaTeX (with OS fonts) do not need fontenc
if (!useNonTeXFonts && !features.isProvided("fontenc")
- && font_encoding() != "default") {
+ && main_font_encoding() != "default") {
// get main font encodings
vector<string> fontencs = font_encodings();
// get font encodings of secondary languages
} else {
// when separation by indentation
// only output something when a width is given
- if (getIndentation().asLyXCommand() != "default") {
+ if (!getParIndent().empty()) {
os << "\\setlength{\\parindent}{"
- << from_utf8(getIndentation().asLatexCommand())
+ << from_utf8(getParIndent().asLatexString())
+ << "}\n";
+ }
+ }
+
+ if (is_math_indent) {
+ // when formula indentation
+ // only output something when it is not the default
+ if (!getMathIndent().empty()) {
+ os << "\\setlength{\\mathindent}{"
+ << from_utf8(getMathIndent().asString())
<< "}\n";
}
}
// 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
// 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,
+ // If we use hyperref, jurabib, japanese or varioref,
// we have to call babel before
if (use_babel
&& (features.isRequired("jurabib")
|| features.isRequired("hyperref")
|| 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")) {
IndicesList::const_iterator iit = indiceslist().begin();
IndicesList::const_iterator iend = indiceslist().end();
for (; iit != iend; ++iit) {
- pair<docstring, docstring> 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 += indexname_latex.first;
- lyxpreamble += "]{";
- lyxpreamble += escape(iit->shortcut());
- lyxpreamble += "}\n";
+ os << "\\newindex{";
+ 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
// 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 '"
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()) {
"preamble code accordingly."),
uncodable_glyphs));
}
- atlyxpreamble += user_preamble.str() + '\n';
+ atlyxpreamble << user_preamble.str() << '\n';
}
// footmisc must be loaded after setspace
// 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
// 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
}
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
// called after babel, though.
if (use_babel && !features.isRequired("jurabib")
&& !features.isRequired("hyperref")
- && !features.isRequired("varioref")
- && !features.isRequired("vietnamese")
+ && !features.isRequired("varioref")
&& !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")
+ || features.mustProvide("minted")) {
+ if (features.mustProvide("listings"))
+ os << "\\usepackage{listings}\n";
+ else
+ os << "\\usepackage{minted}\n";
+ }
if (!listings_params.empty()) {
- lyxpreamble += "\\lstset{";
+ if (features.mustProvide("listings"))
+ os << "\\lstset{";
+ else
+ os << "\\setminted{";
// 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,
+ // xunicode only needs to be loaded if tipa is used
+ // (the rest is obsoleted by the new TU encoding).
+ // It 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";
+ if (features.mustProvide("tipa") && useNonTeXFonts
+ && !features.isProvided("xunicode")) {
+ // The package officially only supports XeTeX, but also works
+ // with LuaTeX. Thus we work around its XeTeX test.
+ if (features.runparams().flavor != OutputParams::XETEX) {
+ os << "% Pretend to xunicode that we are XeTeX\n"
+ << "\\def\\XeTeXpicfile{}\n";
+ }
+ os << "\\usepackage{xunicode}\n";
+ }
- // Polyglossia must be loaded last
+ // 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<std::string, std::string> const polylangs =
+ set<string> const polylangs =
features.getPolyglossiaLanguages();
- for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
+ for (set<string>::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";
+ // We do not output the options here; they are output in
+ // the language switch commands. This is safer if multiple
+ // varieties are used.
+ if (*mit == language->polyglossia())
+ continue;
+ os << "\\setotherlanguage";
+ os << "{" << from_ascii(*mit) << "}\n";
+ }
+ }
+
+ // ... but before biblatex (see #7065)
+ if (features.mustProvide("biblatex")) {
+ string delim = "";
+ string opts;
+ os << "\\usepackage";
+ if (!biblatex_bibstyle.empty()
+ && (biblatex_bibstyle == biblatex_citestyle)) {
+ opts = "style=" + biblatex_bibstyle;
+ delim = ",";
+ } else {
+ if (!biblatex_bibstyle.empty()) {
+ opts = "bibstyle=" + biblatex_bibstyle;
+ delim = ",";
+ }
+ if (!biblatex_citestyle.empty()) {
+ opts += delim + "citestyle=" + biblatex_citestyle;
+ delim = ",";
+ }
+ }
+ if (!multibib.empty() && multibib != "child") {
+ opts += delim + "refsection=" + multibib;
+ delim = ",";
+ }
+ if (bibtexCommand() == "bibtex8"
+ || prefixIs(bibtexCommand(), "bibtex8 ")) {
+ opts += delim + "backend=bibtex8";
+ delim = ",";
+ } else if (bibtexCommand() == "bibtex"
+ || prefixIs(bibtexCommand(), "bibtex ")) {
+ opts += delim + "backend=bibtex";
+ delim = ",";
}
+ if (!biblio_opts.empty())
+ opts += delim + biblio_opts;
+ if (!opts.empty())
+ os << "[" << opts << "]";
+ os << "{biblatex}\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);
+ features.getTClassI18nPreamble(use_babel, use_polyglossia,
+ use_minted);
if (!i18npreamble.empty())
- lyxpreamble += i18npreamble + '\n';
-
- os << lyxpreamble;
+ os << i18npreamble + '\n';
return use_babel;
}
DocumentClass const & BufferParams::documentClass() const
{
- return *doc_class_.get();
+ return *doc_class_;
}
{
// evil, but this function is evil
doc_class_ = const_pointer_cast<DocumentClass>(tc);
+ invalidateConverterCache();
}
if (!baseClass())
return;
+ invalidateConverterCache();
LayoutModuleList mods;
+ LayoutModuleList ces;
LayoutModuleList::iterator it = layout_modules_.begin();
LayoutModuleList::iterator en = layout_modules_.end();
for (; it != en; ++it)
it = cite_engine_.begin();
en = cite_engine_.end();
for (; it != en; ++it)
- mods.push_back(*it);
+ ces.push_back(*it);
- doc_class_ = getDocumentClass(*baseClass(), mods, clone);
+ doc_class_ = getDocumentClass(*baseClass(), mods, ces, 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);
}
-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;
string BufferParams::bufferFormat() const
{
- string format = documentClass().outputFormat();
- if (format == "latex") {
- if (useNonTeXFonts)
- return "xetex"; // actually "xetex or 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<string> backs = backends();
- for (vector<string>::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<Format const *> 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<string> const backs = backends();
set<string> excludes;
if (useNonTeXFonts) {
excludes.insert("latex");
excludes.insert("pdflatex");
}
- vector<Format const *> result =
+ FormatList result =
theConverters().getReachable(backs[0], only_viewable, true, excludes);
for (vector<string>::const_iterator it = backs.begin() + 1;
it != backs.end(); ++it) {
- vector<Format const *> 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<Format const *> 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;
}
// 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");
}
- } else
- v.push_back(buffmt);
+ } else {
+ string rbuffmt = buffmt;
+ // If we use an OutputFormat in Japanese docs,
+ // we need special format in order to get the path
+ // via pLaTeX (#8823)
+ if (documentClass().hasOutputFormat()
+ && encoding().package() == Encoding::japanese)
+ rbuffmt += "-ja";
+ v.push_back(rbuffmt);
+ }
v.push_back("xhtml");
v.push_back("text");
if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
// Get shortest path to format
Graph::EdgePath path;
- for (vector<string>::const_iterator it = backs.begin();
- it != backs.end(); ++it) {
- Graph::EdgePath p = theConverters().getPath(*it, dformat);
+ for (auto const & bvar : backs) {
+ Graph::EdgePath p = theConverters().getPath(bvar, dformat);
if (!p.empty() && (path.empty() || p.size() < path.size())) {
path = p;
}
if (!default_output_format.empty()
&& default_output_format != "default")
return default_output_format;
- if (isDocBook()
- || encoding().package() == Encoding::japanese) {
- vector<Format const *> const formats = exportableFormats(true);
+ if (isDocBook()) {
+ FormatList const & formats = exportableFormats(true);
if (formats.empty())
return string();
// return the first we find
return formats.front()->name();
}
+ if (encoding().package() == Encoding::japanese)
+ return lyxrc.default_platex_view_format;
if (useNonTeXFonts)
return lyxrc.default_otf_view_format;
return lyxrc.default_view_format;
}
-InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
+InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
{
- return quoteslangtranslator().find(qs);
+ return quotesstyletranslator().find(qs);
}
lyxerr << "Error (BufferParams::readPreamble):"
"consistency check failed." << endl;
- preamble = lex.getLongString("\\end_preamble");
+ preamble = lex.getLongString(from_ascii("\\end_preamble"));
}
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"));
}
}
-string const BufferParams::font_encoding() const
+string const BufferParams::main_font_encoding() const
{
return font_encodings().empty() ? "default" : font_encodings().back();
}
// 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, for LuaTeX, we load
- // "luainputenc" (see below).
+ // XeTeX must use ASCII encoding (see Buffer.cpp),
+ // for LuaTeX, we load "luainputenc" (see below).
if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
return;
language->encoding()->package();
// Create list of inputenc options:
- set<string> encodings;
+ set<string> encoding_set;
// 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);
+ encoding_set = features.getEncodingSet(doc_encoding);
// 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 ((!encodings.empty() || package == Encoding::inputenc)
+ if ((!encoding_set.empty() || package == Encoding::inputenc)
&& !features.isRequired("japanese")
&& !features.isProvided("inputenc")) {
os << "\\usepackage[";
- set<string>::const_iterator it = encodings.begin();
- set<string>::const_iterator const end = encodings.end();
+ set<string>::const_iterator it = encoding_set.begin();
+ set<string>::const_iterator const end = encoding_set.end();
if (it != end) {
os << from_ascii(*it);
++it;
for (; it != end; ++it)
os << ',' << from_ascii(*it);
if (package == Encoding::inputenc) {
- if (!encodings.empty())
+ if (!encoding_set.empty())
os << ',';
os << from_ascii(doc_encoding);
}
}
// Tex Fonts
- bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
+ bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
bool const dryrun = features.runparams().dryrun;
bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
bool const nomath = (fontsMath() == "default");
Encoding const & BufferParams::encoding() const
{
// 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
string const & BufferParams::defaultBiblioStyle() const
{
- return documentClass().defaultBiblioStyle();
+ map<string, string> const & bs = documentClass().defaultBiblioStyle();
+ auto cit = bs.find(theCiteEnginesList.getTypeAsString(citeEngineType()));
+ if (cit != bs.end())
+ return cit->second;
+ else
+ return empty_string();
}
}
+string BufferParams::getCiteAlias(string const & s) const
+{
+ vector<string> commands =
+ documentClass().citeCommands(citeEngineType());
+ // If it is a real command, don't treat it as an alias
+ if (find(commands.begin(), commands.end(), s) != commands.end())
+ return string();
+ map<string,string> aliases = documentClass().citeCommandAliases();
+ if (aliases.find(s) != aliases.end())
+ return aliases[s];
+ return string();
+}
+
+
void BufferParams::setCiteEngine(string const & engine)
{
clearCiteEngine();
vector<string> commands =
documentClass().citeCommands(citeEngineType());
if (commands.empty())
- commands.push_back(default_style.cmd);
+ commands.push_back(default_style.name);
return commands;
}
return styles;
}
+
+string const BufferParams::bibtexCommand() const
+{
+ // Return document-specific setting if available
+ if (bibtex_command != "default")
+ return bibtex_command;
+
+ // If we have "default" in document settings, consult the prefs
+ // 1. Japanese (uses a specific processor)
+ if (encoding().package() == Encoding::japanese) {
+ if (lyxrc.jbibtex_command != "automatic")
+ // Return the specified program, if "automatic" is not set
+ return lyxrc.jbibtex_command;
+ else if (!useBiblatex()) {
+ // With classic BibTeX, return pbibtex, jbibtex, bibtex
+ if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end())
+ return "pbibtex";
+ if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end())
+ return "jbibtex";
+ return "bibtex";
+ }
+ }
+ // 2. All other languages
+ else if (lyxrc.bibtex_command != "automatic")
+ // Return the specified program, if "automatic" is not set
+ return lyxrc.bibtex_command;
+
+ // 3. Automatic: find the most suitable for the current cite framework
+ if (useBiblatex()) {
+ // For Biblatex, we prefer biber (also for Japanese)
+ // and fall back to bibtex8 and, as last resort, bibtex
+ if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end())
+ return "biber";
+ else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end())
+ return "bibtex8";
+ }
+ return "bibtex";
+}
+
+
+bool BufferParams::useBiblatex() const
+{
+ return theCiteEnginesList[citeEngine().list().front()]
+ ->getCiteFramework() == "biblatex";
+}
+
+
+void BufferParams::invalidateConverterCache() const
+{
+ pimpl_->isExportCacheValid = false;
+ pimpl_->isViewCacheValid = false;
+}
+
} // namespace lyx