]> git.lyx.org Git - lyx.git/blob - src/mathed/math_data.C
merge MathArray and MathXArray classes.
[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->nucleus() << ' ';
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->nucleus() << ">";
117 }
118
119
120 void MathArray::validate(LaTeXFeatures & features) const
121 {
122         for (const_iterator it = begin(); it != end(); ++it)
123                 if (it->nucleus())
124                         it->nucleus()->validate(features);
125 }
126
127
128 bool MathArray::match(MathArray const & ar) const
129 {
130         return size() == ar.size() && matchpart(ar, 0);
131 }
132
133
134 bool MathArray::matchpart(MathArray const & ar, pos_type pos) const
135 {
136         if (size() < ar.size() + pos)
137                 return false;
138         const_iterator it = begin() + pos;
139         for (const_iterator jt = ar.begin(); jt != ar.end(); ++jt, ++it)
140                 if (!jt->nucleus()->match(it->nucleus()))
141                         return false;
142         return true;
143 }
144
145
146 void MathArray::replace(ReplaceData & rep)
147 {
148         for (size_type i = 0; i < size(); ++i) {
149                 if (find1(rep.from, i)) {
150                         // match found
151                         lyxerr << "match found!\n";
152                         erase(i, i + rep.from.size());
153                         insert(i, rep.to);
154                 }
155         }
156
157         for (const_iterator it = begin(); it != end(); ++it)
158                 it->nucleus()->replace(rep);
159 }
160
161
162 bool MathArray::find1(MathArray const & ar, size_type pos) const
163 {
164         //lyxerr << "finding '" << ar << "' in '" << *this << "'\n";
165         for (size_type i = 0, n = ar.size(); i < n; ++i)
166                 if (!operator[](pos + i)->match(ar[i].nucleus()))
167                         return false;
168         return true;
169 }
170
171
172 MathArray::size_type MathArray::find(MathArray const & ar) const
173 {
174         for (int i = 0, last = size() - ar.size(); i < last; ++i)
175                 if (find1(ar, i))
176                         return i;
177         return size();
178 }
179
180
181 MathArray::size_type MathArray::find_last(MathArray const & ar) const
182 {
183         for (int i = size() - ar.size(); i >= 0; --i) 
184                 if (find1(ar, i))
185                         return i;
186         return size();
187 }
188
189
190 bool MathArray::contains(MathArray const & ar) const
191 {
192         if (find(ar) != size())
193                 return true;
194         for (const_iterator it = begin(); it != end(); ++it)
195                 if (it->nucleus()->contains(ar))
196                         return true;
197         return false;
198 }
199
200
201 void MathArray::touch() const
202 {
203         clean_  = false;
204         drawn_  = false;
205 }
206
207
208 Dimension const & MathArray::metrics(MathMetricsInfo & mi) const
209 {
210         //if (clean_)
211         //      return;
212         clean_  = true;
213         drawn_  = false;
214
215         if (empty()) {
216                 mathed_char_dim(mi.base.font, 'I', dim_);
217                 return dim_;
218         }
219
220         dim_.clear();
221         for (const_iterator it = begin(), et = end(); it != et; ++it) {
222                 (*it)->metrics(mi);
223                 dim_ += (*it)->dimensions();
224         }
225         return dim_;
226 }
227
228
229 void MathArray::draw(MathPainterInfo & pi, int x, int y) const
230 {
231         //if (drawn_ && x == xo_ && y == yo_)
232         //      return;
233         //lyxerr << "MathArray::draw: x: " << x << " y: " << y << endl;
234
235         xo_    = x;
236         yo_    = y;
237         drawn_ = true;
238
239         if (y + descent() <= 0)                   // don't draw above the workarea
240                 return;
241         if (y - ascent() >= pi.pain.paperHeight())   // don't draw below the workarea
242                 return;
243         if (x + width() <= 0)                     // don't draw left of workarea
244                 return;
245         if (x >= pi.pain.paperWidth())              // don't draw right of workarea
246                 return;
247
248         if (empty()) {
249                 pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
250                 return;
251         }
252
253         for (const_iterator it = begin(), et = end(); it != et; ++it) {
254                 (*it)->draw(pi, x, y);
255                 x += (*it)->width();
256         }
257 }
258
259
260 Dimension const & MathArray::metricsT(TextMetricsInfo const & mi) const
261 {
262         //if (clean_)
263         //      return;
264         dim_.clear();
265         for (const_iterator it = begin(); it != end(); ++it) {
266                 (*it)->metricsT(mi);
267                 dim_ += (*it)->dimensions();
268         }
269         return dim_;
270 }
271
272
273 void MathArray::drawT(TextPainter & pain, int x, int y) const
274 {
275         //if (drawn_ && x == xo_ && y == yo_)
276         //      return;
277         //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
278         xo_    = x;
279         yo_    = y;
280         drawn_ = true;
281
282         for (const_iterator it = begin(), et = end(); it != et; ++it) {
283                 (*it)->drawT(pain, x, y);
284                 x += (*it)->width();
285         }
286 }
287
288
289 int MathArray::pos2x(size_type pos) const
290 {
291         return pos2x(0, pos, 0);
292 }
293
294
295 int MathArray::pos2x(size_type pos1, size_type pos2, int glue) const
296 {
297         int x = 0;
298         size_type target = min(pos2, size());
299         for (size_type i = pos1; i < target; ++i) {
300                 const_iterator it = begin() + i;
301                 MathInset const * p = it->nucleus();
302                 if (p->getChar() == ' ')
303                         x += glue;
304                 x += p->width();
305         }
306         return x;
307 }
308
309
310 MathArray::size_type MathArray::x2pos(int targetx) const
311 {
312         return x2pos(0, targetx, 0);
313 }
314
315
316 MathArray::size_type MathArray::x2pos(size_type startpos, int targetx,
317         int glue) const
318 {
319         const_iterator it = begin() + startpos;
320         int lastx = 0;
321         int currx = 0;
322         for (; currx < targetx && it < end(); ++it) {
323                 lastx = currx;
324                 MathInset const * p = it->nucleus();
325                 if (p->getChar() == ' ')
326                         currx += glue;
327                 currx += p->width();
328         }
329         if (abs(lastx - targetx) < abs(currx - targetx) && it != begin() + startpos)
330                 --it;
331         return it - begin();
332 }
333
334
335 int MathArray::dist(int x, int y) const
336 {
337         int xx = 0;
338         int yy = 0;
339
340         if (x < xo_)
341                 xx = xo_ - x;
342         else if (x > xo_ + width())
343                 xx = x - xo_ - width();
344
345         if (y < yo_ - ascent())
346                 yy = yo_ - ascent() - y;
347         else if (y > yo_ + descent())
348                 yy = y - yo_ - descent();
349
350         return xx + yy;
351 }
352
353
354 void MathArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
355 {
356         x1 = xo_;
357         x2 = xo_ + width();
358         y1 = yo_ - ascent();
359         y2 = yo_ + descent();
360 }
361
362 void MathArray::center(int & x, int & y) const
363 {
364         x = xo_ + width() / 2;
365         y = yo_ + (descent() - ascent()) / 2;
366 }
367
368
369 void MathArray::towards(int & x, int & y) const
370 {
371         int cx = 0;
372         int cy = 0;
373         center(cx, cy);
374
375         double r = 1.0;
376         //int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
377
378         x = cx + int(r * (x - cx));
379         y = cy + int(r * (y - cy));
380 }
381
382
383 /*
384 std::ostream & operator<<(std::ostream & os, MathArray const & ar)
385 {
386         os << ar.data();
387 }
388 */
389