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