]> git.lyx.org Git - lyx.git/blob - src/mathed/math_scriptinset.C
remove noload/don't typeset
[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 "funcrequest.h"
10 #include "support/LAssert.h"
11 #include "debug.h"
12
13
14 using std::max;
15
16
17 MathScriptInset::MathScriptInset()
18         : MathNestInset(3), limits_(0)
19 {
20         script_[0] = false;
21         script_[1] = false;
22 }
23
24
25 MathScriptInset::MathScriptInset(bool up)
26         : MathNestInset(3), limits_(0)
27 {
28         script_[0] = !up;
29         script_[1] = up;
30 }
31
32
33 MathScriptInset::MathScriptInset(MathAtom const & at, bool up)
34         : MathNestInset(3), limits_(0)
35 {
36         script_[0] = !up;
37         script_[1] = up;
38         cell(2).push_back(at);
39 }
40
41
42
43 MathInset * MathScriptInset::clone() const
44 {
45         return new MathScriptInset(*this);
46 }
47
48
49 MathScriptInset const * MathScriptInset::asScriptInset() const
50 {
51         return this;
52 }
53
54
55 MathScriptInset * MathScriptInset::asScriptInset()
56 {
57         return this;
58 }
59
60
61 bool MathScriptInset::idxFirst(idx_type & idx, pos_type & pos) const
62 {
63         idx = 2;
64         pos = 0;
65         return true;
66 }
67
68
69 bool MathScriptInset::idxLast(idx_type & idx, pos_type & pos) const
70 {
71         idx = 2;
72         pos = nuc().size();
73         return true;
74 }
75
76
77 MathArray const & MathScriptInset::down() const
78 {
79         return cell(0);
80 }
81
82
83 MathArray & MathScriptInset::down()
84 {
85         return cell(0);
86 }
87
88
89 MathArray const & MathScriptInset::up() const
90 {
91         return cell(1);
92 }
93
94
95 MathArray & MathScriptInset::up()
96 {
97         return cell(1);
98 }
99
100
101 void MathScriptInset::ensure(bool up)
102 {
103         script_[up] = true;
104 }
105
106
107 MathArray const & MathScriptInset::nuc() const
108 {
109         return cell(2);
110 }
111
112
113 MathArray & MathScriptInset::nuc()
114 {
115         return cell(2);
116 }
117
118
119 int MathScriptInset::dy0() const
120 {
121         int nd = ndes();
122         if (!hasDown())
123                 return nd;
124         int des = down().ascent();
125         if (hasLimits())
126                 des += nd + 2;
127         else
128                 des = max(des, nd);
129         return des;
130 }
131
132
133 int MathScriptInset::dy1() const
134 {
135         int na = nasc();
136         if (!hasUp())
137                 return na;
138         int asc = up().descent();
139         if (hasLimits())
140                 asc += na + 2;
141         else
142                 asc = max(asc, na);
143         asc = max(asc, 5);
144         return asc;
145 }
146
147
148 int MathScriptInset::dx0() const
149 {
150         lyx::Assert(hasDown());
151         return hasLimits() ? (dim_.w - down().width()) / 2 : nwid();
152 }
153
154
155 int MathScriptInset::dx1() const
156 {
157         lyx::Assert(hasUp());
158         return hasLimits() ? (dim_.w - up().width()) / 2 : nwid();
159 }
160
161
162 int MathScriptInset::dxx() const
163 {
164         return hasLimits() ? (dim_.w - nwid()) / 2  :  0;
165 }
166
167
168 int MathScriptInset::nwid() const
169 {
170         return nuc().size() ? nuc().width() : 2;
171 }
172
173
174 int MathScriptInset::nasc() const
175 {
176         return nuc().size() ? nuc().ascent() : 5;
177 }
178
179
180 int MathScriptInset::ndes() const
181 {
182         return nuc().size() ? nuc().descent() : 0;
183 }
184
185
186 void MathScriptInset::metrics(MathMetricsInfo & mi) const
187 {
188         cell(2).metrics(mi);
189         MathScriptChanger dummy(mi.base);
190         cell(0).metrics(mi);
191         cell(1).metrics(mi);
192         dim_.w = 0;
193         if (hasLimits()) {
194                 dim_.w = nwid();
195                 if (hasUp())
196                         dim_.w = max(dim_.w, up().width());
197                 if (hasDown())
198                         dim_.w = max(dim_.w, down().width());
199         } else {
200                 if (hasUp())
201                         dim_.w = max(dim_.w, up().width());
202                 if (hasDown())
203                         dim_.w = max(dim_.w, down().width());
204                 dim_.w += nwid();
205         }
206         dim_.a = dy1() + (hasUp() ? up().ascent() : 0);
207         dim_.d = dy0() + (hasDown() ? down().descent() : 0);
208         metricsMarkers2();
209 }
210
211
212 void MathScriptInset::draw(MathPainterInfo & pi, int x, int y) const
213 {
214         if (nuc().size())
215                 nuc().draw(pi, x + dxx(), y);
216         else if (editing())
217                 drawStr(pi, pi.base.font, x + dxx(), y, ".");
218         MathScriptChanger dummy(pi.base);
219         if (hasUp())
220                 up().draw(pi, x + dx1(), y - dy1());
221         if (hasDown())
222                 down().draw(pi, x + dx0(), y + dy0());
223         drawMarkers2(pi, x, y);
224 }
225
226
227 void MathScriptInset::metricsT(TextMetricsInfo const & mi) const
228 {
229         if (hasUp())
230                 up().metricsT(mi);
231         if (hasDown())
232                 down().metricsT(mi);
233         nuc().metricsT(mi);
234 }
235
236
237 void MathScriptInset::drawT(TextPainter & pain, int x, int y) const
238 {
239         if (nuc().size())
240                 nuc().drawT(pain, x + dxx(), y);
241         if (hasUp())
242                 up().drawT(pain, x + dx1(), y - dy1());
243         if (hasDown())
244                 down().drawT(pain, x + dx0(), y + dy0());
245 }
246
247
248
249 bool MathScriptInset::hasLimits() const
250 {
251         // obvious cases
252         if (limits_ == 1)
253                 return true;
254         if (limits_ == -1)
255                 return false;
256
257         // we can only display limits if the nucleus wants some
258         if (!nuc().size())
259                 return false;
260         if (!nuc().back()->isScriptable())
261                 return false;
262
263         // per default \int has limits beside the \int even in displayed formulas
264         if (nuc().back()->asSymbolInset())
265                 if (nuc().back()->asSymbolInset()->name().find("int") != string::npos)
266                         return false;
267
268         // assume "real" limits for everything else
269         return true;
270 }
271
272
273 void MathScriptInset::removeEmptyScripts()
274 {
275         for (int i = 0; i <= 1; ++i)
276                 if (script_[i] && cell(i).size() == 0) {
277                         cell(i).clear();
278                         script_[i] = false;
279                 }
280 }
281
282
283 void MathScriptInset::removeScript(bool up)
284 {
285         cell(up).clear();
286         script_[up] = false;
287 }
288
289
290 bool MathScriptInset::has(bool up) const
291 {
292         return script_[up];
293 }
294
295
296 bool MathScriptInset::hasUp() const
297 {
298         return script_[1];
299 }
300
301
302 bool MathScriptInset::hasDown() const
303 {
304         return script_[0];
305 }
306
307
308 bool MathScriptInset::idxRight(idx_type &, pos_type &) const
309 {
310         return false;
311 }
312
313
314 bool MathScriptInset::idxLeft(idx_type &, pos_type &) const
315 {
316         return false;
317 }
318
319
320 bool MathScriptInset::idxUpDown(idx_type & idx, pos_type & pos, bool up,
321         int) const
322 {
323         if (idx == 1) {
324                 // if we are 'up' we can't go further up
325                 if (up)
326                         return false;
327                 // otherwise go to last base position
328                 idx = 2;
329                 pos = cell(2).size();   
330         }
331
332         else if (idx == 0) {
333                 // if we are 'down' we can't go further down
334                 if (!up)
335                         return false;
336                 idx = 2;
337                 pos = cell(2).size();   
338         }
339         
340         else {
341                 // in nucleus
342                 // don't go up/down unless in last position
343                 if (pos != cell(2).size())
344                         return false;   
345                 // don't go up/down if there is no cell.
346                 if (!has(up))
347                         return false;
348                 // otherwise move into the first position
349                 idx = up;
350                 pos = 0;
351         }
352         return true;
353 }
354
355
356 void MathScriptInset::write(WriteStream & os) const
357 {
358         if (nuc().size()) {
359                 os << nuc();
360                 if (nuc().back()->takesLimits()) {
361                         if (limits_ == -1)
362                                 os << "\\nolimits ";
363                         if (limits_ == 1)
364                                 os << "\\limits ";
365                 }
366         } else {
367                 if (os.firstitem())
368                         lyxerr[Debug::MATHED] << "suppressing {} when writing\n";
369                 else
370                         os << "{}";
371         }
372
373         if (hasDown() && down().size())
374                 os << "_{" << down() << '}';
375
376         if (hasUp() && up().size())
377                 os << "^{" << up() << '}';
378
379         if (lock_ && !os.latex())
380                 os << "\\lyxlock ";
381 }
382
383
384 void MathScriptInset::normalize(NormalStream & os) const
385 {
386         bool d = hasDown() && down().size();
387         bool u = hasUp() && up().size();
388
389         if (u && d)
390                 os << "[subsup ";
391         else if (u)
392                 os << "[sup ";
393         else if (d)
394                 os << "[sub ";
395
396         if (nuc().size())
397                 os << nuc() << ' ';
398         else
399                 os << "[par]";
400
401         if (u && d)
402                 os << down() << ' ' << up() << ']';
403         else if (d)
404                 os << down() << ']';
405         else if (u)
406                 os << up() << ']';
407 }
408
409
410 void MathScriptInset::maplize(MapleStream & os) const
411 {
412         if (nuc().size())
413                 os << nuc();
414         if (hasDown() && down().size())
415                 os << '[' << down() << ']';
416         if (hasUp() && up().size())
417                 os << "^(" << up() << ')';
418 }
419
420
421 void MathScriptInset::mathematicize(MathematicaStream & os) const
422 {
423         bool d = hasDown() && down().size();
424         bool u = hasUp() && up().size();
425
426         if (nuc().size()) {
427                 if (d) 
428                         os << "Subscript[" << nuc();
429                 else
430                         os << nuc();
431         }
432
433         if (u)
434                 os << "^(" << up() << ")";
435
436         if (nuc().size())
437                 if (d)
438                         os << "," << down() << "]"; 
439 }
440
441
442 void MathScriptInset::mathmlize( MathMLStream & os) const
443 {
444         bool d = hasDown() && down().size();
445         bool u = hasUp() && up().size();
446
447         if (u && d)
448                 os << MTag("msubsup");
449         else if (u)
450                 os << MTag("msup");
451         else if (d)
452                 os << MTag("msub");
453
454         if (nuc().size())
455                 os << nuc();
456         else
457                 os << "<mrow/>";
458
459         if (u && d)
460                 os << down() << up() << ETag("msubsup");
461         else if (u)
462                 os << up() << ETag("msup");
463         else if (d)
464                 os << down() << ETag("msub");
465 }
466
467
468 void MathScriptInset::octavize(OctaveStream & os) const
469 {
470         if (nuc().size())
471                 os << nuc();
472         if (hasDown() && down().size())
473                 os << '[' << down() << ']';
474         if (hasUp() && up().size())
475                 os << "^(" << up() << ')';
476 }
477
478
479 void MathScriptInset::infoize(std::ostream & os) const
480 {
481         os << "Scripts";
482         if (limits_)
483                 os << (limits_ == 1 ? ", Displayed limits" : ", Inlined limits");
484 }
485
486
487 MathInset::result_type MathScriptInset::dispatch
488         (FuncRequest const & cmd, idx_type & idx, pos_type & pos)
489 {
490         if (cmd.action == LFUN_MATH_LIMITS) {
491                 limits_ = limits_ < 0 ? 1 : -1;
492                 return DISPATCHED;
493         }
494
495         return MathNestInset::dispatch(cmd, idx, pos);
496 }