]> git.lyx.org Git - lyx.git/blob - src/mathed/math_scriptinset.C
fix typo that put too many include paths for most people
[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(font_, '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 ?  nuc->width() : mathed_char_width(font_, '.');
165 }
166
167
168 int MathScriptInset::nasc(MathInset const * nuc) const
169 {
170         return nuc ? nuc->ascent() : mathed_char_ascent(font_, 'I');
171 }
172
173
174 int MathScriptInset::ndes(MathInset const * nuc) const
175 {
176         return nuc ? nuc->descent() : mathed_char_descent(font_, 'I');
177 }
178
179
180 void MathScriptInset::metrics(MathMetricsInfo const & mi) const
181 {
182         metrics(0, mi);
183 }
184
185
186 void MathScriptInset::metrics(MathInset const * nuc,
187         MathMetricsInfo const & mi) const
188 {
189         MathMetricsInfo m = mi;
190         smallerStyleScript(m);
191         MathNestInset::metrics(m);
192         whichFont(font_, LM_TC_VAR, m);
193         if (nuc)
194                 nuc->metrics(mi);
195         ascent_  = ascent2(nuc);
196         descent_ = descent2(nuc);
197         width_   = width2(nuc);
198 }
199
200
201 void MathScriptInset::draw(Painter & pain, int x, int y) const
202 {
203         //lyxerr << "unexpected call to MathScriptInset::draw()\n";
204         draw(0, pain, x, y);
205 }
206
207
208 void MathScriptInset::metricsT(TextMetricsInfo const & mi) const
209 {
210         metricsT(0, mi);
211 }
212
213
214 void MathScriptInset::metricsT(MathInset const * nuc,
215         TextMetricsInfo const & mi) const
216 {
217         if (hasUp())
218                 up().metricsT(mi);
219         if (hasDown())
220                 down().metricsT(mi);
221         if (nuc)
222                 nuc->metricsT(mi);
223         //ascent_  = ascent2(nuc);
224         //descent_ = descent2(nuc);
225         //width_   = width2(nuc);
226 }
227
228
229 void MathScriptInset::draw(MathInset const * nuc, Painter & pain,
230         int x, int y) const
231 {
232         if (nuc)
233                 nuc->draw(pain, x + dxx(nuc), y);
234         else // if (editing())
235                 drawStr(pain, font_, x + dxx(nuc), y, ".");
236
237         if (hasUp())
238                 up().draw(pain, x + dx1(nuc), y - dy1(nuc));
239
240         if (hasDown())
241                 down().draw(pain, x + dx0(nuc), y + dy0(nuc));
242 }
243
244 void MathScriptInset::drawT(TextPainter & pain, int x, int y) const
245 {
246         //lyxerr << "unexpected call to MathScriptInset::draw()\n";
247         drawT(0, pain, x, y);
248 }
249
250
251 void MathScriptInset::drawT(MathInset const * nuc, TextPainter & pain,
252         int x, int y) const
253 {
254         if (nuc)
255                 nuc->drawT(pain, x + dxx(nuc), y);
256         if (hasUp())
257                 up().drawT(pain, x + dx1(nuc), y - dy1(nuc));
258         if (hasDown())
259                 down().drawT(pain, x + dx0(nuc), y + dy0(nuc));
260 }
261
262
263
264 bool MathScriptInset::hasLimits(MathInset const * nuc) const
265 {
266         // obviuos cases
267         if (limits_ == 1)
268                 return true;
269         if (limits_ == -1)
270                 return false;
271
272         // we can only display limits if the nucleus wants some
273         if (!nuc)
274                 return false;
275         if (!nuc->isScriptable())
276                 return false;
277
278         // per default \int has limits beside the \int even in displayed formulas
279         if (nuc->asSymbolInset())
280                 if (nuc->asSymbolInset()->name().find("int") != string::npos)
281                         return false;
282
283         // assume "real" limits for everything else
284         return true;
285 }
286
287
288 void MathScriptInset::removeEmptyScripts()
289 {
290         for (int i = 0; i <= 1; ++i)
291                 if (script_[i] && cell(i).size() == 0) {
292                         cell(i).clear();
293                         script_[i] = false;
294                 }
295 }
296
297
298 void MathScriptInset::removeScript(bool up)
299 {
300         cell(up).clear();
301         script_[up] = false;
302 }
303
304
305 bool MathScriptInset::has(bool up) const
306 {
307         return script_[up];
308 }
309
310
311 bool MathScriptInset::empty() const
312 {
313         return !script_[0] && !script_[1];
314 }
315
316
317 bool MathScriptInset::hasUp() const
318 {
319         return script_[1];
320 }
321
322
323 bool MathScriptInset::hasDown() const
324 {
325         return script_[0];
326 }
327
328
329 bool MathScriptInset::idxRight(MathInset::idx_type &,
330                                  MathInset::pos_type &) const
331 {
332         return false;
333 }
334
335
336 bool MathScriptInset::idxLeft(MathInset::idx_type &,
337                                 MathInset::pos_type &) const
338 {
339         return false;
340 }
341
342
343 void MathScriptInset::write(WriteStream & os) const
344 {
345         //lyxerr << "unexpected call to MathScriptInset::write()\n";
346         write2(0, os);
347 }
348
349
350 void MathScriptInset::write2(MathInset const * nuc, WriteStream & os) const
351 {
352         if (nuc) {
353                 os << nuc;
354                 if (nuc->takesLimits()) {
355                         if (limits_ == -1)
356                                 os << "\\nolimits ";
357                         if (limits_ == 1)
358                                 os << "\\limits ";
359                 }
360         } else
361                         if (os.firstitem())
362                                 lyxerr << "suppressing {} \n";
363                         else
364                                 os << "{}";
365
366         if (hasDown() && down().data_.size())
367                 os << "_{" << down().data_ << '}';
368
369         if (hasUp() && up().data_.size())
370                 os << "^{" << up().data_ << '}';
371 }
372
373
374 void MathScriptInset::normalize(NormalStream & os) const
375 {
376         //lyxerr << "unexpected call to MathScriptInset::normalize()\n";
377         normalize2(0, os);
378 }
379
380
381 void MathScriptInset::normalize2(MathInset const * nuc, NormalStream & os) const
382 {
383         bool d = hasDown() && down().data_.size();
384         bool u = hasUp() && up().data_.size();
385
386         if (u)
387                 os << "[sup ";
388         if (d)
389                 os << "[sub ";
390
391         if (nuc)
392                 os << nuc << ' ';
393         else
394                 os << "[par]";
395
396         if (d)
397                 os << down().data_ << ']';
398         if (u)
399                 os << up().data_ << ']';
400 }
401
402
403 void MathScriptInset::maplize2(MathInset const * nuc, MapleStream & os) const
404 {
405         if (nuc)
406                 os << nuc;
407         if (hasDown() && down().data_.size())
408                 os << '[' << down().data_ << ']';
409         if (hasUp() && up().data_.size())
410                 os << "^(" << up().data_ << ')';
411 }
412
413
414 void MathScriptInset::mathmlize2(MathInset const * nuc, MathMLStream & os) const
415 {
416         bool d = hasDown() && down().data_.size();
417         bool u = hasUp() && up().data_.size();
418
419         if (u && d)
420                 os << MTag("msubsup");
421         else if (u)
422                 os << MTag("msup");
423         else if (d)
424                 os << MTag("msub");
425
426         if (nuc)
427                 os << nuc;
428         else
429                 os << "<mrow/>";
430
431         if (u && d)
432                 os << down().data_ << up().data_ << ETag("msubsup");
433         else if (u)
434                 os << up().data_ << ETag("msup");
435         else if (d)
436                 os << down().data_ << ETag("msub");
437 }
438
439
440 void MathScriptInset::octavize2(MathInset const * nuc, OctaveStream & os) const
441 {
442         if (nuc)
443                 os << nuc;
444         if (hasDown() && down().data_.size())
445                 os << '[' << down().data_ << ']';
446         if (hasUp() && up().data_.size())
447                 os << "^(" << up().data_ << ')';
448 }