]> git.lyx.org Git - lyx.git/blob - src/mathed/math_scriptinset.C
to much stuff for my liking...
[lyx.git] / src / mathed / math_scriptinset.C
1 #ifdef __GNUG__
2 #pragma implementation
3 #endif
4
5 #include "math_scriptinset.h"
6 #include "math_support.h"
7 #include "math_symbolinset.h"
8 #include "math_mathmlstream.h"
9 #include "support/LAssert.h"
10 #include "debug.h"
11
12
13 using std::max;
14
15
16 MathScriptInset::MathScriptInset()
17         : MathNestInset(2), limits_(0)
18 {
19         script_[0] = false;
20         script_[1] = false;
21 }
22
23
24 MathScriptInset::MathScriptInset(bool up)
25         : MathNestInset(2), limits_(0)
26 {
27         script_[0] = !up;
28         script_[1] = up;
29 }
30
31
32 MathInset * MathScriptInset::clone() const
33 {
34         return new MathScriptInset(*this);
35 }
36
37
38 MathScriptInset const * MathScriptInset::asScriptInset() const
39 {
40         return this;
41 }
42
43
44 MathScriptInset * MathScriptInset::asScriptInset()
45 {
46         return this;
47 }
48
49
50 MathXArray const & MathScriptInset::up() const
51 {
52         return xcell(1);
53 }
54
55
56 MathXArray const & MathScriptInset::down() const
57 {
58         return xcell(0);
59 }
60
61
62 MathXArray & MathScriptInset::up()
63 {
64         return xcell(1);
65 }
66
67
68 MathXArray & MathScriptInset::down()
69 {
70         return xcell(0);
71 }
72
73
74 void MathScriptInset::ensure(bool up)
75 {
76         script_[up] = true;
77 }
78
79
80 int MathScriptInset::dy0(MathInset const * nuc) const
81 {
82         int nd = ndes(nuc);
83         if (!hasDown())
84                 return nd;
85         int des = down().ascent();
86         if (hasLimits(nuc))
87                 des += nd + 2;
88         else 
89                 des = max(des, nd);
90         return des;
91 }
92
93
94 int MathScriptInset::dy1(MathInset const * nuc) const
95 {
96         int na = nasc(nuc);
97         if (!hasUp())
98                 return na;
99         int asc = up().descent();
100         if (hasLimits(nuc))
101                 asc += na + 2;
102         else 
103                 asc = max(asc, na);
104         asc = max(asc, mathed_char_ascent(LM_TC_VAR, mi_, 'I'));
105         return asc;
106 }
107
108
109 int MathScriptInset::dx0(MathInset const * nuc) const
110 {
111         lyx::Assert(hasDown());
112         return hasLimits(nuc) ? (width2(nuc) - down().width()) / 2 : nwid(nuc);
113 }
114
115
116 int MathScriptInset::dx1(MathInset const * nuc) const
117 {
118         lyx::Assert(hasUp());
119         return hasLimits(nuc) ? (width2(nuc) - up().width()) / 2 : nwid(nuc);
120 }
121
122
123 int MathScriptInset::dxx(MathInset const * nuc) const
124 {
125         //lyx::Assert(nuc());
126         return hasLimits(nuc)  ?  (width2(nuc) - nwid(nuc)) / 2  :  0;
127 }
128
129
130 int MathScriptInset::ascent2(MathInset const * nuc) const
131 {
132         return dy1(nuc) + (hasUp() ? up().ascent() : 0);
133 }
134
135
136 int MathScriptInset::descent2(MathInset const * nuc) const
137 {
138         return dy0(nuc) + (hasDown() ? down().descent() : 0);
139 }
140
141
142 int MathScriptInset::width2(MathInset const * nuc) const
143 {
144         int wid = 0;
145         if (hasLimits(nuc)) {
146                 wid = nwid(nuc);
147                 if (hasUp())
148                         wid = max(wid, up().width());
149                 if (hasDown())
150                         wid = max(wid, down().width());
151         } else {
152                 if (hasUp())
153                         wid = max(wid, up().width());
154                 if (hasDown())
155                         wid = max(wid, down().width());
156                 wid += nwid(nuc);
157         }
158         return wid;
159 }
160
161
162 int MathScriptInset::nwid(MathInset const * nuc) const
163 {
164         return nuc ?
165                 nuc->width() :
166                 mathed_char_width(LM_TC_TEX, mi_, '.');
167 }
168
169
170 int MathScriptInset::nasc(MathInset const * nuc) const
171 {
172         return nuc ? nuc->ascent()
173                 : mathed_char_ascent(LM_TC_VAR, mi_, 'I');
174 }
175
176
177 int MathScriptInset::ndes(MathInset const * nuc) const
178 {
179         return nuc ? nuc->descent()
180                 : mathed_char_descent(LM_TC_VAR, mi_, 'I');
181 }
182
183
184 void MathScriptInset::metrics(MathMetricsInfo const & mi) const
185 {       
186         metrics(0, mi);
187 }
188
189
190 void MathScriptInset::metrics(MathInset const * nuc,
191         MathMetricsInfo const & mi) const
192 {       
193         mi_ = mi;
194         smallerStyleScript(mi_);
195         MathNestInset::metrics(mi_);
196         if (nuc)
197                 nuc->metrics(mi);
198         ascent_  = ascent2(nuc);
199         descent_ = descent2(nuc);
200         width_   = width2(nuc);
201 }
202
203
204 void MathScriptInset::draw(Painter & pain, int x, int y) const
205 {  
206         //lyxerr << "unexpected call to MathScriptInset::draw()\n";
207         draw(0, pain, x, y);
208 }
209
210
211 void MathScriptInset::draw(MathInset const * nuc, Painter & pain,
212         int x, int y) const
213 {  
214         if (nuc)
215                 nuc->draw(pain, x + dxx(nuc), y);
216         else if (editing())
217                 drawStr(pain, LM_TC_TEX, mi_, x + dxx(nuc), y, ".");
218
219         if (hasUp())
220                 up().draw(pain, x + dx1(nuc), y - dy1(nuc));
221
222         if (hasDown())
223                 down().draw(pain, x + dx0(nuc), y + dy0(nuc));
224 }
225
226
227 bool MathScriptInset::hasLimits(MathInset const * nuc) const
228 {
229         // obviuos cases
230         if (limits_ == 1)
231                 return true;
232         if (limits_ == -1)
233                 return false;
234
235         // we can only display limits if the nucleus wants some 
236         if (!nuc)
237                 return false;
238         if (!nuc->isScriptable())
239                 return false;
240         
241         // per default \int has limits beside the \int even in displayed formulas
242         if (nuc->asSymbolInset())
243                 if (nuc->asSymbolInset()->name().find("int") != string::npos)
244                         return false;
245
246         // assume "real" limits for everything else
247         return true;
248 }
249
250
251 void MathScriptInset::removeEmptyScripts()
252 {
253         for (int i = 0; i <= 1; ++i)
254                 if (script_[i] && !cell(i).size())
255                         script_[i] = false;
256 }
257
258
259 void MathScriptInset::removeScript(bool up)
260 {
261         cell(up).clear();
262         script_[up] = false;
263 }
264
265
266 bool MathScriptInset::has(bool up) const
267 {
268         return script_[up];
269 }
270
271
272 bool MathScriptInset::empty() const
273 {
274         return !script_[0] && !script_[1];
275 }
276
277
278 bool MathScriptInset::hasUp() const
279 {
280         return script_[1];
281 }
282
283
284 bool MathScriptInset::hasDown() const
285 {
286         return script_[0];
287 }
288
289
290 bool MathScriptInset::idxRight(MathInset::idx_type &,
291                                  MathInset::pos_type &) const
292 {
293         return false;
294 }
295
296
297 bool MathScriptInset::idxLeft(MathInset::idx_type &,
298                                 MathInset::pos_type &) const
299 {
300         return false;
301 }
302
303
304 void MathScriptInset::write(WriteStream & os) const
305 {  
306         //lyxerr << "unexpected call to MathScriptInset::write()\n";
307         write2(0, os);
308 }
309
310
311 void MathScriptInset::write2(MathInset const * nuc, WriteStream & os) const
312 {
313         if (nuc) {
314                 os << nuc;
315                 if (nuc->takesLimits()) {
316                         if (limits_ == -1)
317                                 os << "\\nolimits ";
318                         if (limits_ == 1)
319                                 os << "\\limits ";
320                 }
321         } else
322                         if (os.firstitem())
323                                 lyxerr << "suppressing {} \n";
324                         else
325                                 os << "{}";
326
327         if (hasDown() && down().data_.size())
328                 os << "_{" << down().data_ << '}';
329
330         if (hasUp() && up().data_.size())
331                 os << "^{" << up().data_ << '}';
332 }
333
334
335 void MathScriptInset::normalize(NormalStream & os) const
336 {  
337         //lyxerr << "unexpected call to MathScriptInset::normalize()\n";
338         normalize2(0, os);
339 }
340
341
342 void MathScriptInset::normalize2(MathInset const * nuc, NormalStream & os) const
343 {
344         bool d = hasDown() && down().data_.size();
345         bool u = hasUp() && up().data_.size();
346
347         if (u) 
348                 os << "[sup ";
349         if (d)
350                 os << "[sub ";
351         
352         if (nuc)
353                 os << nuc << ' ';
354         else
355                 os << "[par]";
356
357         if (d)
358                 os << down().data_ << ']';
359         if (u) 
360                 os << up().data_ << ']';
361 }
362
363
364 void MathScriptInset::maplize2(MathInset const * nuc, MapleStream & os) const
365 {
366         if (nuc)
367                 os << nuc;
368         if (hasDown() && down().data_.size())
369                 os << '[' << down().data_ << ']';
370         if (hasUp() && up().data_.size())
371                 os << "^(" << up().data_ << ')';
372 }
373
374
375 void MathScriptInset::mathmlize2(MathInset const * nuc, MathMLStream & os) const
376 {
377         bool d = hasDown() && down().data_.size();
378         bool u = hasUp() && up().data_.size();
379
380         if (u && d)
381                 os << MTag("msubsup");
382         else if (u)
383                 os << MTag("msup");
384         else if (d)
385                 os << MTag("msub");
386
387         if (nuc)
388                 os << nuc;
389         else
390                 os << "<mrow/>";
391
392         if (u && d)
393                 os << down().data_ << up().data_ << ETag("msubsup");
394         else if (u)
395                 os << up().data_ << ETag("msup");
396         else if (d)
397                 os << down().data_ << ETag("msub");
398 }
399
400
401 void MathScriptInset::octavize2(MathInset const * nuc, OctaveStream & os) const
402 {
403         if (nuc)
404                 os << nuc;
405         if (hasDown() && down().data_.size())
406                 os << '[' << down().data_ << ']';
407         if (hasUp() && up().data_.size())
408                 os << "^(" << up().data_ << ')';
409 }
410
411