]> git.lyx.org Git - lyx.git/blob - src/mathed/math_scriptinset.C
everything is an inset. sizeof(MathInset) == 36 on IA32
[lyx.git] / src / mathed / math_scriptinset.C
1 #ifdef __GNUG__
2 #pragma implementation
3 #endif
4
5 #include "math_scriptinset.h"
6 #include "support/LOstream.h"
7
8
9 MathScriptInset::MathScriptInset()
10         : MathNestInset(2), up_(false), down_(false), limits_(0), symbol_(0)
11 {}
12
13
14 MathScriptInset::MathScriptInset(bool up, bool down, MathInset * symbol)
15         : MathNestInset(2), up_(up), down_(down), limits_(0), symbol_(symbol)
16 {}
17
18
19 MathScriptInset::MathScriptInset(MathScriptInset const & p)
20         : MathNestInset(p), up_(p.up_), down_(p.down_),
21                 limits_(p.limits_), symbol_(p.symbol_ ? p.symbol_->clone() : 0)
22 {}
23
24
25 MathScriptInset::~MathScriptInset()
26 {
27         delete symbol_;
28 }
29
30
31 MathInset * MathScriptInset::clone() const
32 {   
33         return new MathScriptInset(*this);
34 }
35
36
37 bool MathScriptInset::up() const
38 {
39         return up_;
40 }
41
42
43 bool MathScriptInset::down() const
44 {
45         return down_;
46 }
47
48
49 void MathScriptInset::up(bool b)
50 {
51         up_ = b;
52 }
53
54
55 void MathScriptInset::down(bool b)
56 {
57         down_ = b;
58 }
59
60
61 bool MathScriptInset::idxRight(int &, int &) const
62 {
63         return false;
64 }
65
66
67 bool MathScriptInset::idxLeft(int &, int &) const
68 {
69         return false;
70 }
71
72
73 bool MathScriptInset::idxUp(int & idx, int & pos) const
74 {
75         if (idx == 0 || !up()) 
76                 return false;
77         idx = 0;
78         pos = 0;
79         return true;
80 }
81
82 bool MathScriptInset::idxDown(int & idx, int & pos) const
83 {
84         if (idx == 1 || !down()) 
85                 return false;
86         idx = 1;
87         pos = 0;
88         return true;
89 }
90
91 bool MathScriptInset::idxFirst(int & idx, int & pos) const
92 {
93         idx = up() ? 0 : 1;
94         pos = 0;
95         return true;
96 }
97
98 bool MathScriptInset::idxLast(int & idx, int & pos) const
99 {
100         idx = down() ? 1 : 0;
101         pos = cell(idx).size();
102         return true;
103 }
104
105
106 bool MathScriptInset::idxFirstUp(int & idx, int & pos) const
107 {
108         if (!up()) 
109                 return false;
110         idx = 0;
111         pos = 0;
112         return true;
113 }
114
115
116 bool MathScriptInset::idxFirstDown(int & idx, int & pos) const
117 {
118         if (!down()) 
119                 return false;
120         idx = 1;
121         pos = 0;
122         return true;
123 }
124
125
126 bool MathScriptInset::idxLastUp(int & idx, int & pos) const
127 {
128         if (!up()) 
129                 return false;
130         idx = 0;
131         pos = cell(idx).size();
132         return true;
133 }
134
135
136 bool MathScriptInset::idxLastDown(int & idx, int & pos) const
137 {
138         if (!down()) 
139                 return false;
140         idx = 1;
141         pos = cell(idx).size();
142         return true;
143 }
144
145
146 void MathScriptInset::write(std::ostream & os, bool fragile) const
147 {
148         if (symbol_) {
149                 symbol_->write(os, fragile);
150                 if (limits())
151                         os << (limits() == 1 ? "\\limits" : "\\nolimits");
152         }
153         if (up()) {
154                 os << "^{";
155                 cell(0).write(os, fragile);
156                 os << "}";
157         }
158         if (down()) {
159                 os << "_{";
160                 cell(1).write(os, fragile);
161                 os << "}";
162         }
163         os << " ";
164 }
165
166
167 void MathScriptInset::idxDelete(int & idx, bool & popit, bool & deleteit)
168 {
169         if (idx == 0) 
170                 up(false);
171         else
172                 down(false);
173         popit = true;
174         deleteit = !(up() || down());
175 }
176
177
178 int MathScriptInset::limits() const
179 {  
180         return limits_;
181 }
182
183
184 void MathScriptInset::limits(int limits) 
185 {  
186         limits_ = limits;
187 }
188
189
190 bool MathScriptInset::hasLimits() const
191 {
192         return
193                 symbol_ && (limits_ == 1 || (limits_ == 0 && size() == LM_ST_DISPLAY));
194 }
195
196
197 void MathScriptInset::writeNormal(std::ostream & os) const
198 {
199         if (limits() && symbol_) 
200                 os << "[" << (limits() ? "limits" : "nolimits") << "]";
201         if (up()) {
202                 os << "[superscript ";
203                 cell(0).writeNormal(os);
204                 os << "] ";
205         }
206         if (down()) {
207                 os << "[subscript ";
208                 cell(1).writeNormal(os);
209                 os << "] ";
210         }
211 }
212
213
214 void MathScriptInset::metrics(MathStyles st)
215 {
216         size_ = st;
217         MathStyles tt = smallerStyleScript(st);
218         
219         xcell(0).metrics(tt);
220         xcell(1).metrics(tt);
221
222         width_   = std::max(xcell(0).width(), xcell(1).width());
223
224         if (hasLimits()) {
225                 symbol_->metrics(st);
226                 int wid  = symbol_->width();
227                 ascent_  = symbol_->ascent();
228                 descent_ = symbol_->descent();
229                 width_   = std::max(width_, wid);
230                 if (up()) {
231                         ascent_  += xcell(0).height() + 2;
232                         dy0_     = - (ascent_ - xcell(0).ascent());
233                 }
234                 if (down()) {
235                         descent_ += xcell(1).height() + 2;
236                         dy1_     = descent_ - xcell(1).descent();
237                 }
238                 dxx_   = (width_ - wid) / 2;
239                 dx0_   = (width_ - xcell(0).width()) / 2;
240                 dx1_   = (width_ - xcell(1).width()) / 2;
241         } else {
242                 int asc;
243                 int des;
244                 int wid = 0;
245                 mathed_char_height(LM_TC_VAR, st, 'I', asc, des);
246                 if (symbol_) {
247                         symbol_->metrics(st);
248                         wid  = symbol_->width();
249                         asc  = symbol_->ascent();
250                         des = symbol_->descent();
251                 }
252                 ascent_  = up()   ? xcell(0).height() + asc : 0;
253                 descent_ = down() ? xcell(1).height() + des : 0;
254                 width_  += wid;
255                 dy0_     = - asc - xcell(0).descent();
256                 dy1_     =   des + xcell(1).ascent();
257                 dx0_     = wid;
258                 dx1_     = wid;
259                 dxx_     = 0;
260         }
261 }
262
263
264 void MathScriptInset::draw(Painter & pain, int x, int y)
265 {  
266         xo(x);
267         yo(y);
268
269         if (symbol_)
270                 symbol_->draw(pain, x + dxx_, y);
271         if (up())
272                 xcell(0).draw(pain, x + dx0_, y + dy0_);
273         if (down())
274                 xcell(1).draw(pain, x + dx1_, y + dy1_);
275 }