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 
31 namespace lyx {
32 
InsetMathSymbol(latexkeys const * l)33 InsetMathSymbol::InsetMathSymbol(latexkeys const * l)
34 	: sym_(l), h_(0), kerning_(0), scriptable_(false)
35 {}
36 
37 
InsetMathSymbol(char const * name)38 InsetMathSymbol::InsetMathSymbol(char const * name)
39 	: sym_(in_word_set(from_ascii(name))), h_(0),
40 	  kerning_(0), scriptable_(false)
41 {}
42 
43 
InsetMathSymbol(docstring const & name)44 InsetMathSymbol::InsetMathSymbol(docstring const & name)
45 	: sym_(in_word_set(name)), h_(0), kerning_(0), scriptable_(false)
46 {}
47 
48 
clone() const49 Inset * InsetMathSymbol::clone() const
50 {
51 	return new InsetMathSymbol(*this);
52 }
53 
54 
name() const55 docstring InsetMathSymbol::name() const
56 {
57 	return sym_->name;
58 }
59 
60 
metrics(MetricsInfo & mi,Dimension & dim) const61 void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
62 {
63 	// set dim
64 	mathedSymbolDim(mi.base, dim, sym_);
65 	// set kerning_
66 	kerning_ = mathed_char_kerning(mi.base.font, *sym_->draw.rbegin());
67 	// correct height for broken cmex and wasy font
68 	if (sym_->inset == "cmex" || sym_->inset == "wasy") {
69 		h_ = 4 * dim.des / 5;
70 		dim.asc += h_;
71 		dim.des -= h_;
72 	}
73 	// set scriptable_
74 	scriptable_ = false;
75 	if (mi.base.font.style() == LM_ST_DISPLAY)
76 		if (sym_->inset == "cmex" || sym_->inset == "esint" ||
77 		    sym_->extra == "funclim" ||
78 		    (sym_->inset == "stmry" && sym_->extra == "mathop"))
79 			scriptable_ = true;
80 }
81 
82 
draw(PainterInfo & pi,int x,int y) const83 void InsetMathSymbol::draw(PainterInfo & pi, int x, int y) const
84 {
85 	mathedSymbolDraw(pi, x, y - h_, sym_);
86 }
87 
88 
currentMode() const89 InsetMath::mode_type InsetMathSymbol::currentMode() const
90 {
91 	return sym_->extra == "textmode" ? TEXT_MODE : MATH_MODE;
92 }
93 
94 
isOrdAlpha() const95 bool InsetMathSymbol::isOrdAlpha() const
96 {
97 	return sym_->extra == "mathord" || sym_->extra == "mathalpha";
98 }
99 
100 
mathClass() const101 MathClass InsetMathSymbol::mathClass() const
102 {
103 	if (sym_->extra == "func" || sym_->extra == "funclim")
104 		return MC_OP;
105 	MathClass const mc = string_to_class(sym_->extra);
106 	return (mc == MC_UNKNOWN) ? MC_ORD : mc;
107 }
108 
109 
isScriptable() const110 bool InsetMathSymbol::isScriptable() const
111 {
112 	return scriptable_;
113 }
114 
115 
takesLimits() const116 bool InsetMathSymbol::takesLimits() const
117 {
118 	return
119 		sym_->inset == "cmex" ||
120 		sym_->inset == "lyxboldsymb" ||
121 		sym_->inset == "esint" ||
122 		sym_->extra == "funclim" ||
123 		(sym_->inset == "stmry" && sym_->extra == "mathop");
124 }
125 
126 
normalize(NormalStream & os) const127 void InsetMathSymbol::normalize(NormalStream & os) const
128 {
129 	os << "[symbol " << name() << ']';
130 }
131 
132 
maple(MapleStream & os) const133 void InsetMathSymbol::maple(MapleStream & os) const
134 {
135 	if (name() == "cdot")
136 		os << '*';
137 	else if (name() == "infty")
138 		os << "infinity";
139 	else
140 		os << name();
141 }
142 
maxima(MaximaStream & os) const143 void InsetMathSymbol::maxima(MaximaStream & os) const
144 {
145 	if (name() == "cdot")
146 		os << '*';
147 	else if (name() == "infty")
148 		os << "inf";
149 	else if (name() == "pi")
150 		os << "%pi";
151 	else
152 		os << name();
153 }
154 
155 
mathematica(MathematicaStream & os) const156 void InsetMathSymbol::mathematica(MathematicaStream & os) const
157 {
158 	if ( name() == "pi")    { os << "Pi"; return;}
159 	if ( name() == "infty") { os << "Infinity"; return;}
160 	if ( name() == "cdot")  { os << '*'; return;}
161 	os << name();
162 }
163 
164 
mathmlize(MathStream & os) const165 void InsetMathSymbol::mathmlize(MathStream & os) const
166 {
167 	// FIXME We may need to do more interesting things
168 	// with MathMLtype.
169 	char const * type = sym_->MathMLtype();
170 	os << '<' << type << "> ";
171 	if (sym_->xmlname == "x")
172 		// unknown so far
173 		os << name();
174 	else
175 		os << sym_->xmlname;
176 	os << " </" << type << '>';
177 }
178 
179 
htmlize(HtmlStream & os,bool spacing) const180 void InsetMathSymbol::htmlize(HtmlStream & os, bool spacing) const
181 {
182 	// FIXME We may need to do more interesting things
183 	// with MathMLtype.
184 	char const * type = sym_->MathMLtype();
185 	bool op = (std::string(type) == "mo");
186 
187 	if (sym_->xmlname == "x")
188 		// unknown so far
189 		os << ' ' << name() << ' ';
190 	else if (op && spacing)
191 		os << ' ' << sym_->xmlname << ' ';
192 	else
193 		os << sym_->xmlname;
194 }
195 
196 
htmlize(HtmlStream & os) const197 void InsetMathSymbol::htmlize(HtmlStream & os) const
198 {
199 	htmlize(os, true);
200 }
201 
202 
octave(OctaveStream & os) const203 void InsetMathSymbol::octave(OctaveStream & os) const
204 {
205 	if (name() == "cdot")
206 		os << '*';
207 	else
208 		os << name();
209 }
210 
211 
write(WriteStream & os) const212 void InsetMathSymbol::write(WriteStream & os) const
213 {
214 	unique_ptr<MathEnsurer> ensurer;
215 	if (currentMode() != TEXT_MODE)
216 		ensurer = make_unique<MathEnsurer>(os);
217 	else
218 		ensurer = make_unique<MathEnsurer>(os, false, true, true);
219 	os << '\\' << name();
220 
221 	// $,#, etc. In theory the restriction based on catcodes, but then
222 	// we do not handle catcodes very well, let alone cat code changes,
223 	// so being outside the alpha range is good enough.
224 	if (name().size() == 1 && !isAlphaASCII(name()[0]))
225 		return;
226 
227 	os.pendingSpace(true);
228 }
229 
230 
infoize2(odocstream & os) const231 void InsetMathSymbol::infoize2(odocstream & os) const
232 {
233 	os << from_ascii("Symbol: ") << name();
234 }
235 
236 
validate(LaTeXFeatures & features) const237 void InsetMathSymbol::validate(LaTeXFeatures & features) const
238 {
239 	// this is not really the ideal place to do this, but we can't
240 	// validate in InsetMathExInt.
241 	if (features.runparams().math_flavor == OutputParams::MathAsHTML
242 	    && sym_->name == from_ascii("int")) {
243 		features.addCSSSnippet(
244 			"span.limits{display: inline-block; vertical-align: middle; text-align:center; font-size: 75%;}\n"
245 			"span.limits span{display: block;}\n"
246 			"span.intsym{font-size: 150%;}\n"
247 			"sub.limit{font-size: 75%;}\n"
248 			"sup.limit{font-size: 75%;}");
249 	} else {
250 		if (!sym_->requires.empty())
251 			features.require(sym_->requires);
252 	}
253 }
254 
255 } // namespace lyx
256