]> git.lyx.org Git - lyx.git/blob - src/mathed/InsetMathDecoration.cpp
825b212c9de8970c59640982ade338e02b241a50
[lyx.git] / src / mathed / InsetMathDecoration.cpp
1 /**
2  * \file InsetMathDecoration.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alejandro Aguilar Sierra
7  * \author André Pönitz
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "InsetMathDecoration.h"
15
16 #include "MathData.h"
17 #include "MathExtern.h"
18 #include "MathParser.h"
19 #include "MathSupport.h"
20 #include "MathStream.h"
21 #include "MetricsInfo.h"
22
23 #include "LaTeXFeatures.h"
24
25 #include "support/debug.h"
26 #include "support/lassert.h"
27
28 #include <ostream>
29
30 using namespace std;
31
32 namespace lyx {
33
34
35 InsetMathDecoration::InsetMathDecoration(Buffer * buf, latexkeys const * key)
36         : InsetMathNest(buf, 1), key_(key)
37 {
38 //      lyxerr << " creating deco " << key->name << endl;
39 }
40
41
42 Inset * InsetMathDecoration::clone() const
43 {
44         return new InsetMathDecoration(*this);
45 }
46
47
48 bool InsetMathDecoration::upper() const
49 {
50         return key_->name.substr(0, 5) != "under";
51 }
52
53
54 bool InsetMathDecoration::isScriptable() const
55 {
56         return
57                         key_->name == "overbrace" ||
58                         key_->name == "underbrace" ||
59                         key_->name == "overleftarrow" ||
60                         key_->name == "overrightarrow" ||
61                         key_->name == "overleftrightarrow" ||
62                         key_->name == "underleftarrow" ||
63                         key_->name == "underrightarrow" ||
64                         key_->name == "underleftrightarrow";
65 }
66
67
68 bool InsetMathDecoration::protect() const
69 {
70         return
71                         key_->name == "overbrace" ||
72                         key_->name == "underbrace" ||
73                         key_->name == "overleftarrow" ||
74                         key_->name == "overrightarrow" ||
75                         key_->name == "overleftrightarrow" ||
76                         key_->name == "underleftarrow" ||
77                         key_->name == "underrightarrow" ||
78                         key_->name == "underleftrightarrow";
79 }
80
81
82 bool InsetMathDecoration::wide() const
83 {
84         return
85                         key_->name == "overline" ||
86                         key_->name == "underline" ||
87                         key_->name == "overbrace" ||
88                         key_->name == "underbrace" ||
89                         key_->name == "overleftarrow" ||
90                         key_->name == "overrightarrow" ||
91                         key_->name == "overleftrightarrow" ||
92                         key_->name == "widehat" ||
93                         key_->name == "widetilde" ||
94                         key_->name == "underleftarrow" ||
95                         key_->name == "underrightarrow" ||
96                         key_->name == "underleftrightarrow";
97 }
98
99
100 void InsetMathDecoration::metrics(MetricsInfo & mi, Dimension & dim) const
101 {
102         cell(0).metrics(mi, dim);
103
104         dh_  = 6; //mathed_char_height(LM_TC_VAR, mi, 'I', ascent_, descent_);
105         dw_  = 6; //mathed_char_width(LM_TC_VAR, mi, 'x');
106
107         if (upper()) {
108                 dy_ = -dim.asc - dh_;
109                 dim.asc += dh_ + 1;
110         } else {
111                 dy_ = dim.des + 1;
112                 dim.des += dh_ + 2;
113         }
114
115         metricsMarkers(dim);
116 }
117
118
119 void InsetMathDecoration::draw(PainterInfo & pi, int x, int y) const
120 {
121         cell(0).draw(pi, x + 1, y);
122         Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
123         if (wide())
124                 mathed_draw_deco(pi, x + 1, y + dy_, dim0.wid, dh_, key_->name);
125         else
126                 mathed_draw_deco(pi, x + 1 + (dim0.wid - dw_) / 2,
127                         y + dy_, dw_, dh_, key_->name);
128         drawMarkers(pi, x, y);
129         setPosCache(pi, x, y);
130 }
131
132
133 void InsetMathDecoration::write(WriteStream & os) const
134 {
135         MathEnsurer ensurer(os);
136         if (os.fragile() && protect())
137                 os << "\\protect";
138         os << '\\' << key_->name << '{' << cell(0) << '}';
139 }
140
141
142 void InsetMathDecoration::normalize(NormalStream & os) const
143 {
144         os << "[deco " << key_->name << ' ' <<  cell(0) << ']';
145 }
146
147
148 void InsetMathDecoration::infoize(odocstream & os) const
149 {
150         os << "Deco: " << key_->name;
151 }
152
153
154 void InsetMathDecoration::validate(LaTeXFeatures & features) const
155 {
156         if (!key_->requires.empty())
157                 features.require(to_utf8(key_->requires));
158         InsetMathNest::validate(features);
159 }
160
161 namespace {
162         struct Attributes {
163                 Attributes() {}
164                 Attributes(bool o, string t)
165                         : over(o), tag(t) {}
166                 bool over;
167                 string tag;
168         };
169
170         typedef map<string, Attributes> Translator;
171
172         void buildTranslator(Translator & t) {
173                 // the decorations we need to support are listed in lib/symbols
174                 t["acute"] = Attributes(true, "&acute;");
175                 t["bar"]   = Attributes(true, "&OverBar;");
176                 t["breve"] = Attributes(true, "&breve;");
177                 t["check"] = Attributes(true, "&caron;");
178                 t["ddddot"] = Attributes(true, "&DotDot;");
179                 t["dddot"] = Attributes(true, "&TripleDot;");
180                 t["ddot"] = Attributes(true, "&Dot;");
181                 t["dot"] = Attributes(true, "&dot;");
182                 t["grave"] = Attributes(true, "&grave;");
183                 t["hat"] = Attributes(true, "&circ;");
184                 t["mathring"] = Attributes(true, "&ring;");
185                 t["overbrace"] = Attributes(true, "&OverBrace;");
186                 t["overleftarrow"] = Attributes(true, "&xlarr;");
187                 t["overleftrightarrow"] = Attributes(true, "&xharr;");
188                 t["overrightarrow"] = Attributes(true, "&xrarr;");
189                 t["tilde"] = Attributes(true, "&tilde;");
190                 t["underbar"] = Attributes(false, "&UnderBar;");
191                 t["underbrace"] = Attributes(false, "&UnderBrace;");
192                 t["underleftarrow"] = Attributes(false, "&xlarr;");
193                 t["underleftrightarrow"] = Attributes(false, "&xharr;");
194                 t["underline"] = Attributes(false, "&;");
195                 t["underrightarrow"] = Attributes(false, "&xrarr;");
196                 t["vec"] = Attributes(true, "&rarr;");
197                 t["widehat"] = Attributes(true, "&Hat;");
198                 t["widetilde"] = Attributes(true, "&Tilde;");
199         }
200
201         Translator const & translator() {
202                 static Translator t;
203                 if (t.empty())
204                         buildTranslator(t);
205                 return t;
206         }
207 }
208
209 docstring InsetMathDecoration::mathmlize(MathStream & os) const
210 {
211         Translator const & t = translator();
212         Translator::const_iterator cur = t.find(to_utf8(key_->name));
213         LASSERT(cur != t.end(), return docstring());
214         char const * const outag = cur->second.over ? "mover" : "munder";
215         os << MTag(outag) << MTag("mrow");
216         docstring const rv = lyx::mathmlize(cell(0), os);
217         os << ETag("mrow")
218                  << from_ascii("<mo stretchy=\"true\">" + cur->second.tag + "</mo>")
219                  << ETag(outag);
220         return rv;
221 }
222
223
224 } // namespace lyx