]> git.lyx.org Git - features.git/blob - src/mathed/math_scriptinset.C
b68c70f26fc786a597c4ecfac6da791f5bb8d5ce
[features.git] / src / mathed / math_scriptinset.C
1 #include <config.h>
2 #include "debug.h"
3 #include "support.h"
4 #include "support/LOstream.h"
5 #include "support/LAssert.h"
6
7 #ifdef __GNUG__
8 #pragma implementation
9 #endif
10
11 #include "math_scriptinset.h"
12
13
14 MathScriptInset::MathScriptInset()
15         : MathNestInset(2), limits_(0)
16 {
17         script_[0] = false;
18         script_[1] = false;
19 }
20
21
22 MathScriptInset::MathScriptInset(bool up)
23         : MathNestInset(2), limits_(0)
24 {
25         script_[0] = !up;
26         script_[1] = up;
27 }
28
29
30
31 MathInset * MathScriptInset::clone() const
32 {
33         return new MathScriptInset(*this);
34 }
35
36
37 MathScriptInset const * MathScriptInset::asScriptInset() const
38 {
39         return this;
40 }
41
42
43 MathScriptInset * MathScriptInset::asScriptInset()
44 {
45         return this;
46 }
47
48
49 MathXArray const & MathScriptInset::up() const
50 {
51         return xcell(1);
52 }
53
54
55 MathXArray const & MathScriptInset::down() const
56 {
57         return xcell(0);
58 }
59
60
61 MathXArray & MathScriptInset::up()
62 {
63         return xcell(1);
64 }
65
66
67 MathXArray & MathScriptInset::down()
68 {
69         return xcell(0);
70 }
71
72
73 void MathScriptInset::ensure(bool up)
74 {
75         script_[up] = true;
76 }
77
78
79 int MathScriptInset::dy0(MathInset const * nuc) const
80 {
81         int nd = ndes(nuc);
82         if (!hasDown())
83                 return nd;
84         int des = down().ascent();
85         if (hasLimits(nuc))
86                 des += nd + 2;
87         else 
88                 des = std::max(des, nd);
89         return des;
90 }
91
92
93 int MathScriptInset::dy1(MathInset const * nuc) const
94 {
95         int na = nasc(nuc);
96         if (!hasUp())
97                 return na;
98         int asc = up().descent();
99         if (hasLimits(nuc))
100                 asc += na + 2;
101         else 
102                 asc = std::max(asc, na);
103         asc = std::max(asc, mathed_char_ascent(LM_TC_VAR, mi_, 'I'));
104         return asc;
105 }
106
107
108 int MathScriptInset::dx0(MathInset const * nuc) const
109 {
110         lyx::Assert(hasDown());
111         return hasLimits(nuc) ? (width(nuc) - down().width()) / 2 : nwid(nuc);
112 }
113
114
115 int MathScriptInset::dx1(MathInset const * nuc) const
116 {
117         lyx::Assert(hasUp());
118         return hasLimits(nuc) ? (width(nuc) - up().width()) / 2 : nwid(nuc);
119 }
120
121
122 int MathScriptInset::dxx(MathInset const * nuc) const
123 {
124         //lyx::Assert(nuc());
125         return hasLimits(nuc)  ?  (width(nuc) - nwid(nuc)) / 2  :  0;
126 }
127
128
129 int MathScriptInset::ascent(MathInset const * nuc) const
130 {
131         return dy1(nuc) + (hasUp() ? up().ascent() : 0);
132 }
133
134
135 int MathScriptInset::descent(MathInset const * nuc) const
136 {
137         return dy0(nuc) + (hasDown() ? down().descent() : 0);
138 }
139
140
141 int MathScriptInset::width(MathInset const * nuc) const
142 {
143         int wid = 0;
144         if (hasLimits(nuc)) {
145                 wid = nwid(nuc);
146                 if (hasUp())
147                         wid = std::max(wid, up().width());
148                 if (hasDown())
149                         wid = std::max(wid, down().width());
150         } else {
151                 if (hasUp())
152                         wid = std::max(wid, up().width());
153                 if (hasDown())
154                         wid = std::max(wid, down().width());
155                 wid += nwid(nuc);
156         }
157         return wid;
158 }
159
160
161 int MathScriptInset::nwid(MathInset const * nuc) const
162 {
163         return nuc ?
164                 nuc->width() :
165                 mathed_char_width(LM_TC_TEX, mi_, '.');
166 }
167
168
169 int MathScriptInset::nasc(MathInset const * nuc) const
170 {
171         return nuc ? nuc->ascent()
172                 : mathed_char_ascent(LM_TC_VAR, mi_, 'I');
173 }
174
175
176 int MathScriptInset::ndes(MathInset const * nuc) const
177 {
178         return nuc ? nuc->descent()
179                 : mathed_char_descent(LM_TC_VAR, mi_, 'I');
180 }
181
182
183 void MathScriptInset::metrics(MathMetricsInfo const & mi) const
184 {       
185         metrics(0, mi);
186 }
187
188
189 void MathScriptInset::metrics(MathInset const * nuc,
190         MathMetricsInfo const & mi) const
191 {       
192         MathNestInset::metrics(mi);
193         if (nuc)
194                 nuc->metrics(mi);
195
196         ascent_  = ascent(nuc);
197         descent_ = descent(nuc);
198         width_   = width(nuc);
199 }
200
201
202 void MathScriptInset::draw(Painter & pain, int x, int y) const
203 {  
204         //lyxerr << "unexpected call to MathScriptInset::draw()\n";
205         draw(0, pain, x, y);
206 }
207
208
209 void MathScriptInset::draw(MathInset const * nuc, Painter & pain,
210         int x, int y) const
211 {  
212         xo(x);
213         yo(y);
214
215         if (nuc)
216                 nuc->draw(pain, x + dxx(nuc), y);
217         else
218                 drawStr(pain, LM_TC_TEX, mi_, x + dxx(nuc), y, ".");
219
220         if (hasUp())
221                 up().draw(pain, x + dx1(nuc), y - dy1(nuc));
222
223         if (hasDown())
224                 down().draw(pain, x + dx0(nuc), y + dy0(nuc));
225 }
226
227
228 void MathScriptInset::write(MathWriteInfo & os) const
229 {  
230         //lyxerr << "unexpected call to MathScriptInset::write()\n";
231         write(0, os);
232 }
233
234
235 void MathScriptInset::write(MathInset const * nuc, MathWriteInfo & os) const
236 {
237         if (nuc) {
238                 nuc->write(os);
239                 if (nuc->takesLimits()) {
240                         if (limits_ == -1)
241                                 os << "\\nolimits ";
242                         if (limits_ == 1)
243                                 os << "\\limits ";
244                 }
245         }
246         else
247                 os << "{}";
248
249         if (hasDown() && down().data_.size())
250                 os << "_{" << down().data_ << '}';
251
252         if (hasUp() && up().data_.size())
253                 os << "^{" << up().data_ << '}';
254 }
255
256
257 bool MathScriptInset::hasLimits(MathInset const * nuc) const
258 {
259         return limits_ == 1 || (limits_ == 0 && nuc && nuc->isScriptable());
260 }
261
262
263 void MathScriptInset::removeEmptyScripts()
264 {
265         for (int i = 0; i <= 1; ++i)
266                 if (script_[i] && !cell(i).size())
267                         script_[i] = false;
268 }
269
270
271 void MathScriptInset::removeScript(bool up)
272 {
273         cell(up).clear();
274         script_[up] = false;
275 }
276
277
278 bool MathScriptInset::has(bool up) const
279 {
280         return script_[up];
281 }
282
283
284 bool MathScriptInset::hasUp() const
285 {
286         return script_[1];
287 }
288
289
290 bool MathScriptInset::hasDown() const
291 {
292         return script_[0];
293 }
294
295
296 bool MathScriptInset::idxRight(MathInset::idx_type &,
297                                  MathInset::pos_type &) const
298 {
299         return false;
300 }
301
302
303 bool MathScriptInset::idxLeft(MathInset::idx_type &,
304                                 MathInset::pos_type &) const
305 {
306         return false;
307 }
308
309