#include "ParagraphParameters.h"
#include "TextClass.h"
#include "TexRow.h"
-#include "VSpace.h"
#include "insets/InsetBibitem.h"
#include "insets/InsetArgument.h"
#include "support/lassert.h"
+#include "support/convert.h"
#include "support/debug.h"
#include "support/lstrings.h"
+#include <algorithm>
#include <boost/next_prior.hpp>
#include <list>
namespace {
enum OpenEncoding {
- none,
- inputenc,
- CJK
+ none,
+ inputenc,
+ CJK
};
static int open_encoding_ = none;
}
-struct TeXEnvironementData
+struct TeXEnvironmentData
{
bool cjk_nested;
Layout const * style;
};
-static TeXEnvironementData prepareEnvironement(Buffer const & buf,
+static TeXEnvironmentData prepareEnvironment(Buffer const & buf,
Text const & text,
ParagraphList::const_iterator pit,
otexstream & os,
OutputParams const & runparams)
{
- TeXEnvironementData data;
+ TeXEnvironmentData data;
BufferParams const & bparams = buf.params();
? (use_prev_env_language ? prev_env_language_
: priorpit->getParLanguage(bparams))
: doc_language;
- string par_lang = data.par_language->babel();
- string prev_par_lang = prev_par_language->babel();
- string doc_lang = doc_language->babel();
- string lang_begin_command = lyxrc.language_command_begin;
- string lang_end_command = lyxrc.language_command_end;
-
- if (runparams.use_polyglossia) {
- par_lang = getPolyglossiaEnvName(data.par_language);
- prev_par_lang = getPolyglossiaEnvName(prev_par_language);
- doc_lang = getPolyglossiaEnvName(doc_language);
- lang_begin_command = "\\begin{$$lang}";
- lang_end_command = "\\end{$$lang}";
- }
+
+ bool const use_polyglossia = runparams.use_polyglossia;
+ string const par_lang = use_polyglossia ?
+ getPolyglossiaEnvName(data.par_language) : data.par_language->babel();
+ string const prev_par_lang = use_polyglossia ?
+ getPolyglossiaEnvName(prev_par_language) : prev_par_language->babel();
+ string const doc_lang = use_polyglossia ?
+ getPolyglossiaEnvName(doc_language) : doc_language->babel();
+ string const lang_begin_command = use_polyglossia ?
+ "\\begin{$$lang}" : lyxrc.language_command_begin;
+ string const lang_end_command = use_polyglossia ?
+ "\\end{$$lang}" : lyxrc.language_command_end;
if (par_lang != prev_par_lang) {
if (!lang_end_command.empty() &&
lang_begin_command,
"$$lang",
par_lang));
- if (runparams.use_polyglossia
+ if (use_polyglossia
&& !data.par_language->polyglossiaOpts().empty())
os << "["
<< from_ascii(data.par_language->polyglossiaOpts())
if (style.isEnvironment()) {
os << "\\begin{" << from_ascii(style.latexname()) << '}';
- if (style.optargs != 0 || style.reqargs != 0)
- latexArgInsets(*pit, os, runparams, style.reqargs, style.optargs);
+ if (!style.latexargs().empty())
+ latexArgInsets(*pit, os, runparams, style.latexargs());
if (style.latextype == LATEX_LIST_ENVIRONMENT) {
os << '{'
<< pit->params().labelWidthString()
}
-static void finishEnvironement(otexstream & os, OutputParams const & runparams,
- TeXEnvironementData const & data)
+static void finishEnvironment(otexstream & os, OutputParams const & runparams,
+ TeXEnvironmentData const & data)
{
if (open_encoding_ == CJK && data.cjk_nested) {
// We need to close the encoding even if it does not change
// This is for debugging purpose at the end.
pit_type const par_begin = pit;
for (; pit < runparams.par_end; ++pit) {
-
ParagraphList::const_iterator par = paragraphs.constIterator(pit);
// check first if this is an higher depth paragraph.
// Or par->params().leftIndent() != current_left_indent)
if (par->layout().isParagraph()) {
- // FIXME (Lgb): How to handle this?
+ // FIXME (Lgb): How to handle this?
//&& !suffixIs(os, "\n\n")
// (ARRae) There should be at least one '\n' already but we need there to
// be two for Standard paragraphs that are depth-increment'ed to be
// output correctly. However, tables can also be paragraphs so
// don't adjust them.
- //
// FIXME (Lgb): Will it ever harm to have one '\n' too
// many? i.e. that we sometimes will have
}
// This is a new environment.
- TeXEnvironementData const data =
- prepareEnvironement(buf, text, par, os, runparams);
+ TeXEnvironmentData const data =
+ prepareEnvironment(buf, text, par, os, runparams);
// Recursive call to TeXEnvironment!
TeXEnvironment(buf, text, runparams, pit, os);
- finishEnvironement(os, runparams, data);
+ finishEnvironment(os, runparams, data);
}
if (pit != runparams.par_end)
void latexArgInsets(Paragraph const & par, otexstream & os,
- OutputParams const & runparams, unsigned int reqargs,
- unsigned int optargs)
+ OutputParams const & runparams, Layout::LaTeXArgMap const & latexargs)
{
- unsigned int totalargs = reqargs + optargs;
- list<InsetArgument const *> ilist;
+ map<int, InsetArgument const *> ilist;
+ vector<string> required;
InsetList::const_iterator it = par.insetList().begin();
InsetList::const_iterator end = par.insetList().end();
for (; it != end; ++it) {
if (it->inset->lyxCode() == ARG_CODE) {
- if (ilist.size() >= totalargs) {
- LYXERR0("WARNING: Found extra argument inset.");
- continue;
- }
InsetArgument const * ins =
static_cast<InsetArgument const *>(it->inset);
- ilist.push_back(ins);
+ if (ins->name().empty())
+ LYXERR0("Error: Unnamed argument inset!");
+ else {
+ unsigned int const nr = convert<unsigned int>(ins->name());
+ ilist[nr] = ins;
+ Layout::LaTeXArgMap::const_iterator const lit =
+ latexargs.find(nr);
+ if (lit != latexargs.end()) {
+ Layout::latexarg const & arg = (*lit).second;
+ if (!arg.requires.empty()) {
+ vector<string> req = getVectorFromString(arg.requires);
+ required.insert(required.end(), req.begin(), req.end());
+ }
+ }
+ }
}
}
- if (!reqargs && ilist.size() == 0)
+ unsigned int const argnr = latexargs.size();
+ if (argnr == 0)
return;
- bool const have_optional_args = ilist.size() > reqargs;
- if (have_optional_args) {
- unsigned int todo = ilist.size() - reqargs;
- for (unsigned int i = 0; i < todo; ++i) {
- InsetArgument const * ins = ilist.front();
- ilist.pop_front();
- ins->latexArgument(os, runparams, true);
+ for (unsigned int i = 1; i <= argnr; ++i) {
+ map<int, InsetArgument const *>::const_iterator lit = ilist.find(i);
+ bool inserted = false;
+ if (lit != ilist.end()) {
+ InsetArgument const * ins = (*lit).second;
+ if (ins) {
+ Layout::LaTeXArgMap::const_iterator const lait =
+ latexargs.find(convert<unsigned int>(ins->name()));
+ if (lait != latexargs.end()) {
+ Layout::latexarg arg = (*lait).second;
+ docstring ldelim = arg.mandatory ?
+ from_ascii("{") : from_ascii("[");
+ docstring rdelim = arg.mandatory ?
+ from_ascii("}") : from_ascii("]");
+ if (!arg.ldelim.empty())
+ ldelim = arg.ldelim;
+ if (!arg.rdelim.empty())
+ rdelim = arg.rdelim;
+ ins->latexArgument(os, runparams, ldelim, rdelim);
+ inserted = true;
+ }
+ }
}
- }
-
- // we should now have no more insets than there are required
- // arguments.
- LASSERT(ilist.size() <= reqargs, /* */);
- if (!reqargs)
- return;
-
- for (unsigned int i = 0; i < reqargs; ++i) {
- if (ilist.empty())
- // a required argument wasn't given, so we output {}
- os << "{}";
- else {
- InsetArgument const * ins = ilist.front();
- ilist.pop_front();
- ins->latexArgument(os, runparams, false);
+ if (!inserted) {
+ Layout::LaTeXArgMap::const_iterator lait = latexargs.begin();
+ Layout::LaTeXArgMap::const_iterator const laend = latexargs.end();
+ for (; lait != laend; ++lait) {
+ if ((*lait).first == i) {
+ Layout::latexarg arg = (*lait).second;
+ if (arg.mandatory) {
+ docstring ldelim = arg.ldelim.empty() ?
+ from_ascii("{") : arg.ldelim;
+ docstring rdelim = arg.rdelim.empty() ?
+ from_ascii("}") : arg.rdelim;
+ os << ldelim << rdelim;
+ } else if (find(required.begin(), required.end(),
+ convert<string>((*lait).first)) != required.end()) {
+ docstring ldelim = arg.ldelim.empty() ?
+ from_ascii("[") : arg.ldelim;
+ docstring rdelim = arg.rdelim.empty() ?
+ from_ascii("]") : arg.rdelim;
+ os << ldelim << rdelim;
+ } else
+ break;
+ }
+ }
}
}
}
os << '\\' << from_ascii(style.latexname());
// Separate handling of optional argument inset.
- if (style.optargs != 0 || style.reqargs != 0)
- latexArgInsets(par, os, runparams, style.reqargs, style.optargs);
+ if (!style.latexargs().empty())
+ latexArgInsets(par, os, runparams, style.latexargs());
else
os << from_ascii(style.latexparam());
break;
: priorpar->getParLanguage(bparams))
: outer_language;
- string par_lang = par_language->babel();
- string prev_lang = prev_language->babel();
- string doc_lang = doc_language->babel();
- string outer_lang = outer_language->babel();
- string lang_begin_command = lyxrc.language_command_begin;
- string lang_end_command = lyxrc.language_command_end;
-
- if (runparams.use_polyglossia) {
- par_lang = getPolyglossiaEnvName(par_language);
- prev_lang = getPolyglossiaEnvName(prev_language);
- doc_lang = getPolyglossiaEnvName(doc_language);
- outer_lang = getPolyglossiaEnvName(outer_language);
- lang_begin_command = "\\begin{$$lang}";
- lang_end_command = "\\end{$$lang}";
- }
+
+ bool const use_polyglossia = runparams.use_polyglossia;
+ string const par_lang = use_polyglossia ?
+ getPolyglossiaEnvName(par_language): par_language->babel();
+ string const prev_lang = use_polyglossia ?
+ getPolyglossiaEnvName(prev_language) : prev_language->babel();
+ string const doc_lang = use_polyglossia ?
+ getPolyglossiaEnvName(doc_language) : doc_language->babel();
+ string const outer_lang = use_polyglossia ?
+ getPolyglossiaEnvName(outer_language) : outer_language->babel();
+ string const lang_begin_command = use_polyglossia ?
+ "\\begin{$$lang}" : lyxrc.language_command_begin;
+ string const lang_end_command = use_polyglossia ?
+ "\\end{$$lang}" : lyxrc.language_command_end;
+
if (par_lang != prev_lang
// check if we already put language command in TeXEnvironment()
&& !(style.isEnvironment()
// language paragraph should appear within an \L or \R (in addition
// to, outside of, the normal language switch commands).
// This behavior is not correct for ArabTeX, though.
- if (!runparams.use_polyglossia
+ if (!use_polyglossia
// not for ArabTeX
&& par_language->lang() != "arabic_arabtex"
&& outer_language->lang() != "arabic_arabtex"
os << "\\L{";
}
// With CJK, the CJK tag has to be closed first (see below)
- if (runparams.encoding->package() != Encoding::CJK) {
+ if (runparams.encoding->package() != Encoding::CJK
+ && !par_lang.empty()) {
os << from_ascii(subst(
lang_begin_command,
"$$lang",
par_lang));
- if (runparams.use_polyglossia
+ if (use_polyglossia
&& !par_language->polyglossiaOpts().empty())
os << "["
<< from_ascii(par_language->polyglossiaOpts())
os << "%\n";
}
// With CJK, the CJK tag had to be closed first (see above)
- if (runparams.encoding->package() == Encoding::CJK) {
+ if (runparams.encoding->package() == Encoding::CJK
+ && !par_lang.empty()) {
os << from_ascii(subst(
lang_begin_command,
"$$lang",
}
bool pending_newline = false;
+ bool unskip_newline = false;
switch (style.latextype) {
case LATEX_ITEM_ENVIRONMENT:
case LATEX_LIST_ENVIRONMENT:
// Closing the language is needed for the last paragraph; it is also
// needed if we're within an \L or \R that we may have opened above (not
// necessarily in this paragraph) and are about to close.
- bool closing_rtl_ltr_environment = !runparams.use_polyglossia
+ bool closing_rtl_ltr_environment = !use_polyglossia
// not for ArabTeX
&& (par_language->lang() != "arabic_arabtex"
&& outer_language->lang() != "arabic_arabtex")
|| (runparams.isLastPar && par_language->babel() != outer_language->babel()));
if (closing_rtl_ltr_environment
- || (runparams.isLastPar && par_language->babel() != outer_language->babel())) {
+ || (runparams.isLastPar
+ && ((!use_polyglossia && par_language->babel() != outer_language->babel())
+ || (use_polyglossia && par_language->polyglossia() != outer_language->polyglossia())))) {
// Since \selectlanguage write the language to the aux file,
// we need to reset the language at the end of footnote or
// float.
(runparams.isLastPar && runparams.master_language)
? runparams.master_language
: outer_language;
- string const current_lang = runparams.use_polyglossia ?
- getPolyglossiaEnvName(current_language)
+ string const current_lang = use_polyglossia
+ ? getPolyglossiaEnvName(current_language)
: current_language->babel();
if (!current_lang.empty()) {
os << from_ascii(subst(
"$$lang",
current_lang));
pending_newline = true;
+ unskip_newline = true;
}
} else if (!par_lang.empty()) {
os << from_ascii(subst(
"$$lang",
par_lang));
pending_newline = true;
+ unskip_newline = true;
}
}
}
if (closing_rtl_ltr_environment)
os << "}";
- if (pending_newline)
+ if (pending_newline) {
+ if (unskip_newline)
+ // prevent unwanted whitespace
+ os << '%';
os << '\n';
+ }
// if this is a CJK-paragraph and the next isn't, close CJK
// also if the next paragraph is a multilingual environment (because of nesting)
}
// if "auto begin" is switched off, explicitly switch the
// language on at start
- string const mainlang = runparams.use_polyglossia ?
- getPolyglossiaEnvName(bparams.language)
+ string const mainlang = runparams.use_polyglossia
+ ? getPolyglossiaEnvName(bparams.language)
: bparams.language->babel();
string const lang_begin_command = runparams.use_polyglossia ?
"\\begin{$$lang}" : lyxrc.language_command_begin;
continue;
}
- TeXEnvironementData const data =
- prepareEnvironement(buf, text, par, os, runparams);
+ TeXEnvironmentData const data =
+ prepareEnvironment(buf, text, par, os, runparams);
// pit can be changed in TeXEnvironment.
TeXEnvironment(buf, text, runparams, pit, os);
- finishEnvironement(os, runparams, data);
+ finishEnvironment(os, runparams, data);
}
if (pit == runparams.par_end) {