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