From 361bd53bc36da61c6abfc2e0b7b7c7294800bbd9 Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Mon, 30 May 2016 10:33:35 +0200 Subject: [PATCH] Introduce the notion of math class This done according to the TeXbook. This class replaces the individual isMathXXX() methods. The mathClass() method (currently unused) is provided for the following insets: * InsetMathChar (with a revised list of affected characters) * InsetMathSymbol: the class is given by the `extra' field Operators defined in lib/symbols (e.g. \log) are MC_OP * InsetMathFrac is MC_INNER (except nicefrac and units) * InsetDelimiters is MC_INNER * InsetStackrel is MC_REL * The class of InsetScript is the class of the last element of its nucleus (yes, it is a hack, but doing it right is more work). Remove the explicit spacing that was done in the different insets. The spacing will be reintroduced properly in a forthcoming commit. --- src/Makefile.am | 4 +- src/mathed/InsetMath.cpp | 6 +++ src/mathed/InsetMath.h | 11 ++--- src/mathed/InsetMathChar.cpp | 29 +++++------ src/mathed/InsetMathChar.h | 6 +-- src/mathed/InsetMathDelim.cpp | 9 ++-- src/mathed/InsetMathDelim.h | 2 + src/mathed/InsetMathFrac.cpp | 25 ++++++++++ src/mathed/InsetMathFrac.h | 4 ++ src/mathed/InsetMathHull.cpp | 2 +- src/mathed/InsetMathScript.cpp | 13 +++++ src/mathed/InsetMathScript.h | 2 + src/mathed/InsetMathStackrel.cpp | 7 +++ src/mathed/InsetMathStackrel.h | 4 +- src/mathed/InsetMathSymbol.cpp | 25 ++++------ src/mathed/InsetMathSymbol.h | 6 +-- src/mathed/MathClass.cpp | 82 ++++++++++++++++++++++++++++++++ src/mathed/MathClass.h | 64 +++++++++++++++++++++++++ src/mathed/MathSupport.cpp | 11 ----- 19 files changed, 243 insertions(+), 69 deletions(-) create mode 100644 src/mathed/MathClass.cpp create mode 100644 src/mathed/MathClass.h diff --git a/src/Makefile.am b/src/Makefile.am index f3dd870077..fc135af00e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -447,14 +447,15 @@ SOURCEFILESMATHED = \ mathed/InsetMathXArrow.cpp \ mathed/InsetMathXYMatrix.cpp \ mathed/InsetMathDiagram.cpp \ + mathed/MacroTable.cpp \ mathed/MathAtom.cpp \ mathed/MathAutoCorrect.cpp \ + mathed/MathClass.cpp \ mathed/MathData.cpp \ mathed/MathExtern.cpp \ mathed/MathFactory.cpp \ mathed/MathMacro.cpp \ mathed/MathMacroArgument.cpp \ - mathed/MacroTable.cpp \ mathed/MathMacroTemplate.cpp \ mathed/MathParser.cpp \ mathed/MathStream.cpp \ @@ -518,6 +519,7 @@ HEADERFILESMATHED = \ mathed/InsetMathDiagram.h \ mathed/MathAtom.h \ mathed/MathAutoCorrect.h \ + mathed/MathClass.h \ mathed/MathData.h \ mathed/MathCompletionList.h \ mathed/MathExtern.h \ diff --git a/src/mathed/InsetMath.cpp b/src/mathed/InsetMath.cpp index 2fb1ff5a55..aec53d0518 100644 --- a/src/mathed/InsetMath.cpp +++ b/src/mathed/InsetMath.cpp @@ -49,6 +49,12 @@ MathData const & InsetMath::cell(idx_type) const } +MathClass InsetMath::mathClass() const +{ + return MC_ORD; +} + + void InsetMath::dump() const { lyxerr << "---------------------------------------------" << endl; diff --git a/src/mathed/InsetMath.h b/src/mathed/InsetMath.h index da84af1010..e791099b72 100644 --- a/src/mathed/InsetMath.h +++ b/src/mathed/InsetMath.h @@ -13,6 +13,8 @@ #ifndef MATH_INSET_H #define MATH_INSET_H +#include "MathClass.h" + #include "insets/Inset.h" @@ -160,14 +162,11 @@ public: virtual InsetMathRef * asRefInset() { return 0; } virtual InsetMathSpecialChar const * asSpecialCharInset() const { return 0; } + /// The class of the math object (used primarily for spacing) + virtual MathClass mathClass() const; + /// identifies things that can get scripts virtual bool isScriptable() const { return false; } - /// identifies a binary operators (used for spacing) - virtual bool isMathBin() const { return false; } - /// identifies relational operators (used for spacing and splitting equations) - virtual bool isMathRel() const { return false; } - /// identifies punctuation (used for spacing) - virtual bool isMathPunct() const { return false; } /// will this get written as a single block in {..} virtual bool extraBraces() const { return false; } diff --git a/src/mathed/InsetMathChar.cpp b/src/mathed/InsetMathChar.cpp index ae843bf00d..1669515b66 100644 --- a/src/mathed/InsetMathChar.cpp +++ b/src/mathed/InsetMathChar.cpp @@ -121,8 +121,6 @@ void InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const dim = fm.dimension(char_); kerning_ = fm.rbearing(char_) - dim.wid; } - if (mathfont && isMathPunct()) - dim.wid += mathed_thinmuskip(mi.base.font); } @@ -266,22 +264,19 @@ void InsetMathChar::htmlize(HtmlStream & ms) const } -bool InsetMathChar::isMathBin() const +MathClass InsetMathChar::mathClass() const { - return subst_ && subst_->extra == "mathbin"; -} - - -bool InsetMathChar::isMathRel() const -{ - return subst_ && subst_->extra == "mathrel"; -} - - -bool InsetMathChar::isMathPunct() const -{ - return support::contains(",;", static_cast(char_)) - || (subst_ && subst_->extra == "mathpunct"); + // this information comes from fontmath.ltx in LaTeX source. + char const ch = static_cast(char_); + if (subst_) + return string_to_class(subst_->extra); + else if (support::contains(",;", ch)) + return MC_PUNCT; + else if (support::contains("([", ch)) + return MC_OPEN; + else if (support::contains(")]!?", ch)) + return MC_CLOSE; + else return MC_ORD; } diff --git a/src/mathed/InsetMathChar.h b/src/mathed/InsetMathChar.h index ea190211b7..6e7ff72c9c 100644 --- a/src/mathed/InsetMathChar.h +++ b/src/mathed/InsetMathChar.h @@ -51,11 +51,7 @@ public: /// char_type getChar() const { return char_; } /// - bool isMathBin() const; - /// - bool isMathRel() const; - /// - bool isMathPunct() const; + MathClass mathClass() const; /// InsetCode lyxCode() const { return MATH_CHAR_CODE; } diff --git a/src/mathed/InsetMathDelim.cpp b/src/mathed/InsetMathDelim.cpp index 68e4430514..4ab179e7b2 100644 --- a/src/mathed/InsetMathDelim.cpp +++ b/src/mathed/InsetMathDelim.cpp @@ -115,7 +115,7 @@ void InsetMathDelim::metrics(MetricsInfo & mi, Dimension & dim) const dw_ = 8; if (dw_ < 4) dw_ = 4; - dim.wid = dim0.width() + 2 * dw_ + 2 * mathed_thinmuskip(mi.base.font); + dim.wid = dim0.width() + 2 * dw_; dim.asc = max(a0, d0) + h0; dim.des = max(a0, d0) - h0; } @@ -125,10 +125,9 @@ void InsetMathDelim::draw(PainterInfo & pi, int x, int y) const { Dimension const dim = dimension(*pi.base.bv); int const b = y - dim.asc; - int const skip = mathed_thinmuskip(pi.base.font); - cell(0).draw(pi, x + dw_ + skip, y); - mathed_draw_deco(pi, x + skip, b, dw_, dim.height(), left_); - mathed_draw_deco(pi, x + dim.width() - dw_ - skip, + cell(0).draw(pi, x + dw_, y); + mathed_draw_deco(pi, x, b, dw_, dim.height(), left_); + mathed_draw_deco(pi, x + dim.width() - dw_, b, dw_, dim.height(), right_); setPosCache(pi, x, y); } diff --git a/src/mathed/InsetMathDelim.h b/src/mathed/InsetMathDelim.h index 3a09ede2f3..5a7e816404 100644 --- a/src/mathed/InsetMathDelim.h +++ b/src/mathed/InsetMathDelim.h @@ -30,6 +30,8 @@ public: InsetMathDelim * asDelimInset() { return this; } /// InsetMathDelim const * asDelimInset() const { return this; } + /// + MathClass mathClass() const { return MC_INNER; } /// is it (...)? bool isParenthesis() const; /// is it [...]? diff --git a/src/mathed/InsetMathFrac.cpp b/src/mathed/InsetMathFrac.cpp index ab876e060d..263587ed6e 100644 --- a/src/mathed/InsetMathFrac.cpp +++ b/src/mathed/InsetMathFrac.cpp @@ -123,6 +123,31 @@ bool InsetMathFrac::idxBackward(Cursor & cur) const } +MathClass InsetMathFrac::mathClass() const +{ + // Generalized fractions are of inner class (see The TeXbook, p. 292) + // But stuff from the unit/nicefrac packages are not real fractions. + MathClass mc = MC_ORD; + switch (kind_) { + case ATOP: + case OVER: + case FRAC: + case DFRAC: + case TFRAC: + case CFRAC: + case CFRACLEFT: + case CFRACRIGHT: + mc = MC_INNER; + break; + case NICEFRAC: + case UNITFRAC: + case UNIT: + break; + } + return mc; +} + + void InsetMathFrac::metrics(MetricsInfo & mi, Dimension & dim) const { Dimension dim0, dim1, dim2; diff --git a/src/mathed/InsetMathFrac.h b/src/mathed/InsetMathFrac.h index c030c8a51a..96b62930ba 100644 --- a/src/mathed/InsetMathFrac.h +++ b/src/mathed/InsetMathFrac.h @@ -62,6 +62,8 @@ public: /// bool idxBackward(Cursor &) const; /// + MathClass mathClass() const; + /// void metrics(MetricsInfo & mi, Dimension & dim) const; /// void draw(PainterInfo &, int x, int y) const; @@ -117,6 +119,8 @@ public: void write(WriteStream & os) const; /// void normalize(NormalStream &) const; + /// Generalized fractions are of inner class (see The TeXbook, p.292) + MathClass mathClass() const { return MC_INNER; } /// void metrics(MetricsInfo & mi, Dimension & dim) const; /// diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp index e2ceb5c903..dc943bb520 100644 --- a/src/mathed/InsetMathHull.cpp +++ b/src/mathed/InsetMathHull.cpp @@ -108,7 +108,7 @@ namespace { size_t firstRelOp(MathData const & ar) { for (MathData::const_iterator it = ar.begin(); it != ar.end(); ++it) - if ((*it)->isMathRel()) + if ((*it)->mathClass() == MC_REL) return it - ar.begin(); return ar.size(); } diff --git a/src/mathed/InsetMathScript.cpp b/src/mathed/InsetMathScript.cpp index b4cd5909be..8098a1a2d8 100644 --- a/src/mathed/InsetMathScript.cpp +++ b/src/mathed/InsetMathScript.cpp @@ -273,6 +273,19 @@ int InsetMathScript::nker(BufferView const * bv) const } +MathClass InsetMathScript::mathClass() const +{ + // FIXME: this is a hack, since the class will not be correct if + // the nucleus has several elements. + // 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. + return nuc().back()->mathClass(); +} + + void InsetMathScript::metrics(MetricsInfo & mi, Dimension & dim) const { Dimension dim0; diff --git a/src/mathed/InsetMathScript.h b/src/mathed/InsetMathScript.h index e84886b7d3..d0707439b9 100644 --- a/src/mathed/InsetMathScript.h +++ b/src/mathed/InsetMathScript.h @@ -33,6 +33,8 @@ public: /// mode_type currentMode() const { return MATH_MODE; } /// + MathClass mathClass() const; + /// void metrics(MetricsInfo & mi, Dimension & dim) const; /// void draw(PainterInfo & pi, int x, int y) const; diff --git a/src/mathed/InsetMathStackrel.cpp b/src/mathed/InsetMathStackrel.cpp index 9412d99182..3dda0dae24 100644 --- a/src/mathed/InsetMathStackrel.cpp +++ b/src/mathed/InsetMathStackrel.cpp @@ -52,6 +52,13 @@ bool InsetMathStackrel::idxUpDown(Cursor & cur, bool up) const } +MathClass InsetMathStackrel::mathClass() const +{ + // FIXME: update this when/if \stackbin is supported + return MC_REL; +} + + void InsetMathStackrel::metrics(MetricsInfo & mi, Dimension & dim) const { Dimension dim1; diff --git a/src/mathed/InsetMathStackrel.h b/src/mathed/InsetMathStackrel.h index 91862a7792..d6ac815182 100644 --- a/src/mathed/InsetMathStackrel.h +++ b/src/mathed/InsetMathStackrel.h @@ -24,6 +24,8 @@ public: /// bool idxUpDown(Cursor &, bool up) const; /// + MathClass mathClass() const; + /// void metrics(MetricsInfo & mi, Dimension & dim) const; /// void draw(PainterInfo & pi, int x, int y) const; @@ -35,7 +37,7 @@ public: void mathmlize(MathStream &) const; /// void htmlize(HtmlStream &) const; - /// + /// void validate(LaTeXFeatures &) const; /// InsetCode lyxCode() const { return MATH_STACKREL_CODE; } diff --git a/src/mathed/InsetMathSymbol.cpp b/src/mathed/InsetMathSymbol.cpp index 620ca226a2..01bafe614d 100644 --- a/src/mathed/InsetMathSymbol.cpp +++ b/src/mathed/InsetMathSymbol.cpp @@ -70,7 +70,7 @@ void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const dim.asc += h_; dim.des -= h_; } - // set striptable_ + // set scriptable_ scriptable_ = false; if (mi.base.style == LM_ST_DISPLAY) if (sym_->inset == "cmex" || sym_->inset == "esint" || @@ -92,27 +92,18 @@ InsetMath::mode_type InsetMathSymbol::currentMode() const } -bool InsetMathSymbol::isMathBin() const -{ - return sym_->extra == "mathbin"; -} - - -bool InsetMathSymbol::isMathRel() const -{ - return sym_->extra == "mathrel"; -} - - -bool InsetMathSymbol::isMathPunct() const +bool InsetMathSymbol::isOrdAlpha() const { - return sym_->extra == "mathpunct"; + return sym_->extra == "mathord" || sym_->extra == "mathalpha"; } -bool InsetMathSymbol::isOrdAlpha() const +MathClass InsetMathSymbol::mathClass() const { - return sym_->extra == "mathord" || sym_->extra == "mathalpha"; + if (sym_->extra == "func" || sym_->extra == "funclim") + return MC_OP; + MathClass const mc = string_to_class(sym_->extra); + return (mc == MC_UNKNOWN) ? MC_ORD : mc; } diff --git a/src/mathed/InsetMathSymbol.h b/src/mathed/InsetMathSymbol.h index 6ca3ded7d1..67b33fd85a 100644 --- a/src/mathed/InsetMathSymbol.h +++ b/src/mathed/InsetMathSymbol.h @@ -40,11 +40,7 @@ public: /// mode_type currentMode() const; /// - bool isMathRel() const; - /// - bool isMathBin() const; - /// - bool isMathPunct() const; + MathClass mathClass() const; /// bool isOrdAlpha() const; /// do we take scripts? diff --git a/src/mathed/MathClass.cpp b/src/mathed/MathClass.cpp new file mode 100644 index 0000000000..fae7654334 --- /dev/null +++ b/src/mathed/MathClass.cpp @@ -0,0 +1,82 @@ +/** + * \file MathClass.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Jean-Marc Lasgouttes + * + * Full author contact details are available in file CREDITS. + */ + +#include + +#include "MathClass.h" + +#include "support/docstring.h" +#include "support/lassert.h" + +using namespace std; + +namespace lyx { + + +docstring const class_to_string(MathClass const mc) +{ + string s; + switch (mc) { + case MC_ORD: + s = "mathord"; + break; + case MC_OP: + s = "mathop"; + break; + case MC_BIN: + s = "mathbin"; + break; + case MC_REL: + s = "mathrel"; + break; + case MC_OPEN: + s = "mathopen"; + break; + case MC_CLOSE: + s = "mathclose"; + break; + case MC_PUNCT: + s = "mathpunct"; + break; + case MC_INNER: + s = "mathinner"; + break; + case MC_UNKNOWN: + LATTEST(false); + s = "mathord"; + } + return from_ascii(s); +} + + +MathClass string_to_class(docstring const &s) +{ + if (s == "mathop") + return MC_OP; + else if (s == "mathbin") + return MC_BIN; + else if (s == "mathrel") + return MC_REL; + else if (s == "mathopen") + return MC_OPEN; + else if (s == "mathclose") + return MC_CLOSE; + else if (s == "mathpunct") + return MC_PUNCT; + else if (s == "mathinner") + return MC_INNER; + else if (s == "mathord") + return MC_ORD; + else + return MC_UNKNOWN; +} + + +} // namespace lyx diff --git a/src/mathed/MathClass.h b/src/mathed/MathClass.h new file mode 100644 index 0000000000..ceedd8db07 --- /dev/null +++ b/src/mathed/MathClass.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +/** + * \file MathClass.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Jean-Marc Lasgouttes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef MATH_CLASS_H +#define MATH_CLASS_H + +#include "support/strfwd.h" + +namespace lyx { + + +/* The TeXbook, p. 158: + * + * There are thirteen kinds of atoms, each of which might act + * differently in a formula; for example, ‘(’ is an Open atom because + * it comes from an opening. Here is a complete list of the different + * kinds: + + * + Ord: an ordinary atom like ‘x’ + * + Op: a large operator atom like ‘\sum’ + * + Bin: a binary operation atom like ‘+’ + * + Rel: a relation atom like ‘=’ + * + Open: an opening atom like ‘(’ + * + Close: a closing atom like ‘)’ + * + Punct: a punctuation atom like ‘,’ + * + Inner: an inner atom like ‘\frac{1}{2}’ + * + Over: an overline atom like ‘\overline{x}’ + * + Under: an underline atom like ‘\underline{x}’ + * + Acc: an accented atom like ‘\hat{x}’ + * + Rad: a radical atom like ‘\sqrt{2}’ + * + Vcent: a vbox to be centered, produced by \vcenter. + * + * Over, Under, Acc, Rad and Vcent are not considered in the enum + * below. The relvant elements will be considered as Ord. + */ +enum MathClass { + MC_ORD, + MC_OP, + MC_BIN, + MC_REL, + MC_OPEN, + MC_CLOSE, + MC_PUNCT, + MC_INNER, + MC_UNKNOWN +}; + + +MathClass string_to_class(docstring const &); + +docstring const class_to_string(MathClass); + + +} // namespace lyx + +#endif diff --git a/src/mathed/MathSupport.cpp b/src/mathed/MathSupport.cpp index 0c610b1e69..9d79a8abfa 100644 --- a/src/mathed/MathSupport.cpp +++ b/src/mathed/MathSupport.cpp @@ -671,13 +671,6 @@ void mathedSymbolDim(MetricsInfo & mi, Dimension & dim, latexkeys const * sym) std::string const font = italic_upcase_greek ? "cmm" : sym->inset; Changer dummy = mi.base.changeFontSet(font); mathed_string_dim(mi.base.font, sym->draw, dim); - // seperate things a bit - if (sym->extra == "mathbin") - dim.wid += 2 * mathed_medmuskip(mi.base.font); - else if (sym->extra == "mathrel") - dim.wid += 2 * mathed_thickmuskip(mi.base.font); - else if (sym->extra == "mathpunct") - dim.wid += mathed_thinmuskip(mi.base.font); } @@ -693,10 +686,6 @@ void mathedSymbolDraw(PainterInfo & pi, int x, int y, latexkeys const * sym) sym->extra == "mathalpha" && pi.base.fontname == "mathit"; std::string const font = italic_upcase_greek ? "cmm" : sym->inset; - if (sym->extra == "mathbin") - x += mathed_medmuskip(pi.base.font); - else if (sym->extra == "mathrel") - x += mathed_thickmuskip(pi.base.font); Changer dummy = pi.base.changeFontSet(font); pi.draw(x, y, sym->draw); -- 2.39.2