]> git.lyx.org Git - lyx.git/blob - src/mathed/math_data.C
up/down tweaks
[lyx.git] / src / mathed / math_data.C
1 #include <config.h>
2
3 #ifdef __GNUG__
4 #pragma implementation
5 #endif
6
7 #include "math_data.h"
8 #include "math_inset.h"
9 #include "math_deliminset.h"
10 #include "math_charinset.h"
11 #include "math_scriptinset.h"
12 #include "math_stringinset.h"
13 #include "math_matrixinset.h"
14 #include "math_mathmlstream.h"
15 #include "math_support.h"
16 #include "math_replace.h"
17 #include "debug.h"
18 #include "support/LAssert.h"
19 #include "math_metricsinfo.h"
20 #include "frontends/Painter.h"
21 #include "textpainter.h"
22
23
24 using std::max;
25 using std::min;
26 using std::abs;
27
28
29
30 MathArray::MathArray()
31         : xo_(0), yo_(0), clean_(false), drawn_(false)
32 {}
33
34
35 MathArray::MathArray(const_iterator from, const_iterator to)
36         : base_type(from, to), xo_(0), yo_(0), clean_(false), drawn_(false)
37 {}
38
39
40 void MathArray::substitute(MathMacro const & m)
41 {
42         for (iterator it = begin(); it != end(); ++it)
43                 it->nucleus()->substitute(m);
44 }
45
46
47 MathAtom & MathArray::operator[](size_type pos)
48 {
49         lyx::Assert(pos < size());
50         return base_type::operator[](pos);
51 }
52
53
54 MathAtom const & MathArray::operator[](size_type pos) const
55 {
56         lyx::Assert(pos < size());
57         return base_type::operator[](pos);
58 }
59
60
61 void MathArray::insert(size_type pos, MathAtom const & t)
62 {
63         base_type::insert(begin() + pos, t);
64 }
65
66
67 void MathArray::insert(size_type pos, MathArray const & ar)
68 {
69         base_type::insert(begin() + pos, ar.begin(), ar.end());
70 }
71
72
73 void MathArray::append(MathArray const & ar)
74 {
75         insert(size(), ar);
76 }
77
78
79 void MathArray::erase(size_type pos)
80 {
81         if (pos < size())
82                 erase(pos, pos + 1);
83 }
84
85
86 void MathArray::erase(iterator pos1, iterator pos2)
87 {
88         base_type::erase(pos1, pos2);
89 }
90
91
92 void MathArray::erase(iterator pos)
93 {
94         base_type::erase(pos);
95 }
96
97
98 void MathArray::erase(size_type pos1, size_type pos2)
99 {
100         base_type::erase(begin() + pos1, begin() + pos2);
101 }
102
103
104 void MathArray::dump2() const
105 {
106         NormalStream ns(lyxerr);
107         for (const_iterator it = begin(); it != end(); ++it)
108                 ns << *it << ' ';
109 }
110
111
112 void MathArray::dump() const
113 {
114         NormalStream ns(lyxerr);
115         for (const_iterator it = begin(); it != end(); ++it)
116                 ns << "<" << *it << ">";
117 }
118
119
120 void MathArray::validate(LaTeXFeatures & features) const
121 {
122         for (const_iterator it = begin(); it != end(); ++it)
123                 (*it)->validate(features);
124 }
125
126
127 bool MathArray::match(MathArray const & ar) const
128 {
129         return size() == ar.size() && matchpart(ar, 0);
130 }
131
132
133 bool MathArray::matchpart(MathArray const & ar, pos_type pos) const
134 {
135         if (size() < ar.size() + pos)
136                 return false;
137         const_iterator it = begin() + pos;
138         for (const_iterator jt = ar.begin(); jt != ar.end(); ++jt, ++it)
139                 if (!(*jt)->match(it->nucleus()))
140                         return false;
141         return true;
142 }
143
144
145 void MathArray::replace(ReplaceData & rep)
146 {
147         for (size_type i = 0; i < size(); ++i) {
148                 if (find1(rep.from, i)) {
149                         // match found
150                         lyxerr << "match found!\n";
151                         erase(i, i + rep.from.size());
152                         insert(i, rep.to);
153                 }
154         }
155
156 #ifdef WITH_WARNINGS
157 #warning temporarily disabled
158         // for (const_iterator it = begin(); it != end(); ++it)
159         //      it->nucleus()->replace(rep);
160 #endif
161 }
162
163
164 bool MathArray::find1(MathArray const & ar, size_type pos) const
165 {
166         //lyxerr << "finding '" << ar << "' in '" << *this << "'\n";
167         for (size_type i = 0, n = ar.size(); i < n; ++i)
168                 if (!operator[](pos + i)->match(ar[i].nucleus()))
169                         return false;
170         return true;
171 }
172
173
174 MathArray::size_type MathArray::find(MathArray const & ar) const
175 {
176         for (int i = 0, last = size() - ar.size(); i < last; ++i)
177                 if (find1(ar, i))
178                         return i;
179         return size();
180 }
181
182
183 MathArray::size_type MathArray::find_last(MathArray const & ar) const
184 {
185         for (int i = size() - ar.size(); i >= 0; --i) 
186                 if (find1(ar, i))
187                         return i;
188         return size();
189 }
190
191
192 bool MathArray::contains(MathArray const & ar) const
193 {
194         if (find(ar) != size())
195                 return true;
196         for (const_iterator it = begin(); it != end(); ++it)
197                 if (it->nucleus()->contains(ar))
198                         return true;
199         return false;
200 }
201
202
203 void MathArray::touch() const
204 {
205         clean_  = false;
206         drawn_  = false;
207 }
208
209
210 Dimension const & MathArray::metrics(MathMetricsInfo & mi) const
211 {
212         //if (clean_)
213         //      return;
214         clean_  = true;
215         drawn_  = false;
216
217         if (empty()) {
218                 mathed_char_dim(mi.base.font, 'I', dim_);
219                 return dim_;
220         }
221
222         dim_.clear();
223         for (const_iterator it = begin(), et = end(); it != et; ++it) {
224                 (*it)->metrics(mi);
225                 dim_ += (*it)->dimensions();
226         }
227         return dim_;
228 }
229
230
231 void MathArray::draw(MathPainterInfo & pi, int x, int y) const
232 {
233         //if (drawn_ && x == xo_ && y == yo_)
234         //      return;
235         //lyxerr << "MathArray::draw: x: " << x << " y: " << y << endl;
236
237         xo_    = x;
238         yo_    = y;
239         drawn_ = true;
240
241         if (y + descent() <= 0)                   // don't draw above the workarea
242                 return;
243         if (y - ascent() >= pi.pain.paperHeight())   // don't draw below the workarea
244                 return;
245         if (x + width() <= 0)                     // don't draw left of workarea
246                 return;
247         if (x >= pi.pain.paperWidth())              // don't draw right of workarea
248                 return;
249
250         if (empty()) {
251                 pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
252                 return;
253         }
254
255         for (const_iterator it = begin(), et = end(); it != et; ++it) {
256                 (*it)->draw(pi, x, y);
257                 x += (*it)->width();
258         }
259 }
260
261
262 Dimension const & MathArray::metricsT(TextMetricsInfo const & mi) const
263 {
264         //if (clean_)
265         //      return;
266         dim_.clear();
267         for (const_iterator it = begin(); it != end(); ++it) {
268                 (*it)->metricsT(mi);
269                 dim_ += (*it)->dimensions();
270         }
271         return dim_;
272 }
273
274
275 void MathArray::drawT(TextPainter & pain, int x, int y) const
276 {
277         //if (drawn_ && x == xo_ && y == yo_)
278         //      return;
279         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
280         xo_    = x;
281         yo_    = y;
282         drawn_ = true;
283
284         for (const_iterator it = begin(), et = end(); it != et; ++it) {
285                 (*it)->drawT(pain, x, y);
286                 x += (*it)->width();
287         }
288 }
289
290
291 int MathArray::pos2x(size_type pos) const
292 {
293         return pos2x(0, pos, 0);
294 }
295
296
297 int MathArray::pos2x(size_type pos1, size_type pos2, int glue) const
298 {
299         int x = 0;
300         size_type target = min(pos2, size());
301         for (size_type i = pos1; i < target; ++i) {
302                 const_iterator it = begin() + i;
303                 MathInset const * p = it->nucleus();
304                 if (p->getChar() == ' ')
305                         x += glue;
306                 x += p->width();
307         }
308         return x;
309 }
310
311
312 MathArray::size_type MathArray::x2pos(int targetx) const
313 {
314         return x2pos(0, targetx, 0);
315 }
316
317
318 MathArray::size_type MathArray::x2pos(size_type startpos, int targetx,
319         int glue) const
320 {
321         const_iterator it = begin() + startpos;
322         int lastx = 0;
323         int currx = 0;
324         for (; currx < targetx && it < end(); ++it) {
325                 lastx = currx;
326                 MathInset const * p = it->nucleus();
327                 if (p->getChar() == ' ')
328                         currx += glue;
329                 currx += p->width();
330         }
331         if (abs(lastx - targetx) < abs(currx - targetx) && it != begin() + startpos)
332                 --it;
333         return it - begin();
334 }
335
336
337 int MathArray::dist(int x, int y) const
338 {
339         int xx = 0;
340         int yy = 0;
341
342         if (x < xo_)
343                 xx = xo_ - x;
344         else if (x > xo_ + width())
345                 xx = x - xo_ - width();
346
347         if (y < yo_ - ascent())
348                 yy = yo_ - ascent() - y;
349         else if (y > yo_ + descent())
350                 yy = y - yo_ - descent();
351
352         return xx + yy;
353 }
354
355
356 void MathArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
357 {
358         x1 = xo_;
359         x2 = xo_ + width();
360         y1 = yo_ - ascent();
361         y2 = yo_ + descent();
362 }
363
364 void MathArray::center(int & x, int & y) const
365 {
366         x = xo_ + width() / 2;
367         y = yo_ + (descent() - ascent()) / 2;
368 }
369
370
371 void MathArray::towards(int & x, int & y) const
372 {
373         int cx = 0;
374         int cy = 0;
375         center(cx, cy);
376
377         double r = 1.0;
378         //int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
379
380         x = cx + int(r * (x - cx));
381         y = cy + int(r * (y - cy));
382 }
383
384
385 void MathArray::setXY(int x, int y)
386 {
387         xo_ = x;
388         yo_ = y;
389 }
390