]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/InsetMathScript.cpp
Improve metrics for \limits in display mode
[lyx.git] / src / mathed / InsetMathScript.cpp
index b4cd5909be06cca3c8dfff89a12ad90c948cffb7..c461c9ca748d14232a04ddc5e35fb641351e6bd6 100644 (file)
@@ -226,7 +226,8 @@ int InsetMathScript::dx0(BufferView const & bv) const
 {
        LASSERT(hasDown(), return 0);
        Dimension const dim = dimension(bv);
-       return hasLimits() ? (dim.wid - down().dimension(bv).width()) / 2 : nwid(bv);
+       return hasLimits() ? (dim.wid - down().dimension(bv).width()) / 2
+               : nwid(bv) + min(nker(&bv), 0);
 }
 
 
@@ -234,7 +235,8 @@ int InsetMathScript::dx1(BufferView const & bv) const
 {
        LASSERT(hasUp(), return 0);
        Dimension const dim = dimension(bv);
-       return hasLimits() ? (dim.wid - up().dimension(bv).width()) / 2 : nwid(bv) + nker(&bv);
+       return hasLimits() ? (dim.wid - up().dimension(bv).width()) / 2
+               : nwid(bv) + max(nker(&bv), 0);
 }
 
 
@@ -265,25 +267,40 @@ int InsetMathScript::ndes(BufferView const & bv) const
 
 int InsetMathScript::nker(BufferView const * bv) const
 {
-       if (!nuc().empty()) {
-               int kerning = nuc().kerning(bv);
-               return kerning > 0 ? kerning : 0;
-       }
+       if (!nuc().empty())
+               return nuc().kerning(bv);
        return 0;
 }
 
 
+MathClass InsetMathScript::mathClass() const
+{
+       // FIXME: this is a hack, since the class will not be correct if
+       // the nucleus has several elements or if the last element is a math macro
+       // or a macro argument proxy.
+       // The correct implementation would require to linearize the nucleus.
+       if (nuc().empty())
+               return MC_ORD;
+       else {
+               // return the class of last element since this is the one that counts.
+               MathClass mc = nuc().back()->mathClass();
+               return (mc == MC_UNKNOWN) ? MC_ORD : mc;
+       }
+}
+
+
 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);
+               cell(1).metrics(mi, dim1, !hasLimits());
        if (nargs() > 2)
-               cell(2).metrics(mi, dim2);
+               cell(2).metrics(mi, dim2, !hasLimits());
 
        dim.wid = 0;
        BufferView & bv = *mi.base.bv;
@@ -303,9 +320,9 @@ void InsetMathScript::metrics(MetricsInfo & mi, Dimension & dim) const
                        dim.wid = max(dim.wid, dimdown.width());
        } else {
                if (hasUp())
-                       dim.wid = max(dim.wid, nker(mi.base.bv) + dimup.width());
+                       dim.wid = max(dim.wid, max(nker(mi.base.bv), 0) + dimup.width());
                if (hasDown())
-                       dim.wid = max(dim.wid, dimdown.width());
+                       dim.wid = max(dim.wid, min(nker(mi.base.bv), 0) + dimdown.width());
                dim.wid += nwid(bv);
        }
        int na = nasc(bv);
@@ -320,12 +337,12 @@ void InsetMathScript::metrics(MetricsInfo & mi, Dimension & dim) const
                dim.des = max(nd, des);
        } else
                dim.des = nd;
-       metricsMarkers(dim);
 }
 
 
 void InsetMathScript::draw(PainterInfo & pi, int x, int y) const
 {
+       Changer dummy2 = pi.base.changeEnsureMath();
        BufferView & bv = *pi.base.bv;
        if (!nuc().empty())
                nuc().draw(pi, x + dxx(bv), y);
@@ -339,7 +356,6 @@ void InsetMathScript::draw(PainterInfo & pi, int x, int y) const
                up().draw(pi, x + dx1(bv), y - dy1(bv));
        if (hasDown())
                down().draw(pi, x + dx0(bv), y + dy0(bv));
-       drawMarkers(pi, x, y);
 }
 
 
@@ -365,6 +381,20 @@ void InsetMathScript::drawT(TextPainter & pain, int x, int y) const
 }
 
 
+// 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
 {
@@ -375,8 +405,9 @@ bool InsetMathScript::hasLimits() const
                return false;
 
        // we can only display limits if the nucleus wants some
-       if (nuc().empty())
+       if (!allowsLimits())
                return false;
+       // FIXME: this is some hardcoding done in InsetMathSymbol::metrics.
        if (!nuc().back()->isScriptable())
                return false;
 
@@ -616,8 +647,8 @@ void InsetMathScript::mathmlize(MathStream & os) const
                os << "<mrow />";
 
        if (u && d)
-               os << MTag("mrow") << down() << ETag("mrow") 
-                  << MTag("mrow") << up() << ETag("mrow") 
+               os << MTag("mrow") << down() << ETag("mrow")
+                  << MTag("mrow") << up() << ETag("mrow")
                   << ETag(l ? "munderover" : "msubsup");
        else if (u)
                os << MTag("mrow") << up() << ETag("mrow") << ETag(l ? "mover" : "msup");
@@ -735,6 +766,9 @@ 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")
@@ -758,15 +792,19 @@ bool InsetMathScript::getStatus(Cursor & cur, FuncRequest const & cmd,
                                FuncStatus & flag) const
 {
        if (cmd.action() == LFUN_MATH_LIMITS) {
-               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);
+               // 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;
        }