]> git.lyx.org Git - lyx.git/blob - src/mathed/math_scriptinset.C
use stream-like syntax for LaTeX output
[lyx.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, LM_ST_TEXT, '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, LM_ST_TEXT, '.');
166 }
167
168
169 int MathScriptInset::nasc(MathInset const * nuc) const
170 {
171         return nuc ? nuc->ascent()
172                 : mathed_char_ascent(LM_TC_VAR, LM_ST_TEXT, '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, LM_ST_TEXT, 'I');
180 }
181
182
183 void MathScriptInset::metrics(MathMetricsInfo const & st) const
184 {       
185         metrics(0, st);
186 }
187
188
189 void MathScriptInset::metrics(MathInset const * nuc,
190         MathMetricsInfo const & st) const
191 {       
192         MathNestInset::metrics(st);
193         if (nuc)
194                 nuc->metrics(st);
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         if (nuc)
215                 nuc->draw(pain, x + dxx(nuc), y);
216         else
217                 drawStr(pain, LM_TC_TEX, LM_ST_TEXT, x + dxx(nuc), y, ".");
218         if (hasUp())
219                 up().draw(pain, x + dx1(nuc), y - dy1(nuc));
220         if (hasDown())
221                 down().draw(pain, x + dx0(nuc), y + dy0(nuc));
222 }
223
224
225 void MathScriptInset::write(MathWriteInfo & os) const
226 {  
227         //lyxerr << "unexpected call to MathScriptInset::write()\n";
228         write(0, os);
229 }
230
231
232 void MathScriptInset::write(MathInset const * nuc, MathWriteInfo & os) const
233 {
234         if (nuc) {
235                 nuc->write(os);
236                 if (nuc->takesLimits()) {
237                         if (limits_ == -1)
238                                 os << "\\nolimits ";
239                         if (limits_ == 1)
240                                 os << "\\limits ";
241                 }
242         }
243         else
244                 os << "{}";
245
246         if (hasDown() && down().data_.size())
247                 os << "_{" << down().data_ << '}';
248
249         if (hasUp() && up().data_.size())
250                 os << "^{" << up().data_ << '}';
251 }
252
253
254 bool MathScriptInset::hasLimits(MathInset const * nuc) const
255 {
256         return limits_ == 1 || (limits_ == 0 && nuc && nuc->isScriptable());
257 }
258
259
260 void MathScriptInset::removeEmptyScripts()
261 {
262         for (int i = 0; i <= 1; ++i)
263                 if (script_[i] && !cell(i).size())
264                         script_[i] = false;
265 }
266
267
268 void MathScriptInset::removeScript(bool up)
269 {
270         cell(up).clear();
271         script_[up] = false;
272 }
273
274
275 bool MathScriptInset::has(bool up) const
276 {
277         return script_[up];
278 }
279
280
281 bool MathScriptInset::hasUp() const
282 {
283         return script_[1];
284 }
285
286
287 bool MathScriptInset::hasDown() const
288 {
289         return script_[0];
290 }
291
292
293 bool MathScriptInset::idxRight(MathInset::idx_type &,
294                                  MathInset::pos_type &) const
295 {
296         return false;
297 }
298
299
300 bool MathScriptInset::idxLeft(MathInset::idx_type &,
301                                 MathInset::pos_type &) const
302 {
303         return false;
304 }
305
306