-#include <config.h>
+/**
+ * \file math_data.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author André Pönitz
+ *
+ * Full author contact details are available in file CREDITS.
+ */
-#ifdef __GNUG__
-#pragma implementation
-#endif
+#include <config.h>
#include "math_data.h"
-#include "math_inset.h"
-#include "math_cursor.h"
-#include "math_deliminset.h"
#include "math_fontinset.h"
#include "math_scriptinset.h"
+#include "math_macro.h"
+#include "math_macrotable.h"
#include "math_mathmlstream.h"
#include "math_support.h"
#include "math_replace.h"
+
+#include "coordcache.h"
+#include "LColor.h"
+#include "BufferView.h"
+#include "buffer.h"
+#include "cursor.h"
#include "debug.h"
-#include "support/LAssert.h"
-#include "math_metricsinfo.h"
+
#include "frontends/Painter.h"
-#include "textpainter.h"
+#include <boost/assert.hpp>
-using std::max;
-using std::min;
using std::abs;
-
+using std::endl;
+using std::min;
+using std::ostringstream;
+using std::string;
+using std::vector;
MathArray::MathArray()
- : xo_(0), yo_(0), clean_(false), drawn_(false)
{}
MathArray::MathArray(const_iterator from, const_iterator to)
- : base_type(from, to), xo_(0), yo_(0), clean_(false), drawn_(false)
+ : base_type(from, to)
{}
-void MathArray::substitute(MathMacro const & m)
+MathAtom & MathArray::operator[](pos_type pos)
{
- for (iterator it = begin(); it != end(); ++it)
- it->nucleus()->substitute(m);
-}
-
-
-MathAtom & MathArray::operator[](size_type pos)
-{
- lyx::Assert(pos < size());
+ BOOST_ASSERT(pos < size());
return base_type::operator[](pos);
}
-MathAtom const & MathArray::operator[](size_type pos) const
+MathAtom const & MathArray::operator[](pos_type pos) const
{
- lyx::Assert(pos < size());
+ BOOST_ASSERT(pos < size());
return base_type::operator[](pos);
}
void MathArray::insert(size_type pos, MathArray const & ar)
{
- lyx::Assert(pos <= size());
+ BOOST_ASSERT(pos <= size());
base_type::insert(begin() + pos, ar.begin(), ar.end());
}
{
NormalStream ns(lyxerr);
for (const_iterator it = begin(); it != end(); ++it)
- ns << "<" << *it << ">";
+ ns << '<' << *it << '>';
}
return false;
const_iterator it = begin() + pos;
for (const_iterator jt = ar.begin(); jt != ar.end(); ++jt, ++it)
- if (!(*jt)->match(*it))
+ if (asString(*it) != asString(*jt))
return false;
return true;
}
for (size_type i = 0; i < size(); ++i) {
if (find1(rep.from, i)) {
// match found
- lyxerr << "match found!\n";
+ lyxerr << "match found!" << endl;
erase(i, i + rep.from.size());
insert(i, rep.to);
}
bool MathArray::find1(MathArray const & ar, size_type pos) const
{
- //lyxerr << "finding '" << ar << "' in '" << *this << "'\n";
+ lyxerr << "finding '" << ar << "' in '" << *this << "'" << endl;
for (size_type i = 0, n = ar.size(); i < n; ++i)
- if (!operator[](pos + i)->match(ar[i]))
+ if (asString(operator[](pos + i)) != asString(ar[i]))
return false;
return true;
}
void MathArray::touch() const
{
- clean_ = false;
- drawn_ = false;
}
-Dimension const & MathArray::metrics(MathMetricsInfo & mi) const
+void MathArray::metrics(MetricsInfo & mi, Dimension & dim) const
{
- //if (clean_)
- // return;
- clean_ = true;
- drawn_ = false;
+ metrics(mi);
+ dim = dim_;
+}
+
+namespace {
+
+bool isInside(DocIterator const & it, MathArray const & ar,
+ lyx::pos_type p1, lyx::pos_type p2)
+{
+ for (size_t i = 0; i != it.size(); ++i) {
+ CursorSlice const & sl = it[i];
+ if (sl.inset().inMathed() && &sl.cell() == &ar)
+ return p1 <= sl.pos() && sl.pos() < p2;
+ }
+ return false;
+}
+
+}
+
+
+
+void MathArray::metrics(MetricsInfo & mi) const
+{
mathed_char_dim(mi.base.font, 'I', dim_);
+
if (empty())
- return dim_;
+ return;
- dim_.w = 0;
- for (const_iterator it = begin(), et = end(); it != et; ++it) {
- (*it)->metrics(mi);
- dim_ += (*it)->dimensions();
+ dim_.wid = 0;
+ Dimension d;
+ //BufferView & bv = *mi.base.bv;
+ //Buffer const & buf = *bv.buffer();
+ for (size_t i = 0, n = size(); i != n; ++i) {
+ MathAtom const & at = operator[](i);
+#if 0
+ MathMacro const * mac = at->asMacro();
+ if (mac && buf.hasMacro(mac->name())) {
+ MacroData const & tmpl = buf.getMacro(mac->name());
+ int numargs = tmpl.numargs();
+ if (i + numargs > n)
+ numargs = n - i - 1;
+ lyxerr << "metrics:found macro: " << mac->name()
+ << " numargs: " << numargs << endl;
+ if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
+ MathArray args(begin() + i + 1, begin() + i + numargs + 1);
+ MathArray exp;
+ tmpl.expand(args, exp);
+ mac->setExpansion(exp, args);
+ mac->metricsExpanded(mi, d);
+ dim_.wid += mac->widthExpanded();
+ i += numargs;
+ continue;
+ }
+ }
+#endif
+ at->metrics(mi, d);
+ dim_ += d;
}
- return dim_;
}
-void MathArray::draw(MathPainterInfo & pi, int x, int y) const
+void MathArray::draw(PainterInfo & pi, int x, int y) const
{
- //if (drawn_ && x == xo_ && y == yo_)
- // return;
//lyxerr << "MathArray::draw: x: " << x << " y: " << y << endl;
-
- xo_ = x;
- yo_ = y;
- drawn_ = true;
-
- if (y + descent() <= 0) // don't draw above the workarea
- return;
- if (y - ascent() >= pi.pain.paperHeight()) // don't draw below the workarea
- return;
- if (x + width() <= 0) // don't draw left of workarea
- return;
- if (x >= pi.pain.paperWidth()) // don't draw right of workarea
- return;
+ setXY(x, y);
if (empty()) {
pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
return;
}
- for (const_iterator it = begin(), et = end(); it != et; ++it) {
- (*it)->draw(pi, x, y);
- x += (*it)->width();
+ // don't draw outside the workarea
+ if (y + descent() <= 0
+ || y - ascent() >= pi.pain.paperHeight()
+ || x + width() <= 0
+ || x >= pi.pain.paperWidth())
+ return;
+
+ //BufferView & bv = *pi.base.bv;
+ for (size_t i = 0, n = size(); i != n; ++i) {
+ MathAtom const & at = operator[](i);
+#if 0
+ Buffer const & buf = *bv.buffer();
+ // special macro handling
+ MathMacro const * mac = at->asMacro();
+ if (mac && buf.hasMacro(mac->name())) {
+ MacroData const & tmpl = buf.getMacro(mac->name());
+ int numargs = tmpl.numargs();
+ if (i + numargs > n)
+ numargs = n - i - 1;
+ if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
+ mac->drawExpanded(pi, x, y);
+ x += mac->widthExpanded();
+ i += numargs;
+ continue;
+ }
+ }
+#endif
+ at->drawSelection(pi, x, y);
+ at->draw(pi, x, y);
+ x += at->width();
}
}
-Dimension const & MathArray::metricsT(TextMetricsInfo const & mi) const
+void MathArray::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
{
- //if (clean_)
- // return;
- dim_.clear();
+ dim.clear();
+ Dimension d;
for (const_iterator it = begin(); it != end(); ++it) {
- (*it)->metricsT(mi);
- dim_ += (*it)->dimensions();
+ (*it)->metricsT(mi, d);
+ dim += d;
}
- return dim_;
}
void MathArray::drawT(TextPainter & pain, int x, int y) const
{
- //if (drawn_ && x == xo_ && y == yo_)
- // return;
- //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
- xo_ = x;
- yo_ = y;
- drawn_ = true;
+ //lyxerr << "x: " << x << " y: " << y << ' ' << pain.workAreaHeight() << endl;
+ setXY(x, y);
for (const_iterator it = begin(), et = end(); it != et; ++it) {
(*it)->drawT(pain, x, y);
- x += (*it)->width();
+ //x += (*it)->width_;
+ x += 2;
}
}
int MathArray::pos2x(size_type pos) const
{
- return pos2x(0, pos, 0);
+ return pos2x(pos, 0);
}
-int MathArray::pos2x(size_type pos1, size_type pos2, int glue) const
+int MathArray::pos2x(size_type pos, int glue) const
{
int x = 0;
- size_type target = min(pos2, size());
- for (size_type i = pos1; i < target; ++i) {
+ size_type target = min(pos, size());
+ for (size_type i = 0; i < target; ++i) {
const_iterator it = begin() + i;
if ((*it)->getChar() == ' ')
x += glue;
+ //lyxerr << "char: " << (*it)->getChar()
+ // << "width: " << (*it)->width() << std::endl;
x += (*it)->width();
}
return x;
MathArray::size_type MathArray::x2pos(int targetx) const
{
- return x2pos(0, targetx, 0);
+ return x2pos(targetx, 0);
}
-MathArray::size_type MathArray::x2pos(size_type startpos, int targetx,
- int glue) const
+MathArray::size_type MathArray::x2pos(int targetx, int glue) const
{
- const_iterator it = begin() + startpos;
+ const_iterator it = begin();
int lastx = 0;
int currx = 0;
for (; currx < targetx && it < end(); ++it) {
currx += glue;
currx += (*it)->width();
}
- if (abs(lastx - targetx) < abs(currx - targetx) && it != begin() + startpos)
+ if (abs(lastx - targetx) < abs(currx - targetx) && it != begin())
--it;
return it - begin();
}
int xx = 0;
int yy = 0;
+ const int xo_ = xo();
+ const int yo_ = yo();
+
if (x < xo_)
xx = xo_ - x;
else if (x > xo_ + width())
}
-void MathArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
-{
- x1 = xo_;
- x2 = xo_ + width();
- y1 = yo_ - ascent();
- y2 = yo_ + descent();
-}
-
-void MathArray::center(int & x, int & y) const
+void MathArray::setXY(int x, int y) const
{
- x = xo_ + width() / 2;
- y = yo_ + (descent() - ascent()) / 2;
+ //lyxerr << "setting position cache for MathArray " << this << std::endl;
+ theCoords.arrays_.add(this, x, y);
}
-void MathArray::towards(int & x, int & y) const
+int MathArray::xo() const
{
- int cx = 0;
- int cy = 0;
- center(cx, cy);
-
- double r = 1.0;
- //int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
-
- x = cx + int(r * (x - cx));
- y = cy + int(r * (y - cy));
+ return theCoords.arrays_.x(this);
}
-void MathArray::setXY(int x, int y) const
+int MathArray::yo() const
{
- xo_ = x;
- yo_ = y;
+ return theCoords.arrays_.y(this);
}
-
-void MathArray::notifyCursorLeaves()
-{
- // do not recurse!
-
- // remove base-only "scripts"
- for (pos_type i = 0; i + 1 < size(); ++i) {
- MathScriptInset * p = operator[](i).nucleus()->asScriptInset();
- if (p && p->cell(0).empty() && p->cell(1).empty()) {
- MathArray ar = p->nuc();
- erase(i);
- insert(i, ar);
- mathcursor->adjust(i, ar.size() - 1);
- }
- }
-
- // glue adjacent font insets of the same kind
- for (pos_type i = 0; i + 1 < size(); ++i) {
- MathFontInset * p = operator[](i).nucleus()->asFontInset();
- MathFontInset const * q = operator[](i + 1)->asFontInset();
- if (p && q && p->name() == q->name()) {
- p->cell(0).append(q->cell(0));
- erase(i + 1);
- mathcursor->adjust(i, -1);
- }
- }
-
-}