]> git.lyx.org Git - lyx.git/blob - src/mathed/InsetMathSymbol.cpp
471ee75460a5648b3d2849bbc6a02db8308325d8
[lyx.git] / src / mathed / InsetMathSymbol.cpp
1 /**
2  * \file InsetMathSymbol.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "InsetMathSymbol.h"
14
15 #include "MathAtom.h"
16 #include "MathParser.h"
17 #include "MathStream.h"
18 #include "MathSupport.h"
19
20 #include "Dimension.h"
21 #include "LaTeXFeatures.h"
22 #include "MetricsInfo.h"
23
24 #include "support/debug.h"
25 #include "support/docstream.h"
26 #include "support/lyxlib.h"
27 #include "support/textutils.h"
28 #include "support/unique_ptr.h"
29
30 using namespace std;
31
32 namespace lyx {
33
34 InsetMathSymbol::InsetMathSymbol(latexkeys const * l)
35         : sym_(l)
36 {}
37
38
39 InsetMathSymbol::InsetMathSymbol(char const * name)
40         : sym_(in_word_set(from_ascii(name)))
41 {}
42
43
44 InsetMathSymbol::InsetMathSymbol(docstring const & name)
45         : sym_(in_word_set(name))
46 {}
47
48
49 Inset * InsetMathSymbol::clone() const
50 {
51         return new InsetMathSymbol(*this);
52 }
53
54
55 docstring InsetMathSymbol::name() const
56 {
57         return sym_->name;
58 }
59
60
61 /// The default limits value
62 Limits InsetMathSymbol::defaultLimits() const
63 {
64         return (allowsLimitsChange() && sym_->extra != "func")
65                         ? LIMITS : NO_LIMITS;
66 }
67
68
69 void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
70 {
71         // set dim
72         // FIXME: this should depend on BufferView
73         // set negative kerning_ so that a subscript is moved leftward
74         kerning_ = -mathedSymbolDim(mi.base, dim, sym_);
75         if (sym_->draw != sym_->name) {
76                 // align character vertically
77                 // FIXME: this should depend on BufferView
78                 h_ = 0;
79                 if (mathClass() == MC_OP) {
80                         // center the symbol around the fraction axis
81                         // See rule 13 of Appendix G of the TeXbook.
82                         h_ = axis_height(mi.base) + (dim.des - dim.asc) / 2;
83                 } else if (sym_->inset == "wasy") {
84                         // correct height for broken wasy font
85                         h_ = 4 * dim.des / 5;
86                 }
87                 dim.asc += h_;
88                 dim.des -= h_;
89         }
90 }
91
92
93 void InsetMathSymbol::draw(PainterInfo & pi, int x, int y) const
94 {
95         mathedSymbolDraw(pi, x, y - h_, sym_);
96 }
97
98
99 InsetMath::mode_type InsetMathSymbol::currentMode() const
100 {
101         return sym_->extra == "textmode" ? TEXT_MODE : MATH_MODE;
102 }
103
104
105 bool InsetMathSymbol::isOrdAlpha() const
106 {
107         return sym_->extra == "mathord" || sym_->extra == "mathalpha";
108 }
109
110
111 MathClass InsetMathSymbol::mathClass() const
112 {
113         if (sym_->extra == "func" || sym_->extra == "funclim")
114                 return MC_OP;
115         MathClass const mc = string_to_class(sym_->extra);
116         return (mc == MC_UNKNOWN) ? MC_ORD : mc;
117 }
118
119
120 void InsetMathSymbol::normalize(NormalStream & os) const
121 {
122         os << "[symbol " << name() << ']';
123 }
124
125
126 void InsetMathSymbol::maple(MapleStream & os) const
127 {
128         if (name() == "cdot")
129                 os << '*';
130         else if (name() == "infty")
131                 os << "infinity";
132         else
133                 os << name();
134 }
135
136 void InsetMathSymbol::maxima(MaximaStream & os) const
137 {
138         if (name() == "cdot")
139                 os << '*';
140         else if (name() == "infty")
141                 os << "inf";
142         else if (name() == "pi")
143                 os << "%pi";
144         else
145                 os << name();
146 }
147
148
149 void InsetMathSymbol::mathematica(MathematicaStream & os) const
150 {
151         if ( name() == "pi")    { os << "Pi"; return;}
152         if ( name() == "infty") { os << "Infinity"; return;}
153         if ( name() == "cdot")  { os << '*'; return;}
154         os << name();
155 }
156
157
158 void InsetMathSymbol::mathmlize(MathStream & ms) const
159 {
160         // FIXME We may need to do more interesting things
161         // with MathMLtype.
162         docstring tag = from_ascii(ms.namespacedTag(sym_->MathMLtype()));
163         ms << '<' << tag << ">";
164         if ((ms.xmlMode() && sym_->xmlname == "x") || (!ms.xmlMode() && sym_->htmlname == "x"))
165                 // unknown so far
166                 ms << name();
167         else if (ms.xmlMode())
168                 ms << sym_->xmlname;
169         else
170                 ms << sym_->htmlname;
171         ms << "</" << tag << '>';
172 }
173
174
175 void InsetMathSymbol::htmlize(HtmlStream & os, bool spacing) const
176 {
177         // FIXME We may need to do more interesting things
178         // with MathMLtype.
179         char const * type = sym_->MathMLtype();
180         bool op = (std::string(type) == "mo");
181
182         if (sym_->htmlname == "x")
183                 // unknown so far
184                 os << ' ' << name() << ' ';
185         else if (op && spacing)
186                 os << ' ' << sym_->htmlname << ' ';
187         else
188                 os << sym_->htmlname;
189 }
190
191
192 void InsetMathSymbol::htmlize(HtmlStream & os) const
193 {
194         htmlize(os, true);
195 }
196
197
198 void InsetMathSymbol::octave(OctaveStream & os) const
199 {
200         if (name() == "cdot")
201                 os << '*';
202         else
203                 os << name();
204 }
205
206
207 void InsetMathSymbol::write(WriteStream & os) const
208 {
209         unique_ptr<MathEnsurer> ensurer;
210         if (currentMode() != TEXT_MODE)
211                 ensurer = make_unique<MathEnsurer>(os);
212         else
213                 ensurer = make_unique<MathEnsurer>(os, false, true, true);
214         os << '\\' << name();
215
216         // $,#, etc. In theory the restriction based on catcodes, but then
217         // we do not handle catcodes very well, let alone cat code changes,
218         // so being outside the alpha range is good enough.
219         if (name().size() == 1 && !isAlphaASCII(name()[0]))
220                 return;
221
222         os.pendingSpace(true);
223         writeLimits(os);
224 }
225
226
227 void InsetMathSymbol::infoize2(odocstream & os) const
228 {
229         os << from_ascii("Symbol: ") << name();
230 }
231
232
233 void InsetMathSymbol::validate(LaTeXFeatures & features) const
234 {
235         // this is not really the ideal place to do this, but we can't
236         // validate in InsetMathExInt.
237         if (features.runparams().math_flavor == OutputParams::MathAsHTML
238             && sym_->name == from_ascii("int")) {
239                 features.addCSSSnippet(
240                         "span.limits{display: inline-block; vertical-align: middle; text-align:center; font-size: 75%;}\n"
241                         "span.limits span{display: block;}\n"
242                         "span.intsym{font-size: 150%;}\n"
243                         "sub.limit{font-size: 75%;}\n"
244                         "sup.limit{font-size: 75%;}");
245         } else {
246                 if (!sym_->required.empty())
247                         features.require(sym_->required);
248         }
249 }
250
251 } // namespace lyx