#include "support/convert.h"
#include "support/debug.h"
#include "support/lstrings.h"
+#include "support/textutils.h"
#include <algorithm>
#include <boost/next_prior.hpp>
CJK
};
+// FIXME THREAD
+// There could easily be a conflict here, with the export process
+// setting this one way, and a View>Source process (possbily for
+// another Buffer) resetting it.
static int open_encoding_ = none;
static int cjk_inherited_ = 0;
Language const * prev_env_language_ = 0;
static void finishEnvironment(otexstream & os, OutputParams const & runparams,
- TeXEnvironmentData const & data)
+ TeXEnvironmentData const & data)
{
if (open_encoding_ == CJK && data.cjk_nested) {
// We need to close the encoding even if it does not change
}
if (data.style->isEnvironment()) {
- os << "\\end{" << from_ascii(data.style->latexname()) << "}\n";
+ os << breakln
+ << "\\end{" << from_ascii(data.style->latexname()) << "}\n";
prev_env_language_ = data.par_language;
if (runparams.encoding != data.prev_encoding) {
runparams.encoding = data.prev_encoding;
}
if (data.leftindent_open) {
- os << "\\end{LyXParagraphLeftIndent}\n";
+ os << breakln << "\\end{LyXParagraphLeftIndent}\n";
prev_env_language_ = data.par_language;
if (runparams.encoding != data.prev_encoding) {
runparams.encoding = data.prev_encoding;
os << setEncoding(data.prev_encoding->iconvName());
}
}
+
+ // Check whether we should output a blank line after the environment
+ if (!data.style->nextnoindent)
+ os << '\n';
}
// Or par->params().depth() > current_depth
// Or par->params().leftIndent() != current_left_indent)
- if (par->layout().isParagraph()) {
- // 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
- // three in a row.
- os << '\n';
- }
-
// FIXME This test should not be necessary.
// We should perhaps issue an error if it is.
bool const force_plain_layout = text.inset().forcePlainLayout();
if (argnr == 0)
return;
+ // Default and preset args are always output, so if they require
+ // other arguments, consider this.
+ Layout::LaTeXArgMap::const_iterator lit = latexargs.begin();
+ Layout::LaTeXArgMap::const_iterator const lend = latexargs.end();
+ for (; lit != lend; ++lit) {
+ Layout::latexarg arg = (*lit).second;
+ if ((!arg.presetarg.empty() || !arg.defaultarg.empty()) && !arg.requires.empty()) {
+ vector<string> req = getVectorFromString(arg.requires);
+ required.insert(required.end(), req.begin(), req.end());
+ }
+ }
+
for (unsigned int i = 1; i <= argnr; ++i) {
map<int, InsetArgument const *>::const_iterator lit = ilist.find(i);
bool inserted = false;
string const name = prefix + convert<string>(i);
if ((*lait).first == name) {
Layout::latexarg arg = (*lait).second;
+ docstring preset = arg.presetarg;
+ if (!arg.defaultarg.empty()) {
+ if (!preset.empty())
+ preset += ",";
+ preset += arg.defaultarg;
+ }
if (arg.mandatory) {
docstring ldelim = arg.ldelim.empty() ?
from_ascii("{") : arg.ldelim;
docstring rdelim = arg.rdelim.empty() ?
from_ascii("}") : arg.rdelim;
- os << ldelim << arg.presetarg << rdelim;
- } else if (!arg.presetarg.empty()) {
- 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;
- os << ldelim << arg.presetarg << rdelim;
+ os << ldelim << preset << rdelim;
+ } else if (!preset.empty()) {
+ docstring ldelim = arg.ldelim.empty() ?
+ from_ascii("[") : arg.ldelim;
+ docstring rdelim = arg.rdelim.empty() ?
+ from_ascii("]") : arg.rdelim;
+ os << ldelim << preset << rdelim;
} else if (find(required.begin(), required.end(),
(*lait).first) != required.end()) {
docstring ldelim = arg.ldelim.empty() ?
string const & everypar,
int start_pos, int end_pos)
{
- BufferParams const & bparams = buf.params();
+ BufferParams const & bparams = runparams_in.is_child
+ ? buf.masterParams() : buf.params();
ParagraphList const & paragraphs = text.paragraphs();
Paragraph const & par = paragraphs.at(pit);
// FIXME This check should not really be needed.
if (style.pass_thru) {
Font const outerfont = text.outerFont(pit);
- runparams.local_font = &par.getFirstFontSettings(bparams);
parStartCommand(par, os, runparams, style);
par.latex(bparams, outerfont, os, runparams, start_pos, end_pos);
os << '\n';
if (!style.parbreak_is_newline) {
os << '\n';
- } else if (nextpar) {
+ } else if (nextpar && !style.isEnvironment()) {
Layout const nextstyle = text.inset().forcePlainLayout()
? bparams.documentClass().plainLayout()
: nextpar->layout();
par.getFontSettings(bparams, i).language()->encoding();
if (encoding->package() != Encoding::CJK
&& runparams.encoding->package() == Encoding::inputenc
- && c < 0x80)
+ && isASCII(c))
continue;
if (par.isInset(i))
break;
bool const useSetSpace = bparams.documentClass().provides("SetSpace");
if (par.allowParagraphCustomization()) {
if (par.params().startOfAppendix()) {
- os << "\\appendix\n";
+ os << "\n\\appendix\n";
}
if (!par.params().spacing().isDefault()
}
}
- runparams.local_font = &par.getFirstFontSettings(bparams);
parStartCommand(par, os, runparams, style);
Font const outerfont = text.outerFont(pit);
switch (style.latextype) {
case LATEX_ITEM_ENVIRONMENT:
case LATEX_LIST_ENVIRONMENT:
- if (nextpar && (par.params().depth() < nextpar->params().depth()))
+ if (nextpar && par.params().depth() < nextpar->params().depth())
pending_newline = true;
break;
case LATEX_ENVIRONMENT: {
&& (runparams.isLastPar || !nextpar->hasSameLayout(par))) {
if (pending_newline)
os << '\n';
- os << from_ascii(par.params().spacing().writeEnvirEnd(useSetSpace));
+
+ string const endtag =
+ par.params().spacing().writeEnvirEnd(useSetSpace);
+ if (prefixIs(endtag, "\\end{"))
+ os << breakln;
+
+ os << from_ascii(endtag);
pending_newline = true;
}
}
// not for ArabTeX
&& (par_language->lang() != "arabic_arabtex"
&& outer_language->lang() != "arabic_arabtex")
- // have we opened and \L or \R environment?
+ // have we opened an \L or \R environment?
&& runparams.local_font != 0
&& runparams.local_font->isRightToLeft() != par_language->rightToLeft()
// are we about to close the language?
if (closing_rtl_ltr_environment)
os << "}";
+ bool const last_was_separator =
+ par.size() > 0 && par.isEnvSeparator(par.size() - 1);
+
if (pending_newline) {
if (unskip_newline)
// prevent unwanted whitespace
os << '%';
- os << '\n';
+ if (!os.afterParbreak() && !last_was_separator)
+ os << '\n';
}
// if this is a CJK-paragraph and the next isn't, close CJK
// we don't need a newline for the last paragraph!!!
// Note from JMarc: we will re-add a \n explicitly in
// TeXEnvironment, because it is needed in this case
- if (nextpar) {
+ if (nextpar && !os.afterParbreak() && !last_was_separator) {
+ // Make sure to start a new line
+ os << breakln;
Layout const & next_layout = nextpar->layout();
- if (style == next_layout
- // no blank lines before environments!
- || !next_layout.isEnvironment()
- // unless there's a depth change
- // FIXME What we really want to do here is put every \begin and \end
- // tag on a new line (which was not the case with nested environments).
- // But in the present state of play, we don't have access to the
- // information whether the current TeX row is empty or not.
- // For some ideas about how to fix this, see this thread:
- // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg145787.html
- || nextpar->params().depth() != par.params().depth()) {
- os << '\n';
+ // A newline '\n' is always output before a command,
+ // so avoid doubling it.
+ if (!next_layout.isCommand()) {
+ // Here we now try to avoid spurious empty lines by
+ // outputting a paragraph break only if: (case 1) the
+ // paragraph style allows parbreaks and no \begin, \end
+ // or \item tags are going to follow (i.e., if the next
+ // isn't the first or the current isn't the last
+ // paragraph of an environment or itemize) and the
+ // depth and alignment of the following paragraph is
+ // unchanged, or (case 2) the following is a
+ // non-environment paragraph whose depth is increased
+ // but whose alignment is unchanged, or (case 3) the
+ // paragraph is not an environment and the next one is a
+ // non-itemize-like env at lower depth, or (case 4) the
+ // paragraph is a command not followed by an environment
+ // and the alignment of the current and next paragraph
+ // is unchanged, or (case 5) the current alignment is
+ // changed and a standard paragraph follows.
+ DocumentClass const & tclass = bparams.documentClass();
+ if ((style == next_layout
+ && !style.parbreak_is_newline
+ && style.latextype != LATEX_ITEM_ENVIRONMENT
+ && style.latextype != LATEX_LIST_ENVIRONMENT
+ && style.align == par.getAlign()
+ && nextpar->getDepth() == par.getDepth()
+ && nextpar->getAlign() == par.getAlign())
+ || (!next_layout.isEnvironment()
+ && nextpar->getDepth() > par.getDepth()
+ && nextpar->getAlign() == par.getAlign())
+ || (!style.isEnvironment()
+ && next_layout.latextype == LATEX_ENVIRONMENT
+ && nextpar->getDepth() < par.getDepth())
+ || (style.isCommand()
+ && !next_layout.isEnvironment()
+ && style.align == par.getAlign()
+ && next_layout.align == nextpar->getAlign())
+ || (style.align != par.getAlign()
+ && tclass.isDefaultLayout(next_layout))) {
+ os << '\n';
+ }
}
}
OutputParams const & runparams,
string const & everypar)
{
+ LASSERT(runparams.par_begin <= runparams.par_end,
+ { os << "% LaTeX Output Error\n"; return; } );
+
BufferParams const & bparams = buf.params();
bool const maintext = text.isMainText();
}
ParagraphList const & paragraphs = text.paragraphs();
- LASSERT(runparams.par_begin <= runparams.par_end, /**/);
if (runparams.par_begin == runparams.par_end) {
// The full doc will be exported but it is easier to just rely on
{
Encoding const & oldEnc = *runparams.encoding;
bool moving_arg = runparams.moving_arg;
- if (!force && ((bparams.inputenc != "auto" && bparams.inputenc != "default")
- || moving_arg))
+ // If we switch from/to CJK, we need to switch anyway, despite custom inputenc
+ bool const from_to_cjk =
+ (oldEnc.package() == Encoding::CJK && newEnc.package() != Encoding::CJK)
+ || (oldEnc.package() != Encoding::CJK && newEnc.package() == Encoding::CJK);
+ if (!force && !from_to_cjk
+ && ((bparams.inputenc != "auto" && bparams.inputenc != "default") || moving_arg))
return make_pair(false, 0);
// Do nothing if the encoding is unchanged.