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