# If the wasysym integrals are really wanted then one has to load the package
# manually and disable automatic loading of amsmath and esint.
iffont esint
-int esint 001|002 0 mathop ∫ ∫ esint|amsmath
intop esint 001|002 0 mathop ∫ ∫ esint
-iint esint 003|004 0 mathop ∬ ∬ esint|amsmath
iintop esint 003|004 0 mathop ∬ ∬ esint
-iiint esint 005|006 0 mathop ∭ ∭ esint|amsmath
iiintop esint 005|006 0 mathop ∭ ∭ esint
-iiiint esint 007|008 0 mathop ⨌ ⨌ esint|amsmath
iiiintop esint 007|008 0 mathop ⨌ ⨌ esint
#9 codepoint forbidden in qt4, 10,12,13 in qt5
-oint esint 043|044 0 mathop ∮ ∮ esint
ointop esint 043|044 0 mathop ∮ ∮ esint
-oiint esint 045|046 0 mathop ∯ ∯ esint
oiintop esint 045|046 0 mathop ∯ ∯ esint
-sqint esint 015|016 0 mathop ⨖ ⨖ esint
sqintop esint 015|016 0 mathop ⨖ ⨖ esint
-sqiint esint 017|018 0 mathop x esint
sqiintop esint 017|017 0 mathop x esint
-dotsint esint 041|042 0 mathop ∫⋯∫ ∫⋯∫ esint
dotsintop esint 041|042 0 mathop ∫⋯∫ ∫⋯∫ esint
-ointctrclockwise esint 023|024 0 mathop ∳ ∳ esint
ointctrclockwiseop esint 023|024 0 mathop ∳ ∳ esint
-ointclockwise esint 025|026 0 mathop ∲ ∲ esint
ointclockwiseop esint 025|026 0 mathop ∲ ∲ esint
else
-int cmex 82|90 242 mathop ∫ ∫ esint|amsmath
intop cmex 82|90 242 mathop ∫ ∫ esint
-iint wasy 115|120 0 mathop ∬ ∬ esint|amsmath
iintop wasy 115|120 0 mathop &Int ∬ esint
-iiint wasy 116|121 0 mathop ∭ ∭ esint|amsmath
iiintop wasy 116|121 0 mathop ∭ ∭ esint
-\def\iiiint{\int\kern-6mu\int\kern-6mu\int\kern-6mu\int} esint|amsmath
\def\iiiintop{\int\kern-6mu\int\kern-6mu\int\kern-6mu\int} esint
-\def\dotsint{\int\kern-3mu\cdots\kern-3mu\int} esint
-\def\dotsintop{\int\kern-3mu\cdots\kern-3mu\int} esint
-oint cmex 72|73 0 mathop ∮ ∮ esint
ointop cmex 72|73 0 mathop ∮ ∮ esint
-oiint wasy 118|123 0 mathop ∯ ∯ esint
oiintop wasy 118|123 0 mathop ∯ ∯ esint
-\def\sqint{\square\kern-17mu\int\kern6mu} esint
\def\sqintop{\square\kern-17mu\int\kern6mu} esint
-\def\sqiint{\square\kern-20mu\iint\kern3mu} esint
\def\sqiintop{\square\kern-20mu\iint\kern3mu} esint
-\def\ointctrclockwise{\circlearrowleft\kern-21mu\int\kern6mu} esint
+\def\dotsintop{\int\kern-3mu\cdots\kern-3mu\int} esint
\def\ointctrclockwiseop{\circlearrowleft\kern-21mu\int\kern6mu} esint
-\def\ointclockwise{\circlearrowright\kern-21mu\int\kern6mu} esint
\def\ointclockwiseop{\circlearrowright\kern-21mu\int\kern6mu} esint
endif
+\def\int{\intop\nolimits} mathop ∫ ∫ esint|amsmath
+\def\iint{\iintop\nolimits} mathop ∬ ∬ esint|amsmath
+\def\iiint{\iiintop\nolimits} mathop ∭ ∭ esint|amsmath
+\def\iiiint{\iiiintop\nolimits} mathop ⨌ ⨌ esint|amsmath
+\def\oint{\ointop\nolimits} mathop ∮ ∮ esint
+\def\oiint{\oiintop\nolimits} mathop ∯ ∯ esint
+\def\sqint{\sqintop\nolimits} mathop ⨖ ⨖ esint
+\def\sqiint{\sqiintop\nolimits} mathop x esint
+\def\dotsint{\dotsintop\nolimits} mathop ∫⋯∫ ∫⋯∫
+\def\ointctrclockwise{\ointctrclockwise\nolimits} mathop ∲ ∲ esint
+\def\ointclockwise{\ointclockwise\nolimits} mathop ∲ ∲ esint
-varointclockwise esint 027|028 0 mathop ∲ ∲ esint
varointclockwiseop esint 027|028 0 mathop ∲ ∲ esint
-varointctrclockwise esint 029|030 0 mathop ∳ ∳ esint
varointctrclockwiseop esint 029|030 0 mathop ∳ ∳ esint
-fint esint 031|032 0 mathop ⨏ ⨏ esint
fintop esint 031|032 0 mathop ⨏ ⨏ esint
-varoiint esint 033|034 0 mathop ∯ ∯ esint
varoiintop esint 033|034 0 mathop ∯ ∯ esint
-landupint esint 035|036 0 mathop x x esint
landupintop esint 035|036 0 mathop x x esint
-landdownint esint 037|038 0 mathop x x esint
landdownintop esint 037|038 0 mathop x x esint
+\def\varointclockwise{\varointclockwiseop\limits} mathop ∲ ∲ esint
+\def\varointctrclockwise{\varointctrclockwiseop\limits} mathop ∳ ∳ esint
+\def\fint{\fintop\limits} mathop ⨏ ⨏ esint
+\def\varoiint{\varoiintop\limits} mathop ∯ ∯ esint
+\def\landupint{\landupintop\limits} mathop x x esint
+\def\landdownint{\landdownintop\limits} mathop x x esint
+
# From the amsmath package:
-\def\idotsint{\int\kern-3mu\cdots\kern-3mu\int} amsmath
+\def\idotsint{\int\kern-3mu\cdots\kern-3mu\int\limits} amsmath
log lyxblacktext 0 0 func x x
}
-MathClass InsetMath::mathClass() const
-{
- return MC_ORD;
-}
-
-
InsetMath::marker_type InsetMath::marker(BufferView const *) const
{
return nargs() > 0 ? MARKER : NO_MARKER;
}
+/// write LaTeX and LyX code
+void InsetMath::writeLimits(WriteStream & os) const
+{
+ if (limits() == LIMITS) {
+ os << "\\limits";
+ os.pendingSpace(true);
+ } else if (limits() == NO_LIMITS) {
+ os << "\\nolimits ";
+ os.pendingSpace(true);
+ }
+}
+
+
void InsetMath::dump() const
{
lyxerr << "---------------------------------------------" << endl;
HullType hullType(docstring const & name);
docstring hullName(HullType type);
+
+enum Limits {
+ // what is obtained with \c \\nolimits
+ NO_LIMITS = -1,
+ // the default
+ AUTO_LIMITS = 0,
+ // what is obtained with \c \\limits
+ LIMITS = 1
+};
+
+
/**
Abstract base class for all math objects. A math insets is for use of the
virtual InsetMathSpecialChar const * asSpecialCharInset() const { return nullptr; }
/// The class of the math object (used primarily for spacing)
- virtual MathClass mathClass() const;
+ virtual MathClass mathClass() const { return MC_ORD; }
/// Add this inset to a math row. Return true if contents got added
virtual bool addToMathRow(MathRow &, MetricsInfo & mi) const;
/// Hook that is run before metrics computation starts
/// Hook that is run after drawing
virtual void afterDraw(PainterInfo const &) const {}
- /// identifies things that can get scripts
- virtual bool isScriptable() const { return false; }
/// will this get written as a single block in {..}
virtual bool extraBraces() const { return false; }
/// return the content as char if the inset is able to do so
virtual char_type getChar() const { return 0; }
- /// identifies things that can get \limits or \nolimits
- virtual bool takesLimits() const { return false; }
+
+ /// Whether the inset allows \(no)limits
+ bool allowsLimitsChange() const { return mathClass() == MC_OP; }
+ /// The default limits value
+ virtual Limits defaultLimits() const { return NO_LIMITS; }
+ /// whether the inset has limit-like sub/superscript
+ virtual Limits limits() const { return AUTO_LIMITS; }
+ /// sets types of sub/superscripts
+ virtual void limits(Limits) {}
+ /// write limits status for LaTeX and LyX code
+ void writeLimits(WriteStream & os) const;
/// replace things by other things
virtual void replace(ReplaceData &) {}
InsetMathDecoration::InsetMathDecoration(Buffer * buf, latexkeys const * key)
- : InsetMathNest(buf, 1), key_(key), dh_(0), dy_(0), dw_(0)
+ : InsetMathNest(buf, 1), key_(key)
{
// lyxerr << " creating deco " << key->name << endl;
}
}
-bool InsetMathDecoration::isScriptable() const
-{
- return mathClass() == MC_OP;
-}
-
-
bool InsetMathDecoration::protect() const
{
return
os << '\\' << key_->name << '{';
ModeSpecifier specifier(os, currentMode());
os << cell(0) << '}';
+ writeLimits(os);
}
void infoize(odocstream & os) const;
///
MathClass mathClass() const;
- ///
- bool isScriptable() const;
+ /// The default limits value
+ Limits defaultLimits() const { return allowsLimitsChange() ? LIMITS : NO_LIMITS; }
+ /// whether the inset has limit-like sub/superscript
+ Limits limits() const { return limits_; }
+ /// sets types of sub/superscripts
+ void limits(Limits lim) { limits_ = lim; }
///
void validate(LaTeXFeatures & features) const;
///
///
latexkeys const * key_;
+ ///
+ Limits limits_ = AUTO_LIMITS;
+ // FIXME: this should depend on BufferView
/// height cache of deco
- mutable int dh_;
+ mutable int dh_ = 0;
/// vertical offset cache of deco
- mutable int dy_;
+ mutable int dy_ = 0;
/// width for non-wide deco
- mutable int dw_;
+ mutable int dw_ = 0;
};
} // namespace lyx
return has_contents;
}
+/// Whether the inset allows \(no)limits
+bool InsetMathMacro::allowsLimitsChange() const
+{
+ // similar to the code in mathClass(), except that we search for
+ // the right-side class.
+ MathClass mc = MC_UNKNOWN;
+ if (MacroData const * m = macroBackup()) {
+ // If it is a global macro and is defined explicitly
+ if (m->symbol())
+ mc = string_to_class(m->symbol()->extra);
+ }
+ // Otherwise guess from the expanded macro
+ if (mc == MC_UNKNOWN)
+ mc = d->expanded_.lastMathClass();
+
+ return mc == MC_OP;
+}
+
+
+Limits InsetMathMacro::defaultLimits() const
+{
+ if (d->expanded_.empty())
+ return NO_LIMITS;
+ // Guess from the expanded macro
+ InsetMath const * in = d->expanded_.back().nucleus();
+ Limits const lim = in->limits() == AUTO_LIMITS
+ ? in->defaultLimits() : in->limits();
+ LATTEST(lim != AUTO_LIMITS);
+ return lim;
+}
+
+
void InsetMathMacro::beforeMetrics() const
{
d->macro_->lock();
// add space if there was no argument
if (first)
os.pendingSpace(true);
+
+ // write \(no)limits modifiers if relevant
+ writeLimits(os);
}
/// If the macro is in normal edit mode, dissolve its contents in
/// the row. Otherwise, just insert the inset.
bool addToMathRow(MathRow &, MetricsInfo & mi) const;
+
+ /// Whether the inset allows \(no)limits
+ bool allowsLimitsChange() const;
+ /// The default limits value
+ Limits defaultLimits() const;
+ /// whether the inset has limit-like sub/superscript
+ Limits limits() const { return limits_; }
+ /// sets types of sub/superscripts
+ void limits(Limits lim) { limits_ = lim; }
+
///
void beforeMetrics() const;
///
///
bool editMode(BufferView const * bv) const;
+ ///
+ Limits limits_ = AUTO_LIMITS;
+
///
class Private;
///
// FIXME: support other font changes here as well?
}
-
void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
{
//LYXERR0("InsetMathNest: request: " << cmd);
}
break;
+ case LFUN_MATH_LIMITS: {
+ InsetMath * in = 0;
+ if (cur.pos() < cur.lastpos() && cur.nextMath().allowsLimitsChange())
+ in = &cur.nextMath();
+ else if (cur.pos() > 0 && cur.prevMath().allowsLimitsChange())
+ in = &cur.prevMath();
+ else if (cur.lastpos() > 0 && cur.cell().back()->allowsLimitsChange())
+ in = cur.cell().back().nucleus();
+ // only when nucleus allows this
+ if (!in)
+ return;
+ cur.recordUndoInset();
+ if (!cmd.argument().empty()) {
+ if (cmd.argument() == "limits")
+ in->limits(LIMITS);
+ else if (cmd.argument() == "nolimits")
+ in->limits(NO_LIMITS);
+ else
+ in->limits(AUTO_LIMITS);
+ } else if (in->limits() == AUTO_LIMITS)
+ in->limits(in->defaultLimits() == LIMITS ? NO_LIMITS : LIMITS);
+ else
+ in->limits(AUTO_LIMITS);
+ return;
+ }
+
default:
InsetMath::doDispatch(cur, cmd);
break;
break;
}
+ case LFUN_MATH_LIMITS: {
+ InsetMath * in = 0;
+ if (cur.pos() < cur.lastpos() && cur.nextMath().allowsLimitsChange())
+ in = &cur.nextMath();
+ else if (cur.pos() > 0 && cur.prevMath().allowsLimitsChange())
+ in = &cur.prevMath();
+ else if (cur.lastpos() > 0 && cur.cell().back()->allowsLimitsChange())
+ in = cur.cell().back().nucleus();
+ if (in) {
+ if (!cmd.argument().empty()) {
+ if (cmd.argument() == "limits")
+ flag.setOnOff(in->limits() == LIMITS);
+ else if (cmd.argument() == "nolimits")
+ flag.setOnOff(in->limits() == NO_LIMITS);
+ else
+ flag.setOnOff(in->limits() == AUTO_LIMITS);
+ }
+ flag.setEnabled(true);
+ } else
+ flag.setEnabled(false);
+ return true;
+ }
+
default:
ret = false;
break;
bool InsetMathNest::interpretString(Cursor & cur, docstring const & str)
{
+ if (str == "\\limits" || str == "\\nolimits") {
+ if (cur.pos() > 0 && cur.prevMath().allowsLimitsChange()) {
+ cur.prevMath().limits(str == "\\limits" ? LIMITS : NO_LIMITS);
+ return true;
+ } else {
+ cur.message(bformat(_("Cannot apply %1$s here."), str));
+ return false;
+ }
+ }
// Create a InsetMathBig from cur.cell()[cur.pos() - 1] and t if
// possible
if (!cur.empty() && cur.pos() > 0 &&
#include "InsetMathScript.h"
#include "InsetMathBrace.h"
-#include "InsetMathSymbol.h"
#include "MathData.h"
#include "MathStream.h"
#include "MathSupport.h"
#include "BufferView.h"
#include "Cursor.h"
-#include "DispatchResult.h"
-#include "FuncRequest.h"
-#include "FuncStatus.h"
#include "LaTeXFeatures.h"
#include "MetricsInfo.h"
InsetMathScript::InsetMathScript(Buffer * buf)
- : InsetMathNest(buf, 1), cell_1_is_up_(false), limits_(0)
+ : InsetMathNest(buf, 1), cell_1_is_up_(false)
{}
InsetMathScript::InsetMathScript(Buffer * buf, bool up)
- : InsetMathNest(buf, 2), cell_1_is_up_(up), limits_(0)
+ : InsetMathNest(buf, 2), cell_1_is_up_(up)
{}
InsetMathScript::InsetMathScript(Buffer * buf, MathAtom const & at, bool up)
- : InsetMathNest(buf, 2), cell_1_is_up_(up), limits_(0)
+ : InsetMathNest(buf, 2), cell_1_is_up_(up)
{
LATTEST(nargs() >= 1);
cell(0).push_back(at);
if (!hasDown())
return nd;
int des = down().dimension(bv).ascent();
- if (hasLimits())
+ if (has_limits_)
des += nd + 2;
else {
int na = nasc(bv);
if (!hasUp())
return na;
int asc = up().dimension(bv).descent();
- if (hasLimits())
+ if (has_limits_)
asc += na + 2;
else {
int nd = ndes(bv);
{
LASSERT(hasDown(), return 0);
Dimension const dim = dimension(bv);
- return hasLimits() ? (dim.wid - down().dimension(bv).width()) / 2
+ return has_limits_ ? (dim.wid - down().dimension(bv).width()) / 2
: nwid(bv) + min(nker(&bv), 0);
}
{
LASSERT(hasUp(), return 0);
Dimension const dim = dimension(bv);
- return hasLimits() ? (dim.wid - up().dimension(bv).width()) / 2
+ return has_limits_ ? (dim.wid - up().dimension(bv).width()) / 2
: nwid(bv) + max(nker(&bv), 0);
}
int InsetMathScript::dxx(BufferView const & bv) const
{
Dimension const dim = dimension(bv);
- return hasLimits() ? (dim.wid - nwid(bv)) / 2 : 0;
+ return has_limits_ ? (dim.wid - nwid(bv)) / 2 : 0;
}
void InsetMathScript::metrics(MetricsInfo & mi, Dimension & dim) const
{
- Changer dummy2 = mi.base.changeEnsureMath();
Dimension dim0;
Dimension dim1;
Dimension dim2;
- cell(0).metrics(mi, dim0);
- Changer dummy = mi.base.changeScript();
- if (nargs() > 1)
- cell(1).metrics(mi, dim1, !hasLimits());
- if (nargs() > 2)
- cell(2).metrics(mi, dim2, !hasLimits());
+ {
+ // Keeps the changers local
+ Changer dummy2 = mi.base.changeEnsureMath();
+ cell(0).metrics(mi, dim0);
+ Changer dummy = mi.base.changeScript();
+ if (nargs() > 1)
+ cell(1).metrics(mi, dim1, !has_limits_);
+ if (nargs() > 2)
+ cell(2).metrics(mi, dim2, !has_limits_);
+ }
+ // we store this, because it is much easier
+ has_limits_ = hasLimits(mi.base.font);
dim.wid = 0;
BufferView & bv = *mi.base.bv;
if (hasDown())
dimdown = down().dimension(bv);
- if (hasLimits()) {
+ if (has_limits_) {
dim.wid = nwid(bv);
if (hasUp())
dim.wid = max(dim.wid, dimup.width());
}
-// FIXME: See InsetMathSymbol::takesLimits, which seems to attempt the
-// same in a hardcoded way. takeLimits use is currently commented out in
-// InsetMathScript::metrics. It seems that the mathop test is general
-// enough, but only time will tell.
-bool InsetMathScript::allowsLimits() const
-{
- if (nuc().empty())
- return false;
- // Only makes sense for insets of mathop class
- if (nuc().back()->mathClass() != MC_OP)
- return false;
- return true;
-}
-
-
-bool InsetMathScript::hasLimits() const
+bool InsetMathScript::hasLimits(FontInfo const & font) const
{
- // obvious cases
- if (limits_ == 1)
- return true;
- if (limits_ == -1)
+ if (font.style() != DISPLAY_STYLE)
return false;
-
- // we can only display limits if the nucleus wants some
- if (!allowsLimits())
- return false;
- // FIXME: this is some hardcoding done in InsetMathSymbol::metrics.
- if (!nuc().back()->isScriptable())
+ if (nuc().empty())
return false;
- if (nuc().back()->asSymbolInset()) {
- // \intop is an alias for \int\limits, \ointop == \oint\limits
- if (nuc().back()->asSymbolInset()->name().find(from_ascii("intop")) != string::npos)
- return true;
- // per default \int has limits beside the \int even in displayed formulas
- if (nuc().back()->asSymbolInset()->name().find(from_ascii("int")) != string::npos)
- return false;
- }
-
- // assume "real" limits for everything else
- return true;
+ Limits const lim = nuc().back()->limits() == AUTO_LIMITS
+ ? nuc().back()->defaultLimits() : nuc().back()->limits();
+ LASSERT(lim != AUTO_LIMITS, return false);
+ return lim == LIMITS;
}
return false;
// go up/down only if in the last position
// or in the first position of something with displayed limits
- if (cur.pos() == cur.lastpos() || (cur.pos() == 0 && hasLimits())) {
+ if (cur.pos() == cur.lastpos()
+ || (cur.pos() == 0 && has_limits_)) {
cur.idx() = idxOfScript(up);
cur.pos() = 0;
return true;
{
MathEnsurer ensurer(os);
- if (!nuc().empty()) {
+ if (!nuc().empty())
os << nuc();
- //if (nuc().back()->takesLimits()) {
- if (limits_ == -1)
- os << "\\nolimits ";
- if (limits_ == 1)
- os << "\\limits ";
- //}
- } else {
- if (os.firstitem())
- LYXERR(Debug::MATHED, "suppressing {} when writing");
- else
- os << "{}";
- }
+ else if (os.firstitem())
+ LYXERR(Debug::MATHED, "suppressing {} when writing");
+ else
+ os << "{}";
if (hasDown() /*&& !down().empty()*/)
os << "_{" << down() << '}';
{
bool d = hasDown() && !down().empty();
bool u = hasUp() && !up().empty();
- bool l = hasLimits();
+ // FIXME: the MathStream should be able to give us this information
+ bool l = has_limits_;
if (u && d)
ms << MTag(l ? "munderover" : "msubsup");
void InsetMathScript::infoize2(odocstream & os) const
{
- if (limits_)
- os << from_ascii(limits_ == 1 ? ", Displayed limits" : ", Inlined limits");
+ os << from_ascii(has_limits_ == 1 ? ", Displayed limits" : ", Inlined limits");
}
}
-void InsetMathScript::doDispatch(Cursor & cur, FuncRequest & cmd)
-{
- //LYXERR("InsetMathScript: request: " << cmd);
-
- if (cmd.action() == LFUN_MATH_LIMITS) {
- // only when nucleus allows this
- if (!allowsLimits())
- return;
- cur.recordUndoInset();
- if (!cmd.argument().empty()) {
- if (cmd.argument() == "limits")
- limits_ = 1;
- else if (cmd.argument() == "nolimits")
- limits_ = -1;
- else
- limits_ = 0;
- } else if (limits_ == 0)
- limits_ = hasLimits() ? -1 : 1;
- else
- limits_ = 0;
- return;
- }
-
- InsetMathNest::doDispatch(cur, cmd);
-}
-
-
-bool InsetMathScript::getStatus(Cursor & cur, FuncRequest const & cmd,
- FuncStatus & flag) const
-{
- if (cmd.action() == LFUN_MATH_LIMITS) {
- // only when nucleus allows this
- if (allowsLimits()) {
- if (!cmd.argument().empty()) {
- if (cmd.argument() == "limits")
- flag.setOnOff(limits_ == 1);
- else if (cmd.argument() == "nolimits")
- flag.setOnOff(limits_ == -1);
- else
- flag.setOnOff(limits_ == 0);
- }
- flag.setEnabled(true);
- } else
- flag.setEnabled(false);
- return true;
- }
-
- return InsetMathNest::getStatus(cur, cmd, flag);
-}
-
-
// the idea for dual scripts came from the eLyXer code
void InsetMathScript::validate(LaTeXFeatures & features) const
{
///
InsetMathScript * asScriptInset();
- /// set limits
- void limits(int lim) { limits_ = lim; }
- /// get limits
- int limits() const { return limits_; }
/// returns subscript. Always run 'hasDown' or 'has(false)' before!
MathData const & down() const;
/// returns subscript. Always run 'hasDown' or 'has(false)' before!
InsetCode lyxCode() const { return MATH_SCRIPT_CODE; }
///
void validate(LaTeXFeatures &features) const;
-protected:
- virtual void doDispatch(Cursor & cur, FuncRequest & cmd);
- /// do we want to handle this event?
- bool getStatus(Cursor & cur, FuncRequest const & cmd,
- FuncStatus & status) const;
private:
virtual Inset * clone() const;
/// returns x offset for main part
/// shifts the superscript to the right, and a negative value shifts the
/// subscript to the left.
int nker(BufferView const * bv) const;
- /// can one change how scripts are drawn?
- bool allowsLimits() const;
- /// where do we have to draw the scripts?
- bool hasLimits() const;
+ /// do we we have to draw the scripts above/below nucleus?
+ bool hasLimits(FontInfo const &) const;
/// clean up empty cells and return true if a cell has been deleted.
bool notifyCursorLeaves(Cursor const & old, Cursor & cur);
/// possible subscript (index 0) and superscript (index 1)
bool cell_1_is_up_;
- /// 1 - "limits", -1 - "nolimits", 0 - "default"
- int limits_;
+ /// remember whether we are in display mode (used by mathml output)
+ mutable bool has_limits_ = false;
};
#include "support/textutils.h"
#include "support/unique_ptr.h"
+using namespace std;
namespace lyx {
InsetMathSymbol::InsetMathSymbol(latexkeys const * l)
- : sym_(l), h_(0), kerning_(0), scriptable_(false)
+ : sym_(l)
{}
InsetMathSymbol::InsetMathSymbol(char const * name)
- : sym_(in_word_set(from_ascii(name))), h_(0),
- kerning_(0), scriptable_(false)
+ : sym_(in_word_set(from_ascii(name)))
{}
InsetMathSymbol::InsetMathSymbol(docstring const & name)
- : sym_(in_word_set(name)), h_(0), kerning_(0), scriptable_(false)
+ : sym_(in_word_set(name))
{}
}
+/// The default limits value
+Limits InsetMathSymbol::defaultLimits() const
+{
+ return (allowsLimitsChange() && sym_->extra != "func")
+ ? LIMITS : NO_LIMITS;
+}
+
+
void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
{
mathedSymbolDim(mi.base, dim, sym_);
dim.asc += h_;
dim.des -= h_;
}
-
- // set scriptable_
- //FIXME: get rid of that? Only "funclim" probably, along with
- // class==MC_OP. The issue is to implement \limits properly.
- scriptable_ = false;
- if (mi.base.font.style() == DISPLAY_STYLE)
- if (sym_->inset == "cmex" || sym_->inset == "esint" ||
- sym_->extra == "funclim" ||
- (sym_->inset == "stmry" && sym_->extra == "mathop"))
- scriptable_ = true;
}
}
-bool InsetMathSymbol::isScriptable() const
-{
- return scriptable_;
-}
-
-
-bool InsetMathSymbol::takesLimits() const
-{
- return
- sym_->inset == "cmex" ||
- sym_->inset == "lyxboldsymb" ||
- sym_->inset == "esint" ||
- sym_->extra == "funclim" ||
- (sym_->inset == "stmry" && sym_->extra == "mathop");
-}
-
-
void InsetMathSymbol::normalize(NormalStream & os) const
{
os << "[symbol " << name() << ']';
return;
os.pendingSpace(true);
+ writeLimits(os);
}
class latexkeys;
-/** "normal" symbols that don't take limits and don't grow in displayed
- * formulae.
- */
+// \xxx symbols that may take limits or grow in displayed formulæ.
class InsetMathSymbol : public InsetMath {
public:
///
MathClass mathClass() const;
///
bool isOrdAlpha() const;
- /// do we take scripts?
- bool isScriptable() const;
- /// do we take \limits or \nolimits?
- bool takesLimits() const;
+ /// The default limits value
+ Limits defaultLimits() const;
+ /// whether the inset has limit-like sub/superscript
+ Limits limits() const { return limits_; }
+ /// sets types of sub/superscripts
+ void limits(Limits lim) { limits_ = lim; }
/// identifies SymbolInset as such
InsetMathSymbol const * asSymbolInset() const { return this; }
/// the LaTeX name of the symbol (without the backslash)
///
latexkeys const * sym_;
///
- mutable int h_;
- /// cached superscript kerning
- mutable int kerning_;
+ Limits limits_ = AUTO_LIMITS;
+
+ // FIXME: these depend on BufferView
+
///
- mutable bool scriptable_;
+ mutable int h_ = 0;
+ /// cached superscript kerning
+ mutable int kerning_ = 0;
};
} // namespace lyx
}
+MathClass MathData::lastMathClass() const
+{
+ MathClass res = MC_ORD;
+ for (MathAtom const & at : *this) {
+ MathClass mc = at->mathClass();
+ if (mc != MC_UNKNOWN)
+ return res = mc;
+ }
+ return res;
+}
+
+
ostream & operator<<(ostream & os, MathData const & ar)
{
odocstringstream oss;
void metricsT(TextMetricsInfo const & mi, Dimension & dim) const;
/// redraw cell using cache metrics information
void drawT(TextPainter & pi, int x, int y) const;
- /// approximate the math class of the data
+ /// approximate mathclass of the data
MathClass mathClass() const;
+ /// math class of last interesting element
+ MathClass lastMathClass() const;
/// access to cached x coordinate of last drawing
int xo(BufferView const & bv) const;
bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
const mode_type mode, const bool numbered)
{
- int limits = 0;
InsetMathGrid::row_type cellrow = 0;
InsetMathGrid::col_type cellcol = 0;
MathData * cell = &grid.cell(grid.index(cellrow, cellcol));
p->nuc().erase(0);
parse(p->cell(p->idxOfScript(up)), FLAG_ITEM, mode);
- if (limits) {
- p->limits(limits);
- limits = 0;
- }
}
else if (t.character() == ']' && (flags & FLAG_BRACK_LAST)) {
}
else if (t.cs() == "limits" || t.cs() == "nolimits") {
- CatCode const cat = nextToken().cat();
- if (cat == catSuper || cat == catSub)
- limits = t.cs() == "limits" ? 1 : -1;
+ if (!cell->empty())
+ cell->back()->limits(t.cs() == "limits" ? LIMITS : NO_LIMITS);
else {
MathAtom at = createInsetMath(t.cs(), buf);
cell->push_back(at);