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