]> git.lyx.org Git - features.git/commitdiff
Fix bug #1424: Native \sideset inset
authorGeorg Baum <baum@lyx.org>
Sun, 17 Feb 2013 10:08:58 +0000 (11:08 +0100)
committerGeorg Baum <baum@lyx.org>
Sun, 17 Feb 2013 10:08:58 +0000 (11:08 +0100)
The toolbar image is the one Uwe attached to the bug report. Note that
\sideset works only for operators like \sum in the nucleus. LyX allows
any content, so you might get a LaTeX error. I don't know how to prevent
wrong content in the nucleus.

lib/Makefile.am
lib/images/math/sideset.png [new file with mode: 0644]
lib/ui/stdtoolbars.inc
src/Makefile.am
src/mathed/InsetMathScript.cpp
src/mathed/InsetMathSideset.cpp [new file with mode: 0644]
src/mathed/InsetMathSideset.h [new file with mode: 0644]
src/mathed/MathFactory.cpp
src/mathed/MathParser.cpp
src/mathed/MathSupport.cpp
src/mathed/MathSupport.h

index 2b620d3140177f7b35db83769d63a25253d58984..a428b3d1a78de74008accb2e0f48d2a104123ac2 100644 (file)
@@ -1109,6 +1109,7 @@ dist_imagesmath_DATA = \
        images/math/shortparallel.png \
        images/math/shortrightarrow.png \
        images/math/shortuparrow.png \
+       images/math/sideset.png \
        images/math/sigma.png \
        images/math/sigma2.png \
        images/math/sim.png \
diff --git a/lib/images/math/sideset.png b/lib/images/math/sideset.png
new file mode 100644 (file)
index 0000000..02a20fe
Binary files /dev/null and b/lib/images/math/sideset.png differ
index 92aaf9e628d27ac966339b72d48d38b3205e5673..5f4e246fbf3b9ddb1c2a7877e12036270ace71cd 100644 (file)
@@ -183,6 +183,7 @@ ToolbarSet
                Item "Insert sum" "math-insert \sum"
                Item "Insert integral" "math-insert \int"
                Item "Insert product" "math-insert \prod"
+               Item "Insert side scripts" "math-insert \sideset"
                Separator
                Item "Insert ( )" "math-delim ( )"
                Item "Insert [ ]" "math-delim [ ]"
index d3c52f5e90a30d5a4313f944ced70787dfd5630a..bdf0c7bbfec6464796218af17b90399b94f60ed0 100644 (file)
@@ -409,6 +409,7 @@ SOURCEFILESMATHED = \
        mathed/InsetMathRef.cpp \
        mathed/InsetMathRoot.cpp \
        mathed/InsetMathScript.cpp \
+       mathed/InsetMathSideset.cpp \
        mathed/InsetMathSize.cpp \
        mathed/InsetMathSpace.cpp \
        mathed/InsetMathSpecialChar.cpp \
@@ -477,6 +478,7 @@ HEADERFILESMATHED = \
        mathed/InsetMathRef.h \
        mathed/InsetMathRoot.h \
        mathed/InsetMathScript.h \
+       mathed/InsetMathSideset.h \
        mathed/InsetMathSize.h \
        mathed/InsetMathSpace.h \
        mathed/InsetMathSpecialChar.h \
index ba2be2f729adddff8a17a16e66fabd886de89c64..d080d0831f090e75fba5b6c48d9915f5f907f719 100644 (file)
@@ -16,7 +16,6 @@
 #include "FuncRequest.h"
 #include "FuncStatus.h"
 #include "InsetMathBrace.h"
-#include "InsetMathFont.h"
 #include "InsetMathScript.h"
 #include "InsetMathSymbol.h"
 #include "LaTeXFeatures.h"
@@ -28,7 +27,6 @@
 
 #include "support/lassert.h"
 
-#include <ostream>
 
 using namespace std;
 
@@ -148,31 +146,6 @@ MathData & InsetMathScript::nuc()
 }
 
 
-namespace {
-
-bool isAlphaSymbol(MathAtom const & at)
-{
-       if (at->asCharInset() ||
-                       (at->asSymbolInset() &&
-                        at->asSymbolInset()->isOrdAlpha()))
-               return true;
-
-       if (at->asFontInset()) {
-               MathData const & ar = at->asFontInset()->cell(0);
-               for (size_t i = 0; i < ar.size(); ++i) {
-                       if (!(ar[i]->asCharInset() ||
-                                       (ar[i]->asSymbolInset() &&
-                                        ar[i]->asSymbolInset()->isOrdAlpha())))
-                               return false;
-               }
-               return true;
-       }
-       return false;
-}
-
-} // namespace anon
-
-
 int InsetMathScript::dy01(BufferView const & bv, int asc, int des, int what) const
 {
        int dasc = 0;
diff --git a/src/mathed/InsetMathSideset.cpp b/src/mathed/InsetMathSideset.cpp
new file mode 100644 (file)
index 0000000..9d1e51b
--- /dev/null
@@ -0,0 +1,415 @@
+/**
+ * \file InsetMathSideset.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ * \author Georg Baum
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "BufferView.h"
+#include "Cursor.h"
+#include "DispatchResult.h"
+#include "FuncRequest.h"
+#include "FuncStatus.h"
+#include "InsetMathSideset.h"
+#include "InsetMathSymbol.h"
+#include "LaTeXFeatures.h"
+#include "MathData.h"
+#include "MathStream.h"
+#include "MathSupport.h"
+
+#include "support/debug.h"
+
+#include "support/lassert.h"
+
+
+using namespace std;
+
+
+namespace {
+       /// x spacing between the nucleus and the scripts
+       int const dx = 2;
+}
+
+
+namespace lyx {
+
+InsetMathSideset::InsetMathSideset(Buffer * buf)
+       : InsetMathNest(buf, 5)
+{}
+
+
+InsetMathSideset::InsetMathSideset(Buffer * buf, MathAtom const & at)
+       : InsetMathNest(buf, 5)
+{
+       nuc().push_back(at);
+}
+
+
+Inset * InsetMathSideset::clone() const
+{
+       return new InsetMathSideset(*this);
+}
+
+
+bool InsetMathSideset::idxFirst(Cursor & cur) const
+{
+       cur.idx() = 0;
+       cur.pos() = 0;
+       return true;
+}
+
+
+bool InsetMathSideset::idxLast(Cursor & cur) const
+{
+       cur.idx() = 0;
+       cur.pos() = nuc().size();
+       return true;
+}
+
+
+int InsetMathSideset::dybt(BufferView const & bv, int asc, int des, bool top) const
+{
+       bool isCharBox = nuc().empty() ? false : isAlphaSymbol(nuc().back());
+       int dasc = max(bl().dimension(bv).ascent(), br().dimension(bv).ascent());
+       int slevel = nuc().slevel();
+       int ascdrop = dasc - slevel;
+       int desdrop = isCharBox ? 0 : des + nuc().sshift();
+       int mindes = nuc().mindes();
+       des = max(desdrop, ascdrop);
+       des = max(mindes, des);
+       int minasc = nuc().minasc();
+       ascdrop = isCharBox ? 0 : asc - min(tl().mindes(), tr().mindes());
+       int udes = max(bl().dimension(bv).descent(), tr().dimension(bv).descent());
+       asc = udes + nuc().sshift();
+       asc = max(ascdrop, asc);
+       asc = max(minasc, asc);
+       int del = asc - udes - dasc;
+       if (del + des <= 2) {
+               int newdes = 2 - del;
+               del = slevel - asc + udes;
+               if (del > 0) {
+                       asc += del;
+                       newdes -= del;
+               }
+               des = max(des, newdes);
+       }
+       return top ? asc : des;
+}
+
+
+int InsetMathSideset::dyb(BufferView const & bv) const
+{
+       int nd = ndes(bv);
+       int des = max(bl().dimension(bv).ascent(), br().dimension(bv).ascent());
+       int na = nasc(bv);
+       des = dybt(bv, na, nd, false);
+       return des;
+}
+
+
+int InsetMathSideset::dyt(BufferView const & bv) const
+{
+       int na = nasc(bv);
+       int asc = max(tl().dimension(bv).descent(), tr().dimension(bv).descent());
+       int nd = ndes(bv);
+       asc = dybt(bv, na, nd, true);
+       return asc;
+}
+
+
+int InsetMathSideset::dxr(BufferView const & bv) const
+{
+       return dxn(bv) + nwid(bv) + dx;
+}
+
+
+int InsetMathSideset::dxn(BufferView const & bv) const
+{
+       Dimension const dimb = bl().dimension(bv);
+       Dimension const dimt = tl().dimension(bv);
+       return max(dimb.width(), dimt.width()) + dx;
+}
+
+
+int InsetMathSideset::nwid(BufferView const & bv) const
+{
+       return nuc().dimension(bv).width();
+}
+
+
+int InsetMathSideset::nasc(BufferView const & bv) const
+{
+       return nuc().dimension(bv).ascent();
+}
+
+
+int InsetMathSideset::ndes(BufferView const & bv) const
+{
+       return nuc().dimension(bv).descent();
+}
+
+
+int InsetMathSideset::nker(BufferView const * bv) const
+{
+       int const kerning = nuc().kerning(bv);
+       return max(kerning, 0);
+}
+
+
+void InsetMathSideset::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       Dimension dimn;
+       Dimension dimbl;
+       Dimension dimtl;
+       Dimension dimbr;
+       Dimension dimtr;
+       nuc().metrics(mi, dimn);
+       ScriptChanger dummy(mi.base);
+       bl().metrics(mi, dimbl);
+       tl().metrics(mi, dimtl);
+       br().metrics(mi, dimbr);
+       tr().metrics(mi, dimtr);
+
+       BufferView & bv = *mi.base.bv;
+       // FIXME: data copying... not very efficient.
+
+       dim.wid = nwid(bv) + nker(mi.base.bv) + 2 * dx;
+       dim.wid += max(dimbl.width(), dimtl.width());
+       dim.wid += max(dimbr.width(), dimtr.width());
+       int na = nasc(bv);
+       int asc = dyt(bv) + max(dimtl.ascent(), dimtr.ascent());
+       dim.asc = max(na, asc);
+       int nd = ndes(bv);
+       int des = dyb(bv) + max(dimbl.descent(), dimbr.descent());
+       dim.des = max(nd, des);
+       metricsMarkers(dim);
+}
+
+
+void InsetMathSideset::draw(PainterInfo & pi, int x, int y) const
+{
+       BufferView & bv = *pi.base.bv;
+       nuc().draw(pi, x + dxn(bv), y);
+       ScriptChanger dummy(pi.base);
+       bl().draw(pi, x          , y + dyb(bv));
+       tl().draw(pi, x          , y - dyt(bv));
+       br().draw(pi, x + dxr(bv), y + dyb(bv));
+       tr().draw(pi, x + dxr(bv), y - dyt(bv));
+       drawMarkers(pi, x, y);
+}
+
+
+void InsetMathSideset::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+{
+       bl().metricsT(mi, dim);
+       tl().metricsT(mi, dim);
+       br().metricsT(mi, dim);
+       tr().metricsT(mi, dim);
+       nuc().metricsT(mi, dim);
+}
+
+
+void InsetMathSideset::drawT(TextPainter & pain, int x, int y) const
+{
+       // FIXME: BROKEN
+       nuc().drawT(pain, x + 1, y);
+       bl().drawT(pain, x + 1, y + 1 /*dy0()*/);
+       tl().drawT(pain, x + 1, y - 1 /*dy1()*/);
+       br().drawT(pain, x + 1, y + 1 /*dy0()*/);
+       tr().drawT(pain, x + 1, y - 1 /*dy1()*/);
+}
+
+
+
+bool InsetMathSideset::idxForward(Cursor &) const
+{
+       return false;
+}
+
+
+bool InsetMathSideset::idxBackward(Cursor &) const
+{
+       return false;
+}
+
+
+bool InsetMathSideset::idxUpDown(Cursor & cur, bool up) const
+{
+       // in nucleus?
+       if (cur.idx() == 0) {
+               // go up/down only if in the last position
+               // or in the first position
+               if (cur.pos() == cur.lastpos() || cur.pos() == 0) {
+                       if (cur.pos() == 0)
+                               cur.idx() = up ? 2 : 1;
+                       else
+                               cur.idx() = up ? 4 : 3;
+                       cur.pos() = 0;
+                       return true;
+               }
+               return false;
+       }
+
+       // Are we 'up'?
+       if (cur.idx() == 2 || cur.idx() == 4) {
+               // can't go further up
+               if (up)
+                       return false;
+               // otherwise go to first or last position in the nucleus
+               cur.idx() = 0;
+               if (cur.idx() == 2)
+                       cur.pos() = 0;
+               else
+                       cur.pos() = cur.lastpos();
+               return true;
+       }
+
+       // Are we 'down'?
+       if (cur.idx() == 1 || cur.idx() == 3) {
+               // can't go further down
+               if (!up)
+                       return false;
+               // otherwise go to first or last position in the nucleus
+               cur.idx() = 0;
+               if (cur.idx() == 1)
+                       cur.pos() = 0;
+               else
+                       cur.pos() = cur.lastpos();
+               return true;
+       }
+
+       return false;
+}
+
+
+void InsetMathSideset::write(WriteStream & os) const
+{
+       MathEnsurer ensurer(os);
+
+       os << "\\sideset";
+       for (int i = 0; i < 2; ++i) {
+               os << '{';
+               if (!cell(2*i+1).empty())
+                       os << "_{" << cell(2*i+1) << '}';
+               if (!cell(2*i+2).empty())
+                       os << "^{" << cell(2*i+2) << '}';
+               os << '}';
+       }
+       os << '{' << nuc() << '}';
+
+       if (lock_ && !os.latex())
+               os << "\\lyxlock ";
+}
+
+
+void InsetMathSideset::normalize(NormalStream & os) const
+{
+       os << "[sideset ";
+
+       if (!bl().empty())
+               os << bl() << ' ';
+       if (!tl().empty())
+               os << tl() << ' ';
+
+       if (!nuc().empty())
+               os << nuc() << ' ';
+       else
+               os << "[par]";
+
+       if (!br().empty())
+               os << br() << ' ';
+       if (!tr().empty())
+               os << tr() << ' ';
+       os << ']';
+}
+
+
+void InsetMathSideset::mathmlize(MathStream & os) const
+{
+       os << MTag("mmultiscripts");
+
+       if (nuc().empty())
+               os << "<mrow />";
+       else
+               os << MTag("mrow") << nuc() << ETag("mrow");
+
+       if (br().empty())
+               os << "<none />";
+       else
+               os << MTag("mrow") << br() << ETag("mrow");
+       if (tr().empty())
+               os << "<none />";
+       else
+               os << MTag("mrow") << tr() << ETag("mrow");
+
+       if (bl().empty())
+               os << "<none />";
+       else
+               os << MTag("mrow") << bl() << ETag("mrow");
+       if (tl().empty())
+               os << "<none />";
+       else
+               os << MTag("mrow") << tl() << ETag("mrow");
+
+       os << ETag("mmultiscripts");
+}
+
+
+void InsetMathSideset::htmlize(HtmlStream & os) const
+{
+       bool const havebl = !bl().empty();
+       bool const havetl = !tl().empty();
+       bool const havebr = !br().empty();
+       bool const havetr = !tr().empty();
+
+       if (havebl && havetl)
+               os << MTag("span", "class='scripts'")
+                        << MTag("span") << tl() << ETag("span")
+                        << MTag("span") << bl() << ETag("span")
+                        << ETag("span");
+       else if (havebl)
+               os << MTag("sub", "class='math'") << bl() << ETag("sub");
+       else if (havetl)
+               os << MTag("sup", "class='math'") << tl() << ETag("sup");
+
+       if (!nuc().empty())
+               os << nuc();
+
+       if (havebr && havetr)
+               os << MTag("span", "class='scripts'")
+                        << MTag("span") << tr() << ETag("span")
+                        << MTag("span") << br() << ETag("span")
+                        << ETag("span");
+       else if (havebr)
+               os << MTag("sub", "class='math'") << br() << ETag("sub");
+       else if (havetr)
+               os << MTag("sup", "class='math'") << tr() << ETag("sup");
+}
+
+
+void InsetMathSideset::infoize(odocstream & os) const
+{
+       os << "Sideset";
+}
+
+
+// the idea for dual scripts came from the eLyXer code
+void InsetMathSideset::validate(LaTeXFeatures & features) const
+{
+       if (features.runparams().math_flavor == OutputParams::MathAsHTML)
+               features.addCSSSnippet(
+                       "span.scripts{display: inline-block; vertical-align: middle; text-align:center; font-size: 75%;}\n"
+                       "span.scripts span {display: block;}\n"
+                       "sub.math{font-size: 75%;}\n"
+                       "sup.math{font-size: 75%;}");
+       features.require("amsmath");
+       InsetMathNest::validate(features);
+}
+
+} // namespace lyx
diff --git a/src/mathed/InsetMathSideset.h b/src/mathed/InsetMathSideset.h
new file mode 100644 (file)
index 0000000..67f7eaa
--- /dev/null
@@ -0,0 +1,113 @@
+// -*- C++ -*-
+/**
+ * \file InsetMathSideset.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ * \author Georg Baum
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef MATH_SIDESETINSET_H
+#define MATH_SIDESETINSET_H
+
+#include "InsetMathNest.h"
+
+
+namespace lyx {
+
+
+/// An inset for amsmath \sideset. The 'nucleus' is always cell 0.
+/// cell(1) is the bottom left index, cell(2) is the top left index,
+/// cell(3) is the bottom right index, and cell(4) is top right index.
+class InsetMathSideset : public InsetMathNest {
+public:
+       ///
+       InsetMathSideset(Buffer * buf);
+       /// create inset with given nucleus
+       InsetMathSideset(Buffer * buf, MathAtom const & at);
+       ///
+       mode_type currentMode() const { return MATH_MODE; }
+       ///
+       void metrics(MetricsInfo & mi, Dimension & dim) const;
+       ///
+       void draw(PainterInfo & pi, int x, int y) const;
+       ///
+       void metricsT(TextMetricsInfo const & mi, Dimension & dim) const;
+       ///
+       void drawT(TextPainter & pi, int x, int y) const;
+
+       /// move cursor backwards
+       bool idxBackward(Cursor & cur) const;
+       /// move cursor forward
+       bool idxForward(Cursor & cur) const;
+       /// move cursor up or down
+       bool idxUpDown(Cursor & cur, bool up) const;
+       /// Target pos when we enter the inset while moving forward
+       bool idxFirst(Cursor & cur) const;
+       /// Target pos when we enter the inset while moving backwards
+       bool idxLast(Cursor & cur) const;
+
+       /// write LaTeX and Lyx code
+       void write(WriteStream & os) const;
+       /// write normalized content
+       void normalize(NormalStream &) const;
+       /// write content as MathML
+       void mathmlize(MathStream &) const;
+       /// write content as HTML
+       void htmlize(HtmlStream &) const;
+
+       /// returns nucleus
+       MathData const & nuc() const { return cell(0); };
+       /// returns nucleus
+       MathData & nuc()             { return cell(0); };
+       /// bottom left index
+       MathData const & bl() const  { return cell(1); }
+       /// bottom left index
+       MathData & bl()              { return cell(1); }
+       /// top left index
+       MathData const & tl() const  { return cell(2); }
+       /// top left index
+       MathData & tl()              { return cell(2); }
+       /// bottom right index
+       MathData const & br() const  { return cell(3); }
+       /// bottom right index
+       MathData & br()              { return cell(3); }
+       /// top right index
+       MathData const & tr() const  { return cell(4); }
+       /// top right index
+       MathData & tr()              { return cell(4); }
+       /// say that we have scripts
+       void infoize(odocstream & os) const;
+       ///
+       InsetCode lyxCode() const { return MATH_SCRIPT_CODE; }
+       ///
+       void validate(LaTeXFeatures &features) const;
+private:
+       virtual Inset * clone() const;
+       /// returns x offset of nucleus
+       int dxn(BufferView const & bv) const;
+       /// returns width of nucleus if any
+       int nwid(BufferView const &) const;
+       /// returns y offset for either superscript or subscript
+       int dybt(BufferView const &, int asc, int des, bool top) const;
+       /// returns y offset for superscript
+       int dyt(BufferView const &) const;
+       /// returns y offset for subscript
+       int dyb(BufferView const &) const;
+       /// returns x offset for right subscript and superscript
+       int dxr(BufferView const & bv) const;
+       /// returns ascent of nucleus if any
+       int nasc(BufferView const &) const;
+       /// returns descent of nucleus if any
+       int ndes(BufferView const &) const;
+       /// returns subscript and superscript kerning of nucleus if any
+       int nker(BufferView const * bv) const;
+};
+
+
+} // namespace lyx
+
+#endif
index ac3ac9861965ea336afffbc5942d665cdd20a260..d2bd2e8cb312c8344af7477880e6b657a8a52baf 100644 (file)
@@ -32,6 +32,7 @@
 #include "InsetMathPhantom.h"
 #include "InsetMathRef.h"
 #include "InsetMathRoot.h"
+#include "InsetMathSideset.h"
 #include "InsetMathSize.h"
 #include "InsetMathSpace.h"
 #include "InsetMathSpecialChar.h"
@@ -535,6 +536,8 @@ MathAtom createInsetMath(docstring const & s, Buffer * buf)
                return MathAtom(new InsetMathPhantom(buf, InsetMathPhantom::mathrlap));
        if (s == "ensuremath")
                return MathAtom(new InsetMathEnsureMath(buf));
+       if (s == "sideset")
+               return MathAtom(new InsetMathSideset(buf));
        if (isSpecialChar(s))
                return MathAtom(new InsetMathSpecialChar(s));
        if (s == " ")
index 3f20df5eb7acb4bd697e998f38dd6b8df72c6adb..61e000ccc2f02e81243d4c0befb11b9d96050a7a 100644 (file)
@@ -56,6 +56,7 @@ following hack as starting point to write some macros:
 #include "InsetMathRef.h"
 #include "InsetMathRoot.h"
 #include "InsetMathScript.h"
+#include "InsetMathSideset.h"
 #include "InsetMathSpace.h"
 #include "InsetMathSplit.h"
 #include "InsetMathSqrt.h"
@@ -1442,6 +1443,28 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
                }
 
+               else if (t.cs() == "sideset") {
+                       // Here allowed formats are \sideset{_{bl}^{tl}}{_{br}^{tr}}{operator}
+                       cell->push_back(MathAtom(new InsetMathSideset(buf)));
+                       for (int i = 0; i < 2; ++i) {
+                               MathData ar;
+                               parse(ar, FLAG_ITEM, mode);
+                               if (!ar.empty()) {
+                                       InsetMathScript * script = (ar.size() == 1) ?
+                                               ar[0].nucleus()->asScriptInset() : 0;
+                                       if (!script) {
+                                               error("found invalid sideset argument");
+                                               break;
+                                       }
+                                       if (script->hasDown())
+                                               cell->back().nucleus()->cell(2 * i + 1) = script->down();
+                                       if (script->hasUp())
+                                               cell->back().nucleus()->cell(2 * i + 2) = script->up();
+                               }
+                       }
+                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+               }
+
                else if (t.cs() == "stackrel") {
                        // Here allowed formats are \stackrel[subscript]{superscript}{operator}
                        MathData ar;
index 0a87fd69bae3c90f67a8a812eba790a2a3831ef6..6a815ed8985e6b81605b4f201c6ecfffb865fab0 100644 (file)
@@ -13,7 +13,8 @@
 
 #include "MathSupport.h"
 
-#include "InsetMath.h"
+#include "InsetMathFont.h"
+#include "InsetMathSymbol.h"
 #include "MathData.h"
 #include "MathParser.h"
 #include "MathStream.h"
@@ -736,6 +737,27 @@ void augmentFont(FontInfo & font, docstring const & name)
 }
 
 
+bool isAlphaSymbol(MathAtom const & at)
+{
+       if (at->asCharInset() ||
+           (at->asSymbolInset() &&
+            at->asSymbolInset()->isOrdAlpha()))
+               return true;
+
+       if (at->asFontInset()) {
+               MathData const & ar = at->asFontInset()->cell(0);
+               for (size_t i = 0; i < ar.size(); ++i) {
+                       if (!(ar[i]->asCharInset() ||
+                             (ar[i]->asSymbolInset() &&
+                              ar[i]->asSymbolInset()->isOrdAlpha())))
+                               return false;
+               }
+               return true;
+       }
+       return false;
+}
+
+
 docstring asString(MathData const & ar)
 {
        odocstringstream os;
index 968be725ef305ae101d8e100c0c5774004faef10..f31606615fc6a63e7a68eeebfa733cb1fc983c7a 100644 (file)
@@ -56,6 +56,8 @@ bool isMathFont(docstring const & name);
 
 bool isTextFont(docstring const & name);
 
+bool isAlphaSymbol(MathAtom const & at);
+
 // converts single cell to string
 docstring asString(MathData const & ar);
 // converts single inset to string