]> git.lyx.org Git - features.git/commitdiff
more work on \parbox support
authorAndré Pönitz <poenitz@gmx.net>
Tue, 16 Jul 2002 18:22:45 +0000 (18:22 +0000)
committerAndré Pönitz <poenitz@gmx.net>
Tue, 16 Jul 2002 18:22:45 +0000 (18:22 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4657 a592a061-630c-0410-9148-cb99ea01b6c8

src/mathed/dimension.C
src/mathed/dimension.h
src/mathed/math_cursor.C
src/mathed/math_inset.C
src/mathed/math_inset.h
src/mathed/math_nestinset.C
src/mathed/math_nestinset.h
src/mathed/math_parboxinset.C
src/mathed/math_parboxinset.h
src/mathed/math_xdata.C
src/mathed/math_xdata.h

index a756c7bf4fc76d1a4bf41dbc41c06cd6b8b2e587..04b30ff8e7ca4ed2f528cacbb198abb06d8f6c92 100644 (file)
@@ -1,5 +1,10 @@
 
+#include <config.h>
 #include "dimension.h"
+#include "math_support.h"
+
+#include <iostream>
+
 
 void Dimension::operator+=(Dimension const & dim)
 {
@@ -9,3 +14,17 @@ void Dimension::operator+=(Dimension const & dim)
                d = dim.d;
        w += dim.w;
 }
+
+
+std::ostream & operator<<(std::ostream & os, Dimension const & dim)
+{
+       os << " (" << dim.w << 'x' << dim.a << '-' << dim.d << ") ";
+       return os;
+}
+
+
+void Dimension::clear(LyXFont const & font)
+{
+       math_font_max_dim(font, a, d);
+       w = 0;
+}
index ab672568a9eee5eb03bcf884e4b5ab6dd90dfd7a..ca19dee251b37041a37d04c20f858da961f8c310 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef DIMENSION_H
 #define DIMENSION_H
 
+#include <iosfwd>
+
+class LyXFont;
+
 class Dimension {
 public:
        /// constructor
@@ -12,6 +16,8 @@ public:
        void operator+=(Dimension const & dim);
        /// set to empty box
        void clear() { w = a = d = 0; }
+       /// set to empty box suitble for given font
+       void clear(LyXFont const & font);
        /// get height
        int height() const { return a + d; }
        /// get ascent
@@ -30,4 +36,6 @@ public:
        int d;
 };
 
+std::ostream & operator<<(std::ostream & os, Dimension const & dim);
+
 #endif
index 18113f0920daa4198357167a2ae9b256ff80a46b..e8c887262dc901cd583ef733e349dd4f1ed20949 100644 (file)
@@ -719,15 +719,7 @@ void MathCursor::handleNest(MathInset * p)
 
 void MathCursor::getPos(int & x, int & y)
 {
-#ifdef WITH_WARNINGS
-#warning This should probably take cellXOffset and cellYOffset into account
-#endif
-       x = xarray().xo() + xarray().pos2x(pos());
-       // move cursor visually into empty cells ("blue rectangles");
-       if (array().empty())
-               x += 2;
-       y = xarray().yo();
-       //lyxerr << "getPos: " << x << " " << y << "\n";
+       par()->getPos(idx(), pos(), x, y);
 }
 
 
index dd2a8382819c92e5c67f9aa29d622b17357ce507..90138a48c0c31b62a15ec3aab75162391f00bf1e 100644 (file)
@@ -173,6 +173,13 @@ bool MathInset::idxEnd(idx_type &, pos_type &) const
 }
 
 
+void MathInset::getPos(idx_type, pos_type, int & x, int & y) const
+{
+       lyxerr << "MathInset::getPos() called directly!\n";
+       x = y = 0;
+}
+
+
 void MathInset::normalize(NormalStream & os) const
 {
        os << "[unknown ";
index 26b1e914c5872a7ebe0458187f08e7fa47c86757..5becf7ed11f9559f6f8597d72a46c58e9943dd04 100644 (file)
@@ -132,6 +132,8 @@ public:
        virtual void dimensions(Dimension & dim) const;
        /// total height (== ascent + descent)
        virtual int height() const;
+       /// get cursor position
+       virtual void getPos(idx_type idx, pos_type pos, int & x, int & y) const;
 
        /// Where should we go when we press the up or down cursor key?
        virtual bool idxUpDown(idx_type & idx, bool up) const;
index 16179f570bf87c9b336ad0b719b14c4585d3584b..520474d1974a9e07f8221e3db0aa2dda76eb6acf 100644 (file)
@@ -48,6 +48,15 @@ MathArray const & MathNestInset::cell(idx_type i) const
 }
 
 
+void MathNestInset::getPos(idx_type idx, pos_type pos, int & x, int & y) const
+{
+       x = cells_[idx].xo() + cells_[idx].pos2x(pos);
+       y = cells_[idx].yo();
+       // move cursor visually into empty cells ("blue rectangles");
+       if (!cells_[idx].data().size())
+               x += 2;
+}
+
 void MathNestInset::substitute(MathMacro const & m)
 {
        for (idx_type i = 0; i < nargs(); ++i)
index 32555e7a1dbdf12ad51b6a3fae2c378bfc5ee5cf..ba791df4d7351371a133a168e794aaeb06a75905 100644 (file)
@@ -36,6 +36,8 @@ public:
        void substitute(MathMacro const & macro);
        /// identifies NestInsets
        MathNestInset * asNestInset() { return this; }
+       /// get cursor position
+       void getPos(idx_type idx, pos_type pos, int & x, int & y) const;
 
        /// order of movement through the cells when pressing the left key
        bool idxLeft(idx_type & idx, pos_type & pos) const;
index 410912d62ced5c3d6781dc9e06b78667e0838af3..60b748c19d7f7da98293b87ae984a6397c1bbd22 100644 (file)
@@ -34,6 +34,22 @@ void MathParboxInset::setWidth(string const & w)
 }
 
 
+void MathParboxInset::getPos(idx_type idx, pos_type pos, int & x, int & y) const
+{
+       for (int r = 0, n = rows_.size(); r < n; ++r) {
+               if (pos >= rows_[r].begin && pos < rows_[r].end) {
+                       //lyxerr << "found cursor at pos " << pos << " in row " << r << "\n";
+                       x = cells_[0].xo() + cells_[0].pos2x(rows_[r].begin, pos, rows_[r].glue);
+                       y = cells_[0].yo() + rows_[r].yo;
+                       break;
+               }
+       }
+       // move cursor visually into empty cells ("blue rectangles");
+       if (cell(0).empty())
+               x += 2;
+}
+
+
 void MathParboxInset::metrics(MathMetricsInfo & mi) const
 {
        MathFontSetChanger dummy(mi.base, "textnormal");
@@ -42,68 +58,100 @@ void MathParboxInset::metrics(MathMetricsInfo & mi) const
        // delete old cache
        rows_.clear();
 
-#if 1
+#if 0
 
        dim_ = xcell(0).metrics(mi);
 
 #else
 
-       xcell(0).metricsExternal(mi, rows_);
+       vector<Dimension> dims; 
+       xcell(0).metricsExternal(mi, dims);
 
        int spaces = 0;
-       Dimension safe(0, 0, 0);
-       Dimension curr(0, 0, 0);
+       Dimension safe;
+       Dimension curr;
+       safe.clear(mi.base.font);
+       curr.clear(mi.base.font);
+       int begin = 0;
        int safepos = 0;
        int yo = 0;
-       for (size_type i = 0, n = cell(0).size(); i != n; ++i) {
+       for (size_type i = 0, n = cell(0).size(); i < n; ++i) {
+               //lyxerr << "at pos: " << i << " of " << n << " safepos: " << safepos
+               //      << " curr: " << curr << " safe: " << safe
+               //      << " spaces: " << spaces << endl;
+
+
+               //   0      1      2      3       4      5      6
+               // <char> <char> <char> <space> <char> <char> <char>
+               // ................... <safe>
+               //                      ..........................<curr>
+               // ....................<safepos>
+
                // Special handling of spaces. We reached a safe position for breaking.
                if (cell(0)[i]->getChar() == ' ') {
+                       //lyxerr << "reached safe pos\n";
+                       // we don't count the space into the safe pos
                        safe += curr;
-                       safepos = i + 1;
+                       // we reset to this safepos if the next chunk does not fit
+                       safepos = i;
                        ++spaces;
-                       // restart chunk
-                       curr = Dimension(0, 0, 0);
+                       // restart chunk with size of the space
+                       curr.clear(mi.base.font);
+                       curr += dims[i];
                        continue;
                }
 
-               // This is a regular item. Go on if we either don't care for
+               // This is a regular char. Go on if we either don't care for
                // the width limit or have not reached that limit.
-               curr += rows_[i].dim;
+               curr += dims[i];
                if (curr.w + safe.w <= lyx_width_) 
                        continue;
 
                // We passed the limit. Create a row entry.
+               //lyxerr << "passed limit\n";
                MathXArray::Row row;
                if (spaces) {
                        // but we had a space break before this position.
-                       row.dim  = safe;
-                       row.glue = (lyx_width_ - safe.w) / spaces;
-                       row.end  = safepos;
-                       i        = safepos;
+                       // so retreat to this position
+                       row.dim   = safe;
+                       row.glue  = (lyx_width_ - safe.w) / spaces;
+                       row.begin = begin;
+                       row.end   = safepos;  // this is position of the safe space
+                       i         = safepos;  // i gets incremented at end of loop
+                       begin     = i + 1;    // next chunk starts after the space
+                       //lyxerr << "... but had safe pos. glue: " << row.glue << "\n";
                        spaces   = 0;
                } else {
+                       lyxerr << "... without safe pos\n";
                        // This item is too large and it is the only one.
                        // We have no choice but to produce an overfull box.
-                       row.dim  = curr;   // safe should be 0.
-                       row.glue = 0;      // does not matter
-                       row.end  = i + 1;
+                       row.dim   = curr;   // safe should be 0.
+                       row.glue  = 0;      // does not matter
+                       row.begin = begin;
+                       row.end   = i + 1;
+                       begin     = i + 1;
                }
-               yo      += rows_[i].dim.height();
                row.yo   = yo;
+               yo      += row.dim.height();
                rows_.push_back(row);
+               // in any case, start the new row with empty boxes
+               curr.clear(mi.base.font);
+               safe.clear(mi.base.font);
        }
-       // last row:
+       // last row: put in everything else
        MathXArray::Row row;
-       row.dim  = safe;
-       row.dim += curr;
-       row.end  = cell(0).size();
-       row.glue = spaces ? (lyx_width_ - row.dim.w) / spaces : 0;
-       yo      += row.dim.height();
-       row.yo   = yo;
+       row.dim   = safe;
+       row.dim  += curr;
+       row.begin = begin;
+       row.end   = cell(0).size();
+       row.glue  = 0; // last line is left aligned
+       row.yo    = yo;
        rows_.push_back(row);
 
        // what to report?
-       dim_  = xcell(0).dim();
+       dim_.w = lyx_width_;
+       dim_.a = rows_.front().dim.a;
+       dim_.d = rows_.back().dim.d + yo;
        metricsMarkers();
 #endif
 }
@@ -112,7 +160,7 @@ void MathParboxInset::metrics(MathMetricsInfo & mi) const
 void MathParboxInset::draw(MathPainterInfo & pi, int x, int y) const
 {
        MathFontSetChanger dummy(pi.base, "textnormal");
-#if 1
+#if 0
        xcell(0).draw(pi, x + 1, y);
 #else
        xcell(0).drawExternal(pi, x + 1, y, rows_);
index 1b6785b5d4650bc503ac77d408c80997ff30de15..f7305478cd21d924fc4352a967611be0ae35e449 100644 (file)
@@ -11,6 +11,8 @@ public:
        MathParboxInset * asParboxInset() { return this; }
        ///
        MathInset * clone() const;
+       /// get cursor position
+       void getPos(idx_type idx, pos_type pos, int & x, int & y) const;
        ///
        void metrics(MathMetricsInfo & mi) const;
        ///
index 2216623f5afe2af67a8734dd65e248ce58655620..a88b7fc8131d9876bf8a509b15dda0e83b2918da 100644 (file)
@@ -67,7 +67,7 @@ Dimension const & MathXArray::metrics(MathMetricsInfo & mi) const
 
 
 void MathXArray::metricsExternal(MathMetricsInfo & mi,
-       std::vector<Row> & v) const
+       std::vector<Dimension> & v) const
 {
        //if (clean_)
        //      return;
@@ -89,18 +89,18 @@ void MathXArray::metricsExternal(MathMetricsInfo & mi,
                if (q) {
                        q->metrics(p, mi);
                        q->dimensions2(p, d);
+                       v.push_back(d);
+                       v.push_back(Dimension());
                        ++it;
-                       v.push_back(Row());
-                       v.back().dim = d;
-                       v.push_back(Row());
                } else {
                        p->metrics(mi);
                        p->dimensions(d);
-                       v.push_back(Row());
-                       v.back().dim = d;
+                       v.push_back(d);
                }
        }
 
+       //for (int i = 0; i < data_.size(); ++i)
+       //      lyxerr << "i: " << i << "  dim: " << v[i] << endl;
        //lyxerr << "MathXArray::metrics(): '" << dim_ << "\n";
 }
 
@@ -150,14 +150,28 @@ void MathXArray::draw(MathPainterInfo & pi, int x, int y) const
 void MathXArray::drawExternal(MathPainterInfo & pi, int x, int y,
        std::vector<Row> const & v) const
 {
-       for (size_type r = 0, pos = 0; r != v.size(); ++r) {
+       //for (size_type r = 0; r < v.size(); ++r)
+       //      lyxerr << "row " << r << " to: " << v[r].end << endl; 
+       //lyxerr << " data: " << data_ << endl;
+
+       xo_    = x;
+       yo_    = y;
+
+       for (size_type r = 0; r < v.size(); ++r) {
                int xx = x;
                int yy = y + v[r].yo;
-               for ( ; pos != v[r].end; ++pos) {
+               for (size_type pos = v[r].begin; pos < v[r].end && pos < data_.size(); ++pos) {
+                       //lyxerr << "drawing pos " << pos << " of " << data_.size() 
+                       //      << " " << int(data_[pos]->getChar()) << endl;
                        MathInset const * p = data_[pos].nucleus();
+               
+                       // insert extra glue
+                       if (p->getChar() == ' ') 
+                               xx += v[r].glue;
+       
                        MathScriptInset const * q = 0;
-                       if (pos + 1 != data_.size())
-                               q = asScript(begin() + pos + 1);
+                       if (pos + 1 < data_.size())
+                               q = asScript(begin() + pos);
                        if (q) {
                                q->draw(p, pi, xx, yy);
                                xx += q->width2(p);
@@ -222,16 +236,24 @@ void MathXArray::drawT(TextPainter & pain, int x, int y) const
 }
 
 
-int MathXArray::pos2x(size_type targetpos) const
+int MathXArray::pos2x(size_type pos) const
+{
+       return pos2x(0, pos, 0);
+}
+
+int MathXArray::pos2x(size_type pos1, size_type pos2, int glue) const
 {
        int x = 0;
-       const_iterator target = min(begin() + targetpos, end());
-       for (const_iterator it = begin(); it < target; ++it) {
+       size_type target = min(pos2, data_.size());
+       for (size_type i = pos1; i < target; ++i) {
+               const_iterator it = begin() + i;
                MathInset const * p = it->nucleus();
-               MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
+               if (p->getChar() == ' ')
+                       x += glue;
+               MathScriptInset const * q = (i + 1 == data_.size()) ? 0 : asScript(it);
                if (q) {
-                       ++it;
-                       if (it < target)
+                       ++i;
+                       if (i < target)
                                x += q->width2(p);
                        else  // "half" position
                                x += q->dxx(p) + q->nwid(p);
index a22735eefd793148e5f3a9dfa632738fc8ca2e50..2bb7a2ff0d0c2301c6aec6309adb66325eb3efd0 100644 (file)
@@ -33,6 +33,8 @@ public:
        struct Row {
                /// constructor
                Row() {}
+               /// first position of this row
+               size_type begin; 
                /// last position of this row plus one
                size_type end; 
                /// y offset relative to yo
@@ -48,8 +50,7 @@ public:
        /// rebuild cached metrics information
        Dimension const & metrics(MathMetricsInfo & mi) const;
        /// rebuild cached metrics information
-       void metricsExternal(MathMetricsInfo & mi,
-               std::vector<MathXArray::Row> &) const;
+       void metricsExternal(MathMetricsInfo & mi, std::vector<Dimension> &) const;
        /// redraw cell using cache metrics information
        void draw(MathPainterInfo & pi, int x, int y) const;
        /// redraw cell using external metrics information
@@ -73,6 +74,8 @@ public:
        /// returns x coordinate of given position in the array
        int pos2x(size_type pos) const;
        /// returns position of given x coordinate
+       int pos2x(size_type pos1, size_type pos2, int glue) const;
+       /// returns position of given x coordinate
        size_type x2pos(int pos) const;
        /// returns distance of this cell to the point given by x and y
        // assumes valid position and size cache