]> git.lyx.org Git - lyx.git/blob - src/mathed/math_atom.C
fix cursor positioning using the mouse
[lyx.git] / src / mathed / math_atom.C
1 /*
2  *  File:        math_inset.C
3  *  Purpose:     Implementation of insets for mathed
4  *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx> 
5  *  Created:     January 1996
6  *  Description: 
7  *
8  *  Dependencies: Xlib, XForms
9  *
10  *  Copyright: 1996, 1997 Alejandro Aguilar Sierra
11  *
12  *   Version: 0.8beta.
13  *
14  *   You are free to use and modify this code under the terms of
15  *   the GNU General Public Licence version 2 or later.
16  */
17
18 #ifdef __GNUG__
19 #pragma implementation
20 #endif
21
22 #include "math_atom.h"
23 #include "math_scriptinset.h"
24 #include "debug.h"
25 #include "support.h"
26 #include "support/LAssert.h"
27
28
29 MathAtom::MathAtom()
30         : nucleus_(0), limits_(0), xo_(0), yo_(0)
31 {
32         script_[0] = 0;
33         script_[1] = 0;
34 }
35
36
37 MathAtom::MathAtom(MathInset * p)
38         : nucleus_(p), limits_(0), xo_(0), yo_(0)
39 {
40         script_[0] = 0;
41         script_[1] = 0;
42 }
43
44
45
46 MathAtom::MathAtom(MathAtom const & p)
47 {
48         copy(p);
49 }
50
51
52 void MathAtom::operator=(MathAtom const & p)
53 {
54         if (this != &p) {
55                 done();
56                 copy(p);
57         }
58 }
59
60
61 MathAtom::~MathAtom()
62 {
63         done();
64 }
65
66
67 void MathAtom::done()
68 {
69         delete nucleus_;
70         delete script_[0];
71         delete script_[1];
72 }
73
74
75 void MathAtom::copy(MathAtom const & p)
76 {
77         //cerr << "calling MathAtom::copy\n";
78         xo_        = p.xo_;
79         yo_        = p.yo_;
80         limits_    = p.limits_;
81         nucleus_   = p.nucleus_;
82         script_[0] = p.script_[0];
83         script_[1] = p.script_[1];
84         if (nucleus_)
85                 nucleus_ = nucleus_->clone();
86         if (script_[0])
87                 script_[0]  = new MathScriptInset(*script_[0]);
88         if (script_[1])
89                 script_[1]  = new MathScriptInset(*script_[1]);
90 }
91
92
93 int MathAtom::height() const
94 {
95         return ascent() + descent();
96 }
97
98
99 std::ostream & operator<<(std::ostream & os, MathAtom const & atom)
100 {
101         atom.write(os, false);
102         return os;
103 }
104
105
106 int MathAtom::xo() const
107 {
108         return xo_;
109 }
110
111
112 int MathAtom::yo() const
113 {
114         return yo_;
115 }
116
117
118 void MathAtom::xo(int x) const
119 {
120         xo_ = x;
121 }
122
123
124 void MathAtom::yo(int y) const
125 {
126         yo_ = y;
127 }
128
129
130 void MathAtom::getXY(int & x, int & y) const
131 {
132    x = xo();
133    y = yo();
134 }
135
136
137 /*
138 void MathAtom::userSetSize(MathStyles sz)
139 {
140         if (sz >= 0) {
141                 size_ = sz;      
142                 flag = flag & ~LMPF_FIXED_SIZE;
143         }
144 }
145 */
146
147 void MathAtom::writeNormal(std::ostream & os) const
148 {
149         os << "[unknown] ";
150 }
151
152
153 void MathAtom::dump() const
154 {
155         lyxerr << "---------------------------------------------\n";
156         write(lyxerr, false);
157         lyxerr << "\n---------------------------------------------\n";
158 }
159
160
161 bool MathAtom::covers(int x, int y) const
162 {
163         return
164                 x >= xo_ &&
165                 x <= xo_ + width() &&
166                 y >= yo_ - ascent() &&
167                 y <= yo_ + descent();
168 }
169
170
171 MathScriptInset * MathAtom::ensure(bool up)
172 {
173         if (!script_[up])
174                 script_[up] = new MathScriptInset(up);
175         return script_[up];
176 }
177
178
179 void MathAtom::validate(LaTeXFeatures &) const
180 {}
181
182
183 void MathAtom::metrics(MathStyles st) const
184 {
185         MathStyles tt = smallerStyleScript(st);
186         if (nucleus())
187                 nucleus()->metrics(st);
188         if (up())
189                 up()->metrics(tt);
190         if (down())
191                 down()->metrics(tt);
192 }
193
194
195 MathScriptInset * MathAtom::up() const
196 {
197         return script_[1];
198 }
199
200
201 MathScriptInset * MathAtom::down() const
202 {
203         return script_[0];
204 }
205
206
207 int MathAtom::dy0() const
208 {
209         lyx::Assert(down());
210         int des = down()->ascent();
211         if (hasLimits())
212                 des += ndes() + 2;
213         else 
214                 des = std::max(des, ndes());
215         return des;
216 }
217
218
219 int MathAtom::dy1() const
220 {
221         lyx::Assert(up());
222         int asc = up()->descent();
223         if (hasLimits())
224                 asc += nasc() + 2;
225         else 
226                 asc = std::max(asc, nasc());
227         asc = std::max(asc, mathed_char_ascent(LM_TC_VAR, LM_ST_TEXT, 'I'));
228         return asc;
229 }
230
231
232 int MathAtom::dx0() const
233 {
234         lyx::Assert(down());
235         return hasLimits() ? (width() - down()->width()) / 2 : nwid();
236 }
237
238
239 int MathAtom::dx1() const
240 {
241         lyx::Assert(up());
242         return hasLimits() ? (width() - up()->width()) / 2 : nwid();
243 }
244
245
246 int MathAtom::dxx() const
247 {
248         lyx::Assert(nucleus());
249         return hasLimits() ? (width() - nwid()) / 2 : 0;
250 }
251
252
253 int MathAtom::ascent() const
254 {
255         int asc = nasc();
256         if (up()) 
257                 asc += hasLimits() ? up()->height() + 2 : up()->ascent();
258         return asc;
259 }
260
261
262 int MathAtom::descent() const
263 {
264         int des = ndes();
265         if (down()) 
266                 des += hasLimits() ? down()->height() + 2 : down()->descent();
267         return des;
268 }
269
270
271 int MathAtom::width() const
272 {
273         int wid = 0;
274         if (hasLimits()) {
275                 wid = nwid();
276                 if (up())
277                         wid = std::max(wid, up()->width());
278                 if (down())
279                         wid = std::max(wid, down()->width());
280         } else {
281                 if (up())
282                         wid = std::max(wid, up()->width());
283                 if (down())
284                         wid = std::max(wid, down()->width());
285                 wid += nwid();
286         }
287         return wid;
288 }
289
290
291 int MathAtom::nwid() const
292 {
293         return nucleus() ? nucleus()->width() : 0;
294 }
295
296
297 int MathAtom::nasc() const
298 {
299         return nucleus() ? nucleus()->ascent()
300                 : mathed_char_ascent(LM_TC_VAR, LM_ST_TEXT, 'I');
301 }
302
303
304 int MathAtom::ndes() const
305 {
306         return nucleus() ? nucleus()->descent()
307                 : mathed_char_descent(LM_TC_VAR, LM_ST_TEXT, 'I');
308 }
309
310
311 void MathAtom::draw(Painter & pain, int x, int y) const
312 {  
313         xo(x);
314         yo(y);
315         if (nucleus())
316                 nucleus()->draw(pain, x + dxx(), y);
317         if (up())
318                 up()->draw(pain, x + dx1(), y - dy1());
319         if (down())
320                 down()->draw(pain, x + dx0(), y + dy0());
321 }
322
323
324 void MathAtom::write(std::ostream & os, bool fragile) const
325 {
326         if (nucleus()) {
327                 nucleus()->write(os, fragile);
328                 if (nucleus()->takesLimits()) {
329                         if (limits_ == -1)
330                                 os << "\\nolimits ";
331                         if (limits_ == 1)
332                                 os << "\\limits ";
333                 }
334         } else
335                 os << "{}";
336
337         if (up()) {
338                 os << "^{";
339                 up()->write(os, fragile);
340                 os << "}";
341         }
342
343         if (down()) {
344                 os << "_{";
345                 down()->write(os, fragile);
346                 os << "}";
347         }
348 }
349
350
351 bool MathAtom::hasLimits() const
352 {
353         return
354                 limits_ == 1 || (limits_ == 0 && nucleus() && nucleus()->isScriptable());
355 }
356
357
358 void MathAtom::substitute(MathArray & array, MathMacro const & m) const
359 {
360         if (nucleus())
361                 nucleus()->substitute(array, m);
362         if (up())
363                 up()->substitute(array, m);
364         if (down())
365                 down()->substitute(array, m);
366 }
367
368
369 void MathAtom::removeEmptyScripts()
370 {
371         for (int i = 0; i <= 1; ++i)
372                 if (script_[i] && !script_[i]->cell(0).size()) {
373                         delete script_[i];
374                         script_[i] = 0;
375                 }
376 }