lyx_mirror/src/BufferParams.cpp
Jürgen Spitzmüller a37190ee62 * BufferParams.{cpp,h}:
- go back to Maping=tex-text for XeTeX and use Ligatures=TeX only for LuaTeX.
	  This gets users of older distributions (such as TeXLive 2009) back into the XeTeX game.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@37402 a592a061-630c-0410-9148-cb99ea01b6c8
2011-02-01 14:00:23 +00:00

2811 lines
76 KiB
C++

/**
* \file BufferParams.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Alfredo Braunstein
* \author Lars Gullik Bjønnes
* \author Jean-Marc Lasgouttes
* \author John Levon
* \author André Pönitz
* \author Martin Vermeer
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "BufferParams.h"
#include "Author.h"
#include "LayoutFile.h"
#include "BranchList.h"
#include "buffer_funcs.h"
#include "Bullet.h"
#include "Color.h"
#include "ColorSet.h"
#include "Encoding.h"
#include "HSpace.h"
#include "IndicesList.h"
#include "Language.h"
#include "LaTeXFeatures.h"
#include "ModuleList.h"
#include "Font.h"
#include "Lexer.h"
#include "LyXRC.h"
#include "OutputParams.h"
#include "Spacing.h"
#include "TexRow.h"
#include "VSpace.h"
#include "PDFOptions.h"
#include "frontends/alert.h"
#include "insets/InsetListingsParams.h"
#include "support/convert.h"
#include "support/debug.h"
#include "support/docstream.h"
#include "support/FileName.h"
#include "support/filetools.h"
#include "support/gettext.h"
#include "support/Messages.h"
#include "support/Translator.h"
#include "support/lstrings.h"
#include <algorithm>
#include <sstream>
using namespace std;
using namespace lyx::support;
static char const * const string_paragraph_separation[] = {
"indent", "skip", ""
};
static char const * const string_quotes_language[] = {
"english", "swedish", "german", "polish", "french", "danish", ""
};
static char const * const string_papersize[] = {
"default", "custom", "letterpaper", "legalpaper", "executivepaper",
"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", ""
};
static char const * const string_orientation[] = {
"portrait", "landscape", ""
};
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",
"ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
"psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
"xetex", "none", ""
};
namespace lyx {
// Local translators
namespace {
// Paragraph separation
typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
ParSepTranslator const init_parseptranslator()
{
ParSepTranslator translator
(string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
return translator;
}
ParSepTranslator const & parseptranslator()
{
static ParSepTranslator translator = init_parseptranslator();
return translator;
}
// Quotes language
typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
QuotesLangTranslator const init_quoteslangtranslator()
{
QuotesLangTranslator translator
(string_quotes_language[0], InsetQuotes::EnglishQuotes);
translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
return translator;
}
QuotesLangTranslator const & quoteslangtranslator()
{
static QuotesLangTranslator translator = init_quoteslangtranslator();
return translator;
}
// Paper size
typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
static PaperSizeTranslator initPaperSizeTranslator()
{
PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
translator.addPair(string_papersize[1], PAPER_CUSTOM);
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_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();
return translator;
}
// Paper orientation
typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
PaperOrientationTranslator const init_paperorientationtranslator()
{
PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
return translator;
}
PaperOrientationTranslator const & paperorientationtranslator()
{
static PaperOrientationTranslator translator = init_paperorientationtranslator();
return translator;
}
// Page sides
typedef Translator<int, PageSides> SidesTranslator;
SidesTranslator const init_sidestranslator()
{
SidesTranslator translator(1, OneSide);
translator.addPair(2, TwoSides);
return translator;
}
SidesTranslator const & sidestranslator()
{
static SidesTranslator translator = init_sidestranslator();
return translator;
}
// LaTeX packages
typedef Translator<int, BufferParams::Package> PackageTranslator;
PackageTranslator const init_packagetranslator()
{
PackageTranslator translator(0, BufferParams::package_off);
translator.addPair(1, BufferParams::package_auto);
translator.addPair(2, BufferParams::package_on);
return translator;
}
PackageTranslator const & packagetranslator()
{
static PackageTranslator translator = init_packagetranslator();
return translator;
}
// Cite engine
typedef Translator<string, CiteEngine> CiteEngineTranslator;
CiteEngineTranslator const init_citeenginetranslator()
{
CiteEngineTranslator translator("basic", ENGINE_BASIC);
translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
translator.addPair("jurabib", ENGINE_JURABIB);
return translator;
}
CiteEngineTranslator const & citeenginetranslator()
{
static CiteEngineTranslator translator = init_citeenginetranslator();
return translator;
}
// Spacing
typedef Translator<string, Spacing::Space> SpaceTranslator;
SpaceTranslator const init_spacetranslator()
{
SpaceTranslator translator("default", Spacing::Default);
translator.addPair("single", Spacing::Single);
translator.addPair("onehalf", Spacing::Onehalf);
translator.addPair("double", Spacing::Double);
translator.addPair("other", Spacing::Other);
return translator;
}
SpaceTranslator const & spacetranslator()
{
static SpaceTranslator translator = init_spacetranslator();
return translator;
}
} // anon namespace
class BufferParams::Impl
{
public:
Impl();
AuthorList authorlist;
BranchList branchlist;
Bullet temp_bullets[4];
Bullet user_defined_bullets[4];
IndicesList indiceslist;
Spacing spacing;
/** This is the amount of space used for paragraph_separation "skip",
* and for detached paragraphs in "indented" documents.
*/
HSpace indentation;
VSpace defskip;
PDFOptions pdfoptions;
LayoutFileIndex baseClass_;
};
BufferParams::Impl::Impl()
: defskip(VSpace::MEDSKIP), baseClass_(string(""))
{
// set initial author
// FIXME UNICODE
authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
}
BufferParams::Impl *
BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
{
LASSERT(ptr, /**/);
return new BufferParams::Impl(*ptr);
}
void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
{
delete ptr;
}
BufferParams::BufferParams()
: pimpl_(new Impl)
{
setBaseClass(defaultBaseclass());
makeDocumentClass();
paragraph_separation = ParagraphIndentSeparation;
quotes_language = InsetQuotes::EnglishQuotes;
fontsize = "default";
/* PaperLayout */
papersize = PAPER_DEFAULT;
orientation = ORIENTATION_PORTRAIT;
use_geometry = false;
use_amsmath = package_auto;
use_esint = package_auto;
use_mhchem = package_auto;
use_mathdots = package_auto;
cite_engine_ = ENGINE_BASIC;
use_bibtopic = false;
use_indices = false;
trackChanges = false;
outputChanges = false;
use_default_options = true;
maintain_unincluded_children = false;
secnumdepth = 3;
tocdepth = 3;
language = default_language;
fontenc = "global";
fonts_roman = "default";
fonts_sans = "default";
fonts_typewriter = "default";
fonts_default_family = "default";
useNonTeXFonts = false;
fonts_expert_sc = false;
fonts_old_figures = false;
fonts_sans_scale = 100;
fonts_typewriter_scale = 100;
inputenc = "auto";
graphics_driver = "default";
default_output_format = "default";
bibtex_command = "default";
index_command = "default";
sides = OneSide;
columns = 1;
listings_params = string();
pagestyle = "default";
suppress_date = false;
// no color is the default (white)
backgroundcolor = lyx::rgbFromHexName("#ffffff");
isbackgroundcolor = false;
// no color is the default (black)
fontcolor = lyx::rgbFromHexName("#000000");
isfontcolor = false;
// light gray is the default font color for greyed-out notes
notefontcolor = lyx::rgbFromHexName("#cccccc");
boxbgcolor = lyx::rgbFromHexName("#ff0000");
compressed = lyxrc.save_compressed;
for (int iter = 0; iter < 4; ++iter) {
user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
}
// default index
indiceslist().addDefault(B_("Index"));
html_be_strict = false;
html_math_output = MathML;
html_math_img_scale = 1.0;
output_sync = false;
use_refstyle = true;
}
docstring BufferParams::B_(string const & l10n) const
{
LASSERT(language, /**/);
return getMessages(language->code()).get(l10n);
}
AuthorList & BufferParams::authors()
{
return pimpl_->authorlist;
}
AuthorList const & BufferParams::authors() const
{
return pimpl_->authorlist;
}
BranchList & BufferParams::branchlist()
{
return pimpl_->branchlist;
}
BranchList const & BufferParams::branchlist() const
{
return pimpl_->branchlist;
}
IndicesList & BufferParams::indiceslist()
{
return pimpl_->indiceslist;
}
IndicesList const & BufferParams::indiceslist() const
{
return pimpl_->indiceslist;
}
Bullet & BufferParams::temp_bullet(lyx::size_type const index)
{
LASSERT(index < 4, /**/);
return pimpl_->temp_bullets[index];
}
Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
{
LASSERT(index < 4, /**/);
return pimpl_->temp_bullets[index];
}
Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
{
LASSERT(index < 4, /**/);
return pimpl_->user_defined_bullets[index];
}
Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
{
LASSERT(index < 4, /**/);
return pimpl_->user_defined_bullets[index];
}
Spacing & BufferParams::spacing()
{
return pimpl_->spacing;
}
Spacing const & BufferParams::spacing() const
{
return pimpl_->spacing;
}
PDFOptions & BufferParams::pdfoptions()
{
return pimpl_->pdfoptions;
}
PDFOptions const & BufferParams::pdfoptions() const
{
return pimpl_->pdfoptions;
}
HSpace const & BufferParams::getIndentation() const
{
return pimpl_->indentation;
}
void BufferParams::setIndentation(HSpace const & indent)
{
pimpl_->indentation = indent;
}
VSpace const & BufferParams::getDefSkip() const
{
return pimpl_->defskip;
}
void BufferParams::setDefSkip(VSpace const & vs)
{
// DEFSKIP will cause an infinite loop
LASSERT(vs.kind() != VSpace::DEFSKIP, return);
pimpl_->defskip = vs;
}
string BufferParams::readToken(Lexer & lex, string const & token,
FileName const & filepath)
{
if (token == "\\textclass") {
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.
string tcp;
LayoutFileList & bcl = LayoutFileList::get();
if (tcp.empty() && !filepath.empty())
tcp = bcl.addLocalLayout(classname, filepath.absFileName());
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.
if (!baseClass()->isTeXClassAvailable()) {
docstring const desc =
translateIfPossible(from_utf8(baseClass()->description()));
docstring const prereqs =
from_utf8(baseClass()->prerequisites());
docstring const msg =
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);
}
} else if (token == "\\begin_preamble") {
readPreamble(lex);
} else if (token == "\\begin_local_layout") {
readLocalLayout(lex);
} else if (token == "\\begin_modules") {
readModules(lex);
} else if (token == "\\begin_removed_modules") {
readRemovedModules(lex);
} else if (token == "\\begin_includeonly") {
readIncludeonly(lex);
} else if (token == "\\maintain_unincluded_children") {
lex >> maintain_unincluded_children;
} else if (token == "\\options") {
lex.eatLine();
options = lex.getString();
} else if (token == "\\use_default_options") {
lex >> use_default_options;
} else if (token == "\\master") {
lex.eatLine();
master = lex.getString();
} else if (token == "\\suppress_date") {
lex >> suppress_date;
} else if (token == "\\language") {
readLanguage(lex);
} else if (token == "\\inputencoding") {
lex >> inputenc;
} else if (token == "\\graphics") {
readGraphicsDriver(lex);
} else if (token == "\\default_output_format") {
lex >> default_output_format;
} else if (token == "\\bibtex_command") {
lex.eatLine();
bibtex_command = lex.getString();
} else if (token == "\\index_command") {
lex.eatLine();
index_command = lex.getString();
} else if (token == "\\fontencoding") {
lex.eatLine();
fontenc = lex.getString();
} else if (token == "\\font_roman") {
lex.eatLine();
fonts_roman = lex.getString();
} else if (token == "\\font_sans") {
lex.eatLine();
fonts_sans = lex.getString();
} else if (token == "\\font_typewriter") {
lex.eatLine();
fonts_typewriter = lex.getString();
} else if (token == "\\font_default_family") {
lex >> fonts_default_family;
} else if (token == "\\use_non_tex_fonts") {
lex >> useNonTeXFonts;
} else if (token == "\\font_sc") {
lex >> fonts_expert_sc;
} else if (token == "\\font_osf") {
lex >> fonts_old_figures;
} else if (token == "\\font_sf_scale") {
lex >> fonts_sans_scale;
} else if (token == "\\font_tt_scale") {
lex >> fonts_typewriter_scale;
} else if (token == "\\font_cjk") {
lex >> fonts_cjk;
} else if (token == "\\paragraph_separation") {
string parsep;
lex >> parsep;
paragraph_separation = parseptranslator().find(parsep);
} else if (token == "\\paragraph_indentation") {
lex.next();
string indentation = lex.getString();
pimpl_->indentation = HSpace(indentation);
} else if (token == "\\defskip") {
lex.next();
string 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;
quotes_language = quoteslangtranslator().find(quotes_lang);
} else if (token == "\\papersize") {
string ppsize;
lex >> ppsize;
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_mathdots") {
int usemathdots;
lex >> usemathdots;
use_mathdots = packagetranslator().find(usemathdots);
} else if (token == "\\cite_engine") {
string engine;
lex >> engine;
cite_engine_ = citeenginetranslator().find(engine);
} else if (token == "\\use_bibtopic") {
lex >> use_bibtopic;
} else if (token == "\\use_indices") {
lex >> use_indices;
} else if (token == "\\tracking_changes") {
lex >> trackChanges;
} else if (token == "\\output_changes") {
lex >> outputChanges;
} else if (token == "\\branch") {
lex.eatLine();
docstring branch = lex.getDocString();
branchlist().add(branch);
while (true) {
lex.next();
string const tok = lex.getString();
if (tok == "\\end_branch")
break;
Branch * branch_ptr = branchlist().find(branch);
if (tok == "\\selected") {
lex.next();
if (branch_ptr)
branch_ptr->setSelected(lex.getInteger());
}
if (tok == "\\filename_suffix") {
lex.next();
if (branch_ptr)
branch_ptr->setFileNameSuffix(lex.getInteger());
}
if (tok == "\\color") {
lex.eatLine();
string color = lex.getString();
if (branch_ptr)
branch_ptr->setColor(color);
// Update also the Color table:
if (color == "none")
color = lcolor.getX11Name(Color_background);
// FIXME UNICODE
lcolor.setColor(to_utf8(branch), color);
}
}
} else if (token == "\\index") {
lex.eatLine();
docstring index = lex.getDocString();
docstring shortcut;
indiceslist().add(index);
while (true) {
lex.next();
string const tok = lex.getString();
if (tok == "\\end_index")
break;
Index * index_ptr = indiceslist().find(index);
if (tok == "\\shortcut") {
lex.next();
shortcut = lex.getDocString();
if (index_ptr)
index_ptr->setShortcut(shortcut);
}
if (tok == "\\color") {
lex.eatLine();
string color = lex.getString();
if (index_ptr)
index_ptr->setColor(color);
// Update also the Color table:
if (color == "none")
color = lcolor.getX11Name(Color_background);
// FIXME UNICODE
if (!shortcut.empty())
lcolor.setColor(to_utf8(shortcut), color);
}
}
} else if (token == "\\author") {
lex.eatLine();
istringstream ss(lex.getString());
Author a;
ss >> a;
author_map[a.bufferId()] = pimpl_->authorlist.record(a);
} else if (token == "\\paperorientation") {
string orient;
lex >> orient;
orientation = paperorientationtranslator().find(orient);
} else if (token == "\\backgroundcolor") {
lex.eatLine();
backgroundcolor = lyx::rgbFromHexName(lex.getString());
isbackgroundcolor = true;
} else if (token == "\\fontcolor") {
lex.eatLine();
fontcolor = lyx::rgbFromHexName(lex.getString());
isfontcolor = true;
} else if (token == "\\notefontcolor") {
lex.eatLine();
string color = lex.getString();
notefontcolor = lyx::rgbFromHexName(color);
} else if (token == "\\boxbgcolor") {
lex.eatLine();
string color = lex.getString();
boxbgcolor = lyx::rgbFromHexName(color);
} else if (token == "\\paperwidth") {
lex >> paperwidth;
} else if (token == "\\paperheight") {
lex >> paperheight;
} else if (token == "\\leftmargin") {
lex >> leftmargin;
} else if (token == "\\topmargin") {
lex >> topmargin;
} else if (token == "\\rightmargin") {
lex >> rightmargin;
} else if (token == "\\bottommargin") {
lex >> bottommargin;
} else if (token == "\\headheight") {
lex >> headheight;
} else if (token == "\\headsep") {
lex >> headsep;
} else if (token == "\\footskip") {
lex >> footskip;
} else if (token == "\\columnsep") {
lex >> columnsep;
} else if (token == "\\paperfontsize") {
lex >> fontsize;
} else if (token == "\\papercolumns") {
lex >> columns;
} else if (token == "\\listings_params") {
string par;
lex >> par;
listings_params = InsetListingsParams(par).params();
} else if (token == "\\papersides") {
int psides;
lex >> psides;
sides = sidestranslator().find(psides);
} else if (token == "\\paperpagestyle") {
lex >> pagestyle;
} else if (token == "\\bullet") {
readBullets(lex);
} else if (token == "\\bulletLaTeX") {
readBulletsLaTeX(lex);
} else if (token == "\\secnumdepth") {
lex >> secnumdepth;
} else if (token == "\\tocdepth") {
lex >> tocdepth;
} else if (token == "\\spacing") {
string nspacing;
lex >> nspacing;
string tmp_val;
if (nspacing == "other") {
lex >> tmp_val;
}
spacing().set(spacetranslator().find(nspacing), tmp_val);
} else if (token == "\\float_placement") {
lex >> float_placement;
} else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
string toktmp = pdfoptions().readToken(lex, token);
if (!toktmp.empty()) {
lyxerr << "PDFOptions::readToken(): Unknown token: " <<
toktmp << endl;
return toktmp;
}
} else if (token == "\\html_math_output") {
int temp;
lex >> temp;
html_math_output = static_cast<MathOutput>(temp);
} else if (token == "\\html_be_strict") {
lex >> html_be_strict;
} else if (token == "\\html_math_img_scale") {
lex >> html_math_img_scale;
} else if (token == "\\html_latex_start") {
lex.eatLine();
html_latex_start = lex.getString();
} else if (token == "\\html_latex_end") {
lex.eatLine();
html_latex_end = lex.getString();
} else if (token == "\\output_sync") {
lex >> output_sync;
} else if (token == "\\output_sync_macro") {
lex >> output_sync_macro;
} else if (token == "\\use_refstyle") {
lex >> use_refstyle;
} else {
lyxerr << "BufferParams::readToken(): Unknown token: " <<
token << endl;
return token;
}
return string();
}
void BufferParams::writeFile(ostream & os) const
{
// The top of the file is written by the buffer.
// Prints out the buffer info into the .lyx file given by file
// the textclass
os << "\\textclass " << baseClass()->name() << '\n';
// then the preamble
if (!preamble.empty()) {
// remove '\n' from the end of preamble
string const tmppreamble = rtrim(preamble, "\n");
os << "\\begin_preamble\n"
<< tmppreamble
<< "\n\\end_preamble\n";
}
// the options
if (!options.empty()) {
os << "\\options " << options << '\n';
}
// use the class options defined in the layout?
os << "\\use_default_options "
<< convert<string>(use_default_options) << "\n";
// the master document
if (!master.empty()) {
os << "\\master " << master << '\n';
}
// removed modules
if (!removed_modules_.empty()) {
os << "\\begin_removed_modules" << '\n';
list<string>::const_iterator it = removed_modules_.begin();
list<string>::const_iterator en = removed_modules_.end();
for (; it != en; it++)
os << *it << '\n';
os << "\\end_removed_modules" << '\n';
}
// the modules
if (!layout_modules_.empty()) {
os << "\\begin_modules" << '\n';
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 (!included_children_.empty()) {
os << "\\begin_includeonly" << '\n';
list<string>::const_iterator it = included_children_.begin();
list<string>::const_iterator en = included_children_.end();
for (; it != en; it++)
os << *it << '\n';
os << "\\end_includeonly" << '\n';
}
os << "\\maintain_unincluded_children "
<< convert<string>(maintain_unincluded_children) << '\n';
// local layout information
if (!local_layout.empty()) {
// remove '\n' from the end
string const tmplocal = rtrim(local_layout, "\n");
os << "\\begin_local_layout\n"
<< tmplocal
<< "\n\\end_local_layout\n";
}
// then the text parameters
if (language != ignore_language)
os << "\\language " << language->lang() << '\n';
os << "\\inputencoding " << inputenc
<< "\n\\fontencoding " << fontenc
<< "\n\\font_roman " << fonts_roman
<< "\n\\font_sans " << fonts_sans
<< "\n\\font_typewriter " << fonts_typewriter
<< "\n\\font_default_family " << fonts_default_family
<< "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
<< "\n\\font_sc " << convert<string>(fonts_expert_sc)
<< "\n\\font_osf " << convert<string>(fonts_old_figures)
<< "\n\\font_sf_scale " << fonts_sans_scale
<< "\n\\font_tt_scale " << fonts_typewriter_scale
<< '\n';
if (!fonts_cjk.empty()) {
os << "\\font_cjk " << fonts_cjk << '\n';
}
os << "\n\\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';
if (!float_placement.empty()) {
os << "\\float_placement " << float_placement << '\n';
}
os << "\\paperfontsize " << fontsize << '\n';
spacing().writeFile(os);
pdfoptions().writeFile(os);
os << "\\papersize " << string_papersize[papersize]
<< "\n\\use_geometry " << convert<string>(use_geometry)
<< "\n\\use_amsmath " << use_amsmath
<< "\n\\use_esint " << use_esint
<< "\n\\use_mhchem " << use_mhchem
<< "\n\\use_mathdots " << use_mathdots
<< "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
<< "\n\\use_bibtopic " << convert<string>(use_bibtopic)
<< "\n\\use_indices " << convert<string>(use_indices)
<< "\n\\paperorientation " << string_orientation[orientation]
<< "\n\\suppress_date " << convert<string>(suppress_date)
<< "\n\\use_refstyle " << use_refstyle
<< '\n';
if (isbackgroundcolor == true)
os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
if (isfontcolor == true)
os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
BranchList::const_iterator it = branchlist().begin();
BranchList::const_iterator end = branchlist().end();
for (; it != end; ++it) {
os << "\\branch " << to_utf8(it->branch())
<< "\n\\selected " << it->isSelected()
<< "\n\\filename_suffix " << it->hasFileNameSuffix()
<< "\n\\color " << lyx::X11hexname(it->color())
<< "\n\\end_branch"
<< "\n";
}
IndicesList::const_iterator iit = indiceslist().begin();
IndicesList::const_iterator iend = indiceslist().end();
for (; iit != iend; ++iit) {
os << "\\index " << to_utf8(iit->index())
<< "\n\\shortcut " << to_utf8(iit->shortcut())
<< "\n\\color " << lyx::X11hexname(iit->color())
<< "\n\\end_index"
<< "\n";
}
if (!paperwidth.empty())
os << "\\paperwidth "
<< VSpace(paperwidth).asLyXCommand() << '\n';
if (!paperheight.empty())
os << "\\paperheight "
<< VSpace(paperheight).asLyXCommand() << '\n';
if (!leftmargin.empty())
os << "\\leftmargin "
<< VSpace(leftmargin).asLyXCommand() << '\n';
if (!topmargin.empty())
os << "\\topmargin "
<< VSpace(topmargin).asLyXCommand() << '\n';
if (!rightmargin.empty())
os << "\\rightmargin "
<< VSpace(rightmargin).asLyXCommand() << '\n';
if (!bottommargin.empty())
os << "\\bottommargin "
<< VSpace(bottommargin).asLyXCommand() << '\n';
if (!headheight.empty())
os << "\\headheight "
<< VSpace(headheight).asLyXCommand() << '\n';
if (!headsep.empty())
os << "\\headsep "
<< VSpace(headsep).asLyXCommand() << '\n';
if (!footskip.empty())
os << "\\footskip "
<< VSpace(footskip).asLyXCommand() << '\n';
if (!columnsep.empty())
os << "\\columnsep "
<< VSpace(columnsep).asLyXCommand() << '\n';
os << "\\secnumdepth " << secnumdepth
<< "\n\\tocdepth " << tocdepth
<< "\n\\paragraph_separation "
<< string_paragraph_separation[paragraph_separation];
if (!paragraph_separation)
os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
else
os << "\n\\defskip " << getDefSkip().asLyXCommand();
os << "\n\\quotes_language "
<< string_quotes_language[quotes_language]
<< "\n\\papercolumns " << columns
<< "\n\\papersides " << sides
<< "\n\\paperpagestyle " << pagestyle << '\n';
if (!listings_params.empty())
os << "\\listings_params \"" <<
InsetListingsParams(listings_params).encodedString() << "\"\n";
for (int i = 0; i < 4; ++i) {
if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
if (user_defined_bullet(i).getFont() != -1) {
os << "\\bullet " << i << " "
<< user_defined_bullet(i).getFont() << " "
<< user_defined_bullet(i).getCharacter() << " "
<< user_defined_bullet(i).getSize() << "\n";
}
else {
// FIXME UNICODE
os << "\\bulletLaTeX " << i << " \""
<< lyx::to_ascii(user_defined_bullet(i).getText())
<< "\"\n";
}
}
}
os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
<< "\\output_changes " << convert<string>(outputChanges) << '\n'
<< "\\html_math_output " << html_math_output << '\n'
<< "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
if (html_math_img_scale != 1.0)
os << "\\html_math_img_scale " << convert<string>(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;
}
void BufferParams::validate(LaTeXFeatures & features) const
{
features.require(documentClass().requires());
if (outputChanges) {
bool dvipost = LaTeXFeatures::isAvailable("dvipost");
bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
LaTeXFeatures::isAvailable("xcolor");
switch (features.runparams().flavor) {
case OutputParams::LATEX:
if (dvipost) {
features.require("ct-dvipost");
features.require("dvipost");
} else if (xcolorulem) {
features.require("ct-xcolor-ulem");
features.require("ulem");
features.require("xcolor");
} else {
features.require("ct-none");
}
break;
case OutputParams::LUATEX:
case OutputParams::PDFLATEX:
case OutputParams::XETEX:
if (xcolorulem) {
features.require("ct-xcolor-ulem");
features.require("ulem");
features.require("xcolor");
// improves color handling in PDF output
features.require("pdfcolmk");
} else {
features.require("ct-none");
}
break;
default:
break;
}
}
// Floats with 'Here definitely' as default setting.
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");
if (use_mathdots == package_on)
features.require("mathdots");
// Document-level line spacing
if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
features.require("setspace");
// 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])
continue;
int const font = user_defined_bullet(i).getFont();
if (font == 0) {
int const c = user_defined_bullet(i).getCharacter();
if (c == 16
|| c == 17
|| c == 25
|| c == 26
|| c == 31) {
features.require("latexsym");
}
} else if (font == 1) {
features.require("amssymb");
} else if (font >= 2 && font <= 5) {
features.require("pifont");
}
}
if (pdfoptions().use_hyperref) {
features.require("hyperref");
// due to interferences with babel and hyperref, the color package has to
// be loaded after hyperref when hyperref is used with the colorlinks
// option, see http://www.lyx.org/trac/ticket/5291
if (pdfoptions().colorlinks)
features.require("color");
}
if (features.runparams().flavor == OutputParams::XETEX
&& useNonTeXFonts)
features.require("polyglossia");
if (language->lang() == "vietnamese")
features.require("vietnamese");
else if (language->lang() == "japanese")
features.require("japanese");
}
bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
TexRow & texrow, 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 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";
texrow.newline();
}
os << "\\documentclass";
DocumentClass const & tclass = documentClass();
ostringstream clsoptions; // the document class options.
if (tokenPos(tclass.opt_fontsize(),
'|', fontsize) >= 0) {
// only write if existing in list (and not default)
clsoptions << fontsize << "pt,";
}
// 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) {
case PAPER_A4:
clsoptions << "a4paper,";
break;
case PAPER_USLETTER:
clsoptions << "letterpaper,";
break;
case PAPER_A5:
clsoptions << "a5paper,";
break;
case PAPER_B5:
clsoptions << "b5paper,";
break;
case PAPER_USEXECUTIVE:
clsoptions << "executivepaper,";
break;
case PAPER_USLEGAL:
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;
}
}
// if needed
if (sides != tclass.sides()) {
switch (sides) {
case OneSide:
clsoptions << "oneside,";
break;
case TwoSides:
clsoptions << "twoside,";
break;
}
}
// if needed
if (columns != tclass.columns()) {
if (columns == 2)
clsoptions << "twocolumn,";
else
clsoptions << "onecolumn,";
}
if (!use_geometry
&& orientation == ORIENTATION_LANDSCAPE)
clsoptions << "landscape,";
// language should be a parameter to \documentclass
if (language->babel() == "hebrew"
&& default_language->babel() != "hebrew")
// This seems necessary
features.useLanguage(default_language);
ostringstream language_options;
bool const use_babel = features.useBabel() && !tclass.provides("babel");
bool const use_polyglossia = features.usePolyglossia();
bool const global = lyxrc.language_global_options;
if (use_babel || (use_polyglossia && global)) {
language_options << features.getLanguages();
if (!language->babel().empty()) {
if (!language_options.str().empty())
language_options << ',';
language_options << language->babel();
}
if (global && !features.needBabelLangOptions())
clsoptions << language_options.str() << ',';
}
// the predefined options from the layout
if (use_default_options && !tclass.options().empty())
clsoptions << tclass.options() << ',';
// the user-defined options
if (!options.empty()) {
clsoptions << options << ',';
}
string strOptions(clsoptions.str());
if (!strOptions.empty()) {
strOptions = rtrim(strOptions, ",");
// FIXME UNICODE
os << '[' << from_utf8(strOptions) << ']';
}
os << '{' << from_ascii(tclass.latexname()) << "}\n";
texrow.newline();
// end of \documentclass defs
int nlines;
// if we use fontspec, we have to load the AMS packages here
string const ams = features.loadAMSPackages();
if (useNonTeXFonts && !ams.empty()) {
os << from_ascii(ams);
nlines = int(count(ams.begin(), ams.end(), '\n'));
texrow.newlines(nlines);
}
if (useNonTeXFonts) {
os << "\\usepackage{fontspec}\n";
texrow.newline();
}
// font selection must be done before loading fontenc.sty
string const fonts =
loadFonts(fonts_roman, fonts_sans, fonts_typewriter,
fonts_expert_sc, fonts_old_figures,
fonts_sans_scale, fonts_typewriter_scale,
useNonTeXFonts, features);
if (!fonts.empty()) {
os << from_ascii(fonts);
nlines =
int(count(fonts.begin(), fonts.end(), '\n'));
texrow.newlines(nlines);
}
if (fonts_default_family != "default")
os << "\\renewcommand{\\familydefault}{\\"
<< 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 and LuaTeX (with OS fonts) work without fontenc
if (font_encoding() != "default" && language->lang() != "japanese"
&& !useNonTeXFonts && !tclass.provides("fontenc")) {
size_t fars = language_options.str().find("farsi");
size_t arab = language_options.str().find("arabic");
if (language->lang() == "arabic_arabi"
|| language->lang() == "farsi" || fars != string::npos
|| arab != string::npos) {
os << "\\usepackage[" << from_ascii(font_encoding())
<< ",LFE,LAE]{fontenc}\n";
texrow.newline();
} else {
os << "\\usepackage[" << from_ascii(font_encoding())
<< "]{fontenc}\n";
texrow.newline();
}
}
// handle inputenc etc.
writeEncodingPreamble(os, features, texrow);
// includeonly
if (!features.runparams().includeall && !included_children_.empty()) {
os << "\\includeonly{";
list<string>::const_iterator it = included_children_.begin();
list<string>::const_iterator en = included_children_.end();
bool first = true;
for (; it != en; ++it) {
string incfile = *it;
FileName inc = makeAbsPath(incfile, filepath.absFileName());
string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
mangledFileName();
if (!features.runparams().nice)
incfile = mangled;
// \includeonly doesn't want an extension
incfile = changeExtension(incfile, string());
incfile = support::latex_path(incfile);
if (!incfile.empty()) {
if (!first)
os << ",";
os << from_utf8(incfile);
}
first = false;
}
os << "}\n";
}
if (!listings_params.empty() || features.isRequired("listings")) {
os << "\\usepackage{listings}\n";
texrow.newline();
}
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")
&& (use_geometry || nonstandard_papersize)) {
odocstringstream ods;
if (!getGraphicsDriver("geometry").empty())
ods << getGraphicsDriver("geometry");
if (orientation == ORIENTATION_LANDSCAPE)
ods << ",landscape";
switch (papersize) {
case PAPER_CUSTOM:
if (!paperwidth.empty())
ods << ",paperwidth="
<< from_ascii(paperwidth);
if (!paperheight.empty())
ods << ",paperheight="
<< from_ascii(paperheight);
break;
case PAPER_USLETTER:
ods << ",letterpaper";
break;
case PAPER_USLEGAL:
ods << ",legalpaper";
break;
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;
case PAPER_A4:
ods << ",a4paper";
break;
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;
case PAPER_B4:
ods << ",b4paper";
break;
case PAPER_B5:
ods << ",b5paper";
break;
case PAPER_B6:
ods << ",b6paper";
break;
case PAPER_C0:
ods << ",c0paper";
break;
case PAPER_C1:
ods << ",c1paper";
break;
case PAPER_C2:
ods << ",c2paper";
break;
case PAPER_C3:
ods << ",c3paper";
break;
case PAPER_C4:
ods << ",c4paper";
break;
case PAPER_C5:
ods << ",c5paper";
break;
case PAPER_C6:
ods << ",c6paper";
break;
case PAPER_JISB0:
ods << ",b0j";
break;
case PAPER_JISB1:
ods << ",b1j";
break;
case PAPER_JISB2:
ods << ",b2j";
break;
case PAPER_JISB3:
ods << ",b3j";
break;
case PAPER_JISB4:
ods << ",b4j";
break;
case PAPER_JISB5:
ods << ",b5j";
break;
case PAPER_JISB6:
ods << ",b6j";
break;
default:
// default papersize ie PAPER_DEFAULT
switch (lyxrc.default_papersize) {
case PAPER_DEFAULT: // keep compiler happy
case PAPER_USLETTER:
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_A0:
case PAPER_A1:
case PAPER_A2:
case PAPER_A6:
case PAPER_B0:
case PAPER_B1:
case PAPER_B2:
case PAPER_B3:
case PAPER_B4:
case PAPER_B6:
case PAPER_C0:
case PAPER_C1:
case PAPER_C2:
case PAPER_C3:
case PAPER_C4:
case PAPER_C5:
case PAPER_C6:
case PAPER_JISB0:
case PAPER_JISB1:
case PAPER_JISB2:
case PAPER_JISB3:
case PAPER_JISB4:
case PAPER_JISB5:
case PAPER_JISB6:
case PAPER_CUSTOM:
break;
}
}
docstring const g_options = trim(ods.str(), ",");
os << "\\usepackage";
if (!g_options.empty())
os << '[' << g_options << ']';
os << "{geometry}\n";
texrow.newline();
// output this only if use_geometry is true
if (use_geometry) {
os << "\\geometry{verbose";
if (!topmargin.empty())
os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
if (!bottommargin.empty())
os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
if (!leftmargin.empty())
os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
if (!rightmargin.empty())
os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
if (!headheight.empty())
os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
if (!headsep.empty())
os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
if (!footskip.empty())
os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
if (!columnsep.empty())
os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
os << "}\n";
texrow.newline();
}
} else if (orientation == ORIENTATION_LANDSCAPE
|| papersize != PAPER_DEFAULT) {
features.require("papersize");
}
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 default
if (isbackgroundcolor == true) {
// only require color here, the background color will be defined
// in LaTeXFeatures.cpp to avoid interferences with the LaTeX
// package pdfpages
features.require("color");
features.require("pagecolor");
}
// only output when the font color is not default
if (isfontcolor == true) {
// only require color here, the font color will be defined
// in LaTeXFeatures.cpp to avoid interferences with the LaTeX
// package pdfpages
features.require("color");
features.require("fontcolor");
}
// Only if class has a ToC hierarchy
if (tclass.hasTocLevels()) {
if (secnumdepth != tclass.secnumdepth()) {
os << "\\setcounter{secnumdepth}{"
<< secnumdepth
<< "}\n";
texrow.newline();
}
if (tocdepth != tclass.tocdepth()) {
os << "\\setcounter{tocdepth}{"
<< tocdepth
<< "}\n";
texrow.newline();
}
}
if (paragraph_separation) {
// when skip separation
switch (getDefSkip().kind()) {
case VSpace::SMALLSKIP:
os << "\\setlength{\\parskip}{\\smallskipamount}\n";
break;
case VSpace::MEDSKIP:
os << "\\setlength{\\parskip}{\\medskipamount}\n";
break;
case VSpace::BIGSKIP:
os << "\\setlength{\\parskip}{\\bigskipamount}\n";
break;
case VSpace::LENGTH:
os << "\\setlength{\\parskip}{"
<< from_utf8(getDefSkip().length().asLatexString())
<< "}\n";
break;
default: // should never happen // Then delete it.
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())
<< "}\n";
texrow.newline();
}
}
// Now insert the LyX specific LaTeX commands...
docstring lyxpreamble;
if (output_sync) {
if (!output_sync_macro.empty())
lyxpreamble += from_utf8(output_sync_macro) +"\n";
else if (features.runparams().flavor == OutputParams::LATEX)
lyxpreamble += "\\usepackage[active]{srcltx}\n";
else if (features.runparams().flavor == OutputParams::PDFLATEX)
lyxpreamble += "\\synctex=-1\n";
}
// due to interferences with babel and hyperref, the color package has to
// be loaded (when it is not already loaded) before babel when hyperref
// is used with the colorlinks option, see
// http://www.lyx.org/trac/ticket/5291
// we decided therefore to load color always before babel, see
// http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
lyxpreamble += from_ascii(features.getColorOptions());
// If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
if (use_babel
&& (features.isRequired("jurabib")
|| features.isRequired("hyperref")
|| features.isRequired("vietnamese")
|| features.isRequired("japanese"))) {
// FIXME UNICODE
lyxpreamble += from_utf8(features.getBabelPresettings());
lyxpreamble += from_utf8(babelCall(language_options.str(),
features.needBabelLangOptions())) + '\n';
lyxpreamble += from_utf8(features.getBabelPostsettings());
}
// The optional packages;
lyxpreamble += from_ascii(features.getPackages());
// Additional Indices
if (features.isRequired("splitidx")) {
IndicesList::const_iterator iit = indiceslist().begin();
IndicesList::const_iterator iend = indiceslist().end();
for (; iit != iend; ++iit) {
lyxpreamble += "\\newindex[";
lyxpreamble += iit->index();
lyxpreamble += "]{";
lyxpreamble += iit->shortcut();
lyxpreamble += "}\n";
}
}
// Line spacing
lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
// PDF support.
// * Hyperref manual: "Make sure it comes last of your loaded
// packages, to give it a fighting chance of not being over-written,
// since its job is to redefine many LaTeX commands."
// * Email from Heiko Oberdiek: "It is usually better to load babel
// before hyperref. Then hyperref has a chance to detect babel.
// * Has to be loaded before the "LyX specific LaTeX commands" to
// 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;
int lines =
int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
OutputParams tmp_params = features.runparams();
lines += pdfoptions().writeLaTeX(tmp_params, os,
documentClass().provides("hyperref"));
texrow.newlines(lines);
// set back for the rest
lyxpreamble.clear();
// 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";
// Will be surrounded by \makeatletter and \makeatother when not empty
docstring atlyxpreamble;
// Some macros LyX will need
docstring tmppreamble(features.getMacros());
if (!tmppreamble.empty())
atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
"LyX specific LaTeX commands.\n"
+ tmppreamble + '\n';
// the text class specific preamble
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";
/* the user-defined preamble */
if (!containsOnly(preamble, " \n\t"))
// FIXME UNICODE
atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
"User specified LaTeX commands.\n"
+ from_utf8(preamble) + '\n';
// subfig loads internally the LaTeX package "caption". As
// caption is a very popular package, users will load it in
// the preamble. Therefore we must load subfig behind the
// user-defined preamble and check if the caption package was
// loaded or not. For the case that caption is loaded before
// subfig, there is the subfig option "caption=false". This
// option also works when a koma-script class is used and
// koma's own caption commands are used instead of caption. We
// use \PassOptionsToPackage here because the user could have
// already loaded subfig in the preamble.
if (features.isRequired("subfig")) {
atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
" \\PassOptionsToPackage{caption=false}{subfig}}\n"
"\\usepackage{subfig}\n";
}
// Itemize bullet settings need to be last in case the user
// defines their own bullets that use a package included
// in the user-defined preamble -- ARRae
// Actually it has to be done much later than that
// since some packages like frenchb make modifications
// at \begin{document} time -- JMarc
docstring bullets_def;
for (int i = 0; i < 4; ++i) {
if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
if (bullets_def.empty())
bullets_def += "\\AtBeginDocument{\n";
bullets_def += " \\def\\labelitemi";
switch (i) {
// `i' is one less than the item to modify
case 0:
break;
case 1:
bullets_def += 'i';
break;
case 2:
bullets_def += "ii";
break;
case 3:
bullets_def += 'v';
break;
}
bullets_def += '{' +
user_defined_bullet(i).getText()
+ "}\n";
}
}
if (!bullets_def.empty())
atlyxpreamble += bullets_def + "}\n\n";
if (!atlyxpreamble.empty())
lyxpreamble += "\n\\makeatletter\n"
+ atlyxpreamble + "\\makeatother\n\n";
// We try to load babel late, in case it interferes with other packages.
// Jurabib and Hyperref have to be called after babel, though.
if (use_babel && !features.isRequired("jurabib")
&& !features.isRequired("hyperref")
&& !features.isRequired("vietnamese")
&& !features.isRequired("japanese")) {
// FIXME UNICODE
lyxpreamble += from_utf8(features.getBabelPresettings());
lyxpreamble += from_utf8(babelCall(language_options.str(),
features.needBabelLangOptions())) + '\n';
lyxpreamble += from_utf8(features.getBabelPostsettings());
}
// 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)
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<std::string, std::string> const polylangs =
features.getPolyglossiaLanguages();
for (std::map<std::string, std::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";
}
}
docstring const i18npreamble =
features.getTClassI18nPreamble(use_babel, use_polyglossia);
if (!i18npreamble.empty())
lyxpreamble += i18npreamble + '\n';
nlines = int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
texrow.newlines(nlines);
os << lyxpreamble;
return use_babel;
}
void BufferParams::useClassDefaults()
{
DocumentClass const & tclass = documentClass();
sides = tclass.sides();
columns = tclass.columns();
pagestyle = tclass.pagestyle();
use_default_options = true;
// Only if class has a ToC hierarchy
if (tclass.hasTocLevels()) {
secnumdepth = tclass.secnumdepth();
tocdepth = tclass.tocdepth();
}
}
bool BufferParams::hasClassDefaults() const
{
DocumentClass const & tclass = documentClass();
return sides == tclass.sides()
&& columns == tclass.columns()
&& pagestyle == tclass.pagestyle()
&& use_default_options
&& secnumdepth == tclass.secnumdepth()
&& tocdepth == tclass.tocdepth();
}
DocumentClass const & BufferParams::documentClass() const
{
return *doc_class_;
}
DocumentClass const * BufferParams::documentClassPtr() const
{
return doc_class_;
}
void BufferParams::setDocumentClass(DocumentClass const * const tc)
{
// evil, but this function is evil
doc_class_ = const_cast<DocumentClass *>(tc);
}
bool BufferParams::setBaseClass(string const & classname)
{
LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
LayoutFileList & bcl = LayoutFileList::get();
if (!bcl.haveClass(classname)) {
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);
}
bool const success = bcl[classname].load();
if (!success) {
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);
bcl.addEmptyClass(classname);
}
pimpl_->baseClass_ = classname;
layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
return true;
}
LayoutFile const * BufferParams::baseClass() const
{
if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
return &(LayoutFileList::get()[pimpl_->baseClass_]);
else
return 0;
}
LayoutFileIndex const & BufferParams::baseClassID() const
{
return pimpl_->baseClass_;
}
void BufferParams::makeDocumentClass()
{
if (!baseClass())
return;
doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
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);
}
}
}
bool BufferParams::moduleCanBeAdded(string const & modName) const
{
return layout_modules_.moduleCanBeAdded(modName, baseClass());
}
bool BufferParams::addLayoutModule(string const & modName)
{
LayoutModuleList::const_iterator it = layout_modules_.begin();
LayoutModuleList::const_iterator end = layout_modules_.end();
for (; it != end; it++)
if (*it == modName)
return false;
layout_modules_.push_back(modName);
return true;
}
Font const BufferParams::getFont() const
{
FontInfo f = documentClass().defaultfont();
if (fonts_default_family == "rmdefault")
f.setFamily(ROMAN_FAMILY);
else if (fonts_default_family == "sfdefault")
f.setFamily(SANS_FAMILY);
else if (fonts_default_family == "ttdefault")
f.setFamily(TYPEWRITER_FAMILY);
return Font(f, language);
}
void BufferParams::readPreamble(Lexer & lex)
{
if (lex.getString() != "\\begin_preamble")
lyxerr << "Error (BufferParams::readPreamble):"
"consistency check failed." << endl;
preamble = lex.getLongString("\\end_preamble");
}
void BufferParams::readLocalLayout(Lexer & lex)
{
if (lex.getString() != "\\begin_local_layout")
lyxerr << "Error (BufferParams::readLocalLayout):"
"consistency check failed." << endl;
local_layout = lex.getLongString("\\end_local_layout");
}
void BufferParams::readLanguage(Lexer & lex)
{
if (!lex.next()) return;
string const tmptok = lex.getString();
// check if tmptok is part of tex_babel in tex-defs.h
language = languages.getLanguage(tmptok);
if (!language) {
// Language tmptok was not found
language = default_language;
lyxerr << "Warning: Setting language `"
<< tmptok << "' to `" << language->lang()
<< "'." << endl;
}
}
void BufferParams::readGraphicsDriver(Lexer & lex)
{
if (!lex.next())
return;
string const tmptok = lex.getString();
// check if tmptok is part of tex_graphics in tex_defs.h
int n = 0;
while (true) {
string const test = tex_graphics[n++];
if (test == tmptok) {
graphics_driver = tmptok;
break;
}
if (test.empty()) {
lex.printError(
"Warning: graphics driver `$$Token' not recognized!\n"
" Setting graphics driver to `default'.\n");
graphics_driver = "default";
break;
}
}
}
void BufferParams::readBullets(Lexer & lex)
{
if (!lex.next())
return;
int const index = lex.getInteger();
lex.next();
int temp_int = lex.getInteger();
user_defined_bullet(index).setFont(temp_int);
temp_bullet(index).setFont(temp_int);
lex >> temp_int;
user_defined_bullet(index).setCharacter(temp_int);
temp_bullet(index).setCharacter(temp_int);
lex >> temp_int;
user_defined_bullet(index).setSize(temp_int);
temp_bullet(index).setSize(temp_int);
}
void BufferParams::readBulletsLaTeX(Lexer & lex)
{
// The bullet class should be able to read this.
if (!lex.next())
return;
int const index = lex.getInteger();
lex.next(true);
docstring const temp_str = lex.getDocString();
user_defined_bullet(index).setText(temp_str);
temp_bullet(index).setText(temp_str);
}
void BufferParams::readModules(Lexer & lex)
{
if (!lex.eatLine()) {
lyxerr << "Error (BufferParams::readModules):"
"Unexpected end of input." << endl;
return;
}
while (true) {
string mod = lex.getString();
if (mod == "\\end_modules")
break;
addLayoutModule(mod);
lex.eatLine();
}
}
void BufferParams::readRemovedModules(Lexer & lex)
{
if (!lex.eatLine()) {
lyxerr << "Error (BufferParams::readRemovedModules):"
"Unexpected end of input." << endl;
return;
}
while (true) {
string mod = lex.getString();
if (mod == "\\end_removed_modules")
break;
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
// start of the read.
list<string>::const_iterator rit = removed_modules_.begin();
list<string>::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;
layout_modules_.erase(found);
}
}
void BufferParams::readIncludeonly(Lexer & lex)
{
if (!lex.eatLine()) {
lyxerr << "Error (BufferParams::readIncludeonly):"
"Unexpected end of input." << endl;
return;
}
while (true) {
string child = lex.getString();
if (child == "\\end_includeonly")
break;
included_children_.push_back(child);
lex.eatLine();
}
}
string BufferParams::paperSizeName(PapersizePurpose purpose) const
{
char real_papersize = papersize;
if (real_papersize == PAPER_DEFAULT)
real_papersize = lyxrc.default_papersize;
switch (real_papersize) {
case PAPER_DEFAULT:
// could be anything, so don't guess
return string();
case PAPER_CUSTOM: {
if (purpose == XDVI && !paperwidth.empty() &&
!paperheight.empty()) {
// heightxwidth<unit>
string first = paperwidth;
string second = paperheight;
if (orientation == ORIENTATION_LANDSCAPE)
first.swap(second);
// cut off unit.
return first.erase(first.length() - 2)
+ "x" + second;
}
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:
if (purpose == DVIPS || purpose == DVIPDFM)
return string();
return "b3";
case PAPER_B4:
// dvipdfm does not know this
if (purpose == DVIPDFM)
return string();
return "b4";
case PAPER_B5:
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)
return string();
return "foolscap";
case PAPER_USLEGAL:
return "legal";
case PAPER_USLETTER:
default:
if (purpose == XDVI)
return "us";
return "letter";
}
}
string const BufferParams::dvips_options() const
{
string result;
if (use_geometry
&& papersize == PAPER_CUSTOM
&& !lyxrc.print_paper_dimension_flag.empty()
&& !paperwidth.empty()
&& !paperheight.empty()) {
// using a custom papersize
result = lyxrc.print_paper_dimension_flag;
result += ' ' + paperwidth;
result += ',' + paperheight;
} else {
string const paper_option = paperSizeName(DVIPS);
if (!paper_option.empty() && (paper_option != "letter" ||
orientation != ORIENTATION_LANDSCAPE)) {
// dvips won't accept -t letter -t landscape.
// In all other cases, include the paper size
// explicitly.
result = lyxrc.print_paper_flag;
result += ' ' + paper_option;
}
}
if (orientation == ORIENTATION_LANDSCAPE &&
papersize != PAPER_CUSTOM)
result += ' ' + lyxrc.print_landscape_flag;
return result;
}
string const BufferParams::font_encoding() const
{
return (fontenc == "global") ? lyxrc.fontenc : fontenc;
}
string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
{
if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
return lyxrc.language_custom_package;
// 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();
// 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 "\\usepackage{babel}";
}
docstring BufferParams::getGraphicsDriver(string const & package) const
{
docstring result;
if (package == "geometry") {
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");
}
return result;
}
void BufferParams::writeEncodingPreamble(odocstream & os,
LaTeXFeatures & features, TexRow & texrow) const
{
// 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) {
if (!useNonTeXFonts) {
os << "\\usepackage[utf8]{luainputenc}\n";
texrow.newline();
}
return;
}
if (inputenc == "auto") {
string const doc_encoding =
language->encoding()->latexName();
Encoding::Package const package =
language->encoding()->package();
// Create a list with all the input encodings used
// in the document
set<string> encodings =
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 (package == Encoding::japanese)
features.require("japanese");
if ((!encodings.empty() || package == Encoding::inputenc)
&& !features.isRequired("japanese")) {
os << "\\usepackage[";
set<string>::const_iterator it = encodings.begin();
set<string>::const_iterator const end = encodings.end();
if (it != end) {
os << from_ascii(*it);
++it;
}
for (; it != end; ++it)
os << ',' << from_ascii(*it);
if (package == Encoding::inputenc) {
if (!encodings.empty())
os << ',';
os << from_ascii(doc_encoding);
}
os << "]{inputenc}\n";
texrow.newline();
}
if (package == Encoding::CJK || features.mustProvide("CJK")) {
if (language->encoding()->name() == "utf8-cjk"
&& LaTeXFeatures::isAvailable("CJKutf8"))
os << "\\usepackage{CJKutf8}\n";
else
os << "\\usepackage{CJK}\n";
texrow.newline();
}
} else if (inputenc != "default") {
switch (encoding().package()) {
case Encoding::none:
case Encoding::japanese:
break;
case Encoding::inputenc:
// do not load inputenc if japanese is used
if (features.isRequired("japanese"))
break;
os << "\\usepackage[" << from_ascii(inputenc)
<< "]{inputenc}\n";
texrow.newline();
break;
case Encoding::CJK:
if (encoding().name() == "utf8-cjk"
&& LaTeXFeatures::isAvailable("CJKutf8"))
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();
}
}
string const BufferParams::parseFontName(string const & name) const
{
string mangled = name;
size_t const idx = mangled.find('[');
if (idx == string::npos || idx == 0)
return mangled;
else
return mangled.substr(0, idx - 1);
}
string const BufferParams::loadFonts(string const & rm,
string const & sf, string const & tt,
bool const & sc, bool const & osf,
int const & sfscale, int const & ttscale,
bool const & use_systemfonts,
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")
//nothing to do
return string();
ostringstream os;
/* 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 (use_systemfonts) {
// "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.
string const texmapping =
(features.runparams().flavor == OutputParams::XETEX) ?
"Mapping=tex-text" : "Ligatures=TeX";
if (rm != "default") {
os << "\\setmainfont[" << texmapping;
if (osf)
os << ",Numbers=OldStyle";
os << "]{" << parseFontName(rm) << "}\n";
}
if (sf != "default") {
string const sans = parseFontName(sf);
if (sfscale != 100)
os << "\\setsansfont[Scale="
<< float(sfscale) / 100
<< "," << texmapping << "]{"
<< sans << "}\n";
else
os << "\\setsansfont[" << texmapping << "]{"
<< sans << "}\n";
}
if (tt != "default") {
string const mono = parseFontName(tt);
if (ttscale != 100)
os << "\\setmonofont[Scale="
<< float(ttscale) / 100
<< "]{"
<< mono << "}\n";
else
os << "\\setmonofont{"
<< mono << "}\n";
}
return os.str();
}
// 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";
// 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";
return os.str();
}
Encoding const & BufferParams::encoding() const
{
// 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.fromLaTeXName("utf8-plain"));
if (inputenc == "auto" || inputenc == "default")
return *language->encoding();
Encoding const * const enc = encodings.fromLaTeXName(inputenc);
if (enc)
return *enc;
LYXERR0("Unknown inputenc value `" << inputenc
<< "'. Using `auto' instead.");
return *language->encoding();
}
CiteEngine BufferParams::citeEngine() 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_;
}
void BufferParams::setCiteEngine(CiteEngine cite_engine)
{
cite_engine_ = cite_engine;
}
} // namespace lyx