void CommandInset::write(WriteStream & os) const
{
- bool brace = ensureMath(os, needs_math_mode_);
+ MathEnsurer ensurer(os, needs_math_mode_);
os << '\\' << name_.c_str();
if (cell(1).size())
os << '[' << cell(1) << ']';
os << '{' << cell(0) << '}';
- os.pendingBrace(brace);
}
void InsetMath::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
docstring const s = name();
os << "\\" << s;
// We need an extra ' ' unless this is a single-char-non-ASCII name
// or anything non-ASCII follows
if (s.size() != 1 || isAlphaASCII(s[0]))
os.pendingSpace(true);
- os.pendingBrace(brace);
-}
-
-
-bool InsetMath::ensureMath(WriteStream & os, bool needs_math_mode) const
-{
- bool brace = os.pendingBrace();
- os.pendingBrace(false);
- if (os.latex() && os.textMode() && needs_math_mode) {
- os << "\\ensuremath{";
- os.textMode(false);
- brace = true;
- }
- return brace;
}
/// write content as something readable by Octave
virtual void octave(OctaveStream &) const;
- /// ensure math mode when writing LaTeX
- bool ensureMath(WriteStream & os, bool needs_math_mode = true) const;
-
/// plain text output in ucs4 encoding
int plaintext(odocstream &, OutputParams const &) const;
void InsetMathAMSArray::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\begin{" << name_ << '}';
InsetMathGrid::write(os);
os << "\\end{" << name_ << '}';
- os.pendingBrace(brace);
}
void InsetMathArray::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
if (os.fragile())
os << "\\protect";
os << "\\end{" << name_ << '}';
// adding a \n here is bad if the array is the last item
// in an \eqnarray...
-
- os.pendingBrace(brace);
}
void InsetMathBig::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << '\\' << name_ << delim_;
if (delim_[0] == '\\')
os.pendingSpace(true);
- os.pendingBrace(brace);
}
void InsetMathBoldSymbol::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
switch (kind_) {
case AMS_BOLD:
os << "\\boldsymbol{" << cell(0) << "}";
os << "\\hm{" << cell(0) << "}";
break;
}
- os.pendingBrace(brace);
}
void InsetMathBox::write(WriteStream & os) const
{
- bool textmode = os.textMode();
- os.textMode(true);
+ ModeSpecifier specifier(os, TEXT_MODE);
os << '\\' << name_ << '{' << cell(0) << '}';
- os.textMode(textmode);
}
void InsetMathFBox::write(WriteStream & os) const
{
- bool textmode = os.textMode();
- os.textMode(true);
+ ModeSpecifier specifier(os, TEXT_MODE);
os << "\\fbox{" << cell(0) << '}';
- os.textMode(textmode);
}
void InsetMathMakebox::write(WriteStream & os) const
{
- bool textmode = os.textMode();
- os.textMode(true);
+ ModeSpecifier specifier(os, TEXT_MODE);
os << (framebox_ ? "\\framebox" : "\\makebox");
if (cell(0).size() || !os.latex()) {
os << '[' << cell(0) << ']';
os << '[' << cell(1) << ']';
}
os << '{' << cell(2) << '}';
- os.textMode(textmode);
}
void InsetMathBoxed::write(WriteStream & os) const
{
- bool textmode = os.textMode();
- os.textMode(false);
+ ModeSpecifier specifier(os, MATH_MODE);
os << "\\boxed{" << cell(0) << '}';
- os.textMode(textmode);
}
void InsetMathCases::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
if (os.fragile())
os << "\\protect";
os << "\\begin{cases}\n";
if (os.fragile())
os << "\\protect";
os << "\\end{cases}";
- os.pendingBrace(brace);
}
void InsetMathDecoration::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
if (os.fragile() && protect())
os << "\\protect";
os << '\\' << key_->name << '{' << cell(0) << '}';
- os.pendingBrace(brace);
}
void InsetMathDelim::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\left" << convertDelimToLatexName(left_) << cell(0)
<< "\\right" << convertDelimToLatexName(right_);
- os.pendingBrace(brace);
}
void InsetMathEnv::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\begin{" << name_ << '}' << cell(0) << "\\end{" << name_ << '}';
- os.pendingBrace(brace);
}
void InsetMathFrac::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
-
+ MathEnsurer ensurer(os);
switch (kind_) {
case ATOP:
os << '{' << cell(0) << "\\atop " << cell(1) << '}';
os << "\\unit{" << cell(0) << '}';
break;
}
-
- os.pendingBrace(brace);
}
void InsetMathBinom::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
-
+ MathEnsurer ensurer(os);
switch (kind_) {
case BINOM:
os << "\\binom{" << cell(0) << "}{" << cell(1) << '}';
os << '{' << cell(0) << " \\brack " << cell(1) << '}';
break;
}
-
- os.pendingBrace(brace);
}
void InsetMathGrid::write(WriteStream & os) const
{
- bool brace = os.pendingBrace();
- os.pendingBrace(false);
-
+ MathEnsurer ensurer(os, false);
docstring eol;
for (row_type row = 0; row < nrows(); ++row) {
os << verboseHLine(rowinfo_[row].lines_);
}
for (col_type col = 0; col < lastcol; ++col) {
os << cell(index(row, col));
- if (os.pendingBrace()) {
- os.pendingBrace(false);
- os.textMode(true);
- os << '}';
- }
+ if (os.pendingBrace())
+ ModeSpecifier specifier(os, TEXT_MODE);
os << eocString(col, lastcol);
}
eol = eolString(row, emptyline, os.fragile());
}
os << s;
}
-
- os.pendingBrace(brace);
}
void InsetMathNest::write(WriteStream & os) const
{
- bool textmode = os.textMode();
- os.textMode(currentMode() == TEXT_MODE);
+ ModeSpecifier specifier(os, currentMode());
docstring const latex_name = name().c_str();
os << '\\' << latex_name;
for (size_t i = 0; i < nargs(); ++i)
os << "\\lyxlock";
os.pendingSpace(true);
}
- os.textMode(textmode);
}
void InsetMathOverset::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\overset{" << cell(0) << "}{" << cell(1) << '}';
- os.pendingBrace(brace);
}
void InsetMathPhantom::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
switch (kind_) {
case phantom:
os << "\\phantom{";
break;
}
os << cell(0) << '}';
- os.pendingBrace(brace);
}
void InsetMathRoot::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\sqrt[" << cell(0) << "]{" << cell(1) << '}';
- os.pendingBrace(brace);
}
void InsetMathScript::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
if (nuc().size()) {
os << nuc();
if (lock_ && !os.latex())
os << "\\lyxlock ";
-
- os.pendingBrace(brace);
}
void InsetMathSize::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "{\\" << key_->name << ' ' << cell(0) << '}';
- os.pendingBrace(brace);
}
void InsetMathSpace::write(WriteStream & os) const
{
if (space_ >= 0 && space_ < nSpace) {
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << '\\' << latex_mathspace[space_];
os.pendingSpace(true);
- os.pendingBrace(brace);
}
}
void InsetMathSplit::write(WriteStream & ws) const
{
- bool brace = ensureMath(ws);
+ MathEnsurer ensurer(ws);
if (ws.fragile())
ws << "\\protect";
ws << "\\begin{" << name_ << '}';
if (ws.fragile())
ws << "\\protect";
ws << "\\end{" << name_ << "}\n";
- ws.pendingBrace(brace);
}
void InsetMathSqrt::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\sqrt{" << cell(0) << '}';
- os.pendingBrace(brace);
}
void InsetMathStackrel::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\stackrel{" << cell(0) << "}{" << cell(1) << '}';
- os.pendingBrace(brace);
}
void InsetMathSubstack::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\substack{";
InsetMathGrid::write(os);
os << "}\n";
- os.pendingBrace(brace);
}
void InsetMathSymbol::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << '\\' << name();
- os.pendingBrace(brace);
// $,#, etc. In theory the restriction based on catcodes, but then
// we do not handle catcodes very well, let alone cat code changes,
void InsetMathTabular::write(WriteStream & os) const
{
- // This is a text mode tabular, so close any previous \ensuremath
- // command and set the proper mode.
- if (os.latex() && os.pendingBrace()) {
- os.pendingBrace(false);
- os << '}';
- }
- bool textmode = os.textMode();
- os.textMode(true);
+ ModeSpecifier specifier(os, TEXT_MODE);
if (os.fragile())
os << "\\protect";
os << "\\end{" << name_ << '}';
// adding a \n here is bad if the tabular is the last item
// in an \eqnarray...
-
- os.textMode(textmode);
}
void InsetMathUnderset::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\underset{" << cell(0) << "}{" << cell(1) << '}';
- os.pendingBrace(brace);
}
void InsetMathXArrow::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << '\\' << name_;
if (cell(1).size())
os << '[' << cell(1) << ']';
os << '{' << cell(0) << '}';
- os.pendingBrace(brace);
}
void InsetMathXYArrow::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\ar";
if (cell(0).size())
os << '[' << cell(0) << ']';
if (cell(1).size())
os << (up_ ? '^' : '_') << '{' << cell(1) << '}';
os << " ";
- os.pendingBrace(brace);
}
void InsetMathXYMatrix::write(WriteStream & os) const
{
- bool brace = ensureMath(os);
+ MathEnsurer ensurer(os);
os << "\\xymatrix";
switch (spacing_code_) {
case 'R':
os << '{';
InsetMathGrid::write(os);
os << "}\n";
- os.pendingBrace(brace);
}
#include "MathMacro.h"
#include "MathMacroArgument.h"
#include "MathParser.h"
+#include "MathStream.h"
#include "MathSupport.h"
#include "insets/InsetCommand.h"
}
+bool ensureMath(WriteStream & os, bool needs_math_mode, bool macro)
+{
+ bool brace = os.pendingBrace();
+ os.pendingBrace(false);
+ if (!os.latex())
+ return brace;
+ if (os.textMode() && needs_math_mode) {
+ os << "\\ensuremath{";
+ os.textMode(false);
+ brace = true;
+ } else if (macro && brace && !needs_math_mode) {
+ // This is a user defined macro, but not a MathMacro, so we
+ // cannot be sure what mode is needed. As it was entered in
+ // a text box, we restore the text mode.
+ os << '}';
+ os.textMode(true);
+ brace = false;
+ }
+ return brace;
+}
+
+
+bool ensureMode(WriteStream & os, InsetMath::mode_type mode)
+{
+ bool textmode = mode == InsetMath::TEXT_MODE;
+ if (os.latex() && textmode && os.pendingBrace()) {
+ os.os() << '}';
+ os.pendingBrace(false);
+ os.pendingSpace(false);
+ os.textMode(true);
+ }
+ bool oldmode = os.textMode();
+ os.textMode(textmode);
+ return oldmode;
+}
+
+
latexkeys const * in_word_set(docstring const & str)
{
MathWordList::iterator it = theWordList.find(str);
void MathMacro::write(WriteStream & os) const
{
- bool brace = os.pendingBrace();
- os.pendingBrace(false);
- if (os.latex()) {
- if (os.textMode() && macro_) {
- // This is for sure a math macro
- os << "\\ensuremath{";
- os.textMode(false);
- brace = true;
- } else if (brace && !macro_) {
- // Cannot tell, so don't mess with the mode
- os << '}';
- os.textMode(true);
- brace = false;
- }
- }
+ MathEnsurer ensurer(os, macro_ != 0, true);
// non-normal mode
if (displayMode_ != DISPLAY_NORMAL) {
os << "\\" << name();
os.pendingSpace(true);
- os.pendingBrace(brace);
return;
}
// add space if there was no argument
if (first)
os.pendingSpace(true);
-
- os.pendingBrace(brace);
}
#include "MathStream.h"
-#include "InsetMath.h"
#include "MathData.h"
#include "MathExtern.h"
#include "support/strfwd.h"
+#include "InsetMath.h"
// FIXME: Move to individual insets
#include "MetricsInfo.h"
///
WriteStream & operator<<(WriteStream &, unsigned int);
+/// ensure math mode, possibly by opening \ensuremath
+bool ensureMath(WriteStream & os, bool needs_math_mode = true, bool macro = false);
+
+/// ensure the requested mode, possibly by closing \ensuremath
+bool ensureMode(WriteStream & os, InsetMath::mode_type mode);
+
+
+/**
+ * MathEnsurer - utility class for ensuring math mode
+ *
+ * A local variable of this type can be used to either ensure math mode
+ * or delay the writing of a pending brace when outputting LaTeX.
+ *
+ * Example 1:
+ *
+ * MathEnsurer ensurer(os);
+ *
+ * If not already in math mode, inserts an \ensuremath command followed
+ * by an open brace. This brace will be automatically closed when exiting
+ * math mode. Math mode is automatically exited when writing something
+ * that doesn't explicitly require math mode.
+ *
+ * Example 2:
+ *
+ * MathEnsurer ensurer(os, false);
+ *
+ * Simply suspend writing a closing brace until the end of ensurer's scope.
+ *
+ * Example 3:
+ *
+ * MathEnsurer ensurer(os, needs_math_mode, true);
+ *
+ * The third parameter is set to true only for a user defined macro, which
+ * needs special handling. When it is a MathMacro, the needs_math_mode
+ * parameter is true and the behavior is as in Example 1. When the
+ * needs_math_mode parameter is false (not a MathMacro) and the macro
+ * was entered in a text box and we are in math mode, the mode is reset
+ * to text. This is because the macro was probably designed for text mode
+ * (given that it was entered in text mode and we have no way to tell the
+ * contrary).
+ */
+class MathEnsurer
+{
+public:
+ ///
+ explicit MathEnsurer(WriteStream & os, bool needs_math_mode = true, bool macro = false)
+ : os_(os), brace_(ensureMath(os, needs_math_mode, macro)) {}
+ ///
+ ~MathEnsurer() { os_.pendingBrace(brace_); }
+private:
+ ///
+ WriteStream & os_;
+ ///
+ bool brace_;
+};
+
+
+/**
+ * ModeSpecifier - utility class for specifying a given mode (math or text)
+ *
+ * A local variable of this type can be used to specify that a command or
+ * environment works in a given mode. For example, \mbox works in text
+ * mode, but \boxed works in math mode. Note that no mode changing commands
+ * are needed, but we have to track the current mode, hence this class.
+ *
+ * Example:
+ *
+ * ModeSpecifier specifier(os, TEXT_MODE);
+ *
+ * Sets the current mode to text mode.
+ *
+ * At the end of specifier's scope the mode is reset to its previous value.
+ */
+class ModeSpecifier
+{
+public:
+ ///
+ explicit ModeSpecifier(WriteStream & os, InsetMath::mode_type mode)
+ : os_(os), textmode_(ensureMode(os, mode)) {}
+ ///
+ ~ModeSpecifier() { os_.textMode(textmode_); }
+private:
+ ///
+ WriteStream & os_;
+ ///
+ bool textmode_;
+};
+
//