]> git.lyx.org Git - lyx.git/blobdiff - src/rowpainter.C
Fix dEPM crash:
[lyx.git] / src / rowpainter.C
index f29b51e1d592023d038c0cfeefdc95d62cc2c006..5b83338af96882b38422430198f471fa20605688 100644 (file)
@@ -48,7 +48,6 @@ using frontend::FontMetrics;
 
 using std::endl;
 using std::max;
-using std::min;
 using std::string;
 
 
@@ -156,6 +155,11 @@ int RowPainter::leftMargin() const
 }
 
 
+// If you want to debug inset metrics uncomment the following line:
+// #define DEBUG_METRICS
+// This draws green lines around each inset.
+
+
 void RowPainter::paintInset(pos_type const pos, LyXFont const & font)
 {
        InsetBase const * inset = par_.getInset(pos);
@@ -168,19 +172,53 @@ void RowPainter::paintInset(pos_type const pos, LyXFont const & font)
                font;
        pi.ltr_pos = (text_.bidi.level(pos) % 2 == 0);
        pi.erased_ = erased_ || par_.isDeleted(pos);
+#ifdef DEBUG_METRICS
+       int const x1 = int(x_);
+#endif
        bv_.coordCache().insets().add(inset, int(x_), yo_);
        InsetText const * const in = inset->asTextInset();
        // non-wide insets are painted completely. Recursive
        bool tmp = refreshInside;
-       if (!in || !in->Wide()) {
+       if (!in || !in->wide()) {
                refreshInside = true;
-               lyxerr[Debug::PAINTING] << endl << "Paint inset fully" << endl;
+               if (lyxerr.debugging(Debug::PAINTING)) { 
+                       lyxerr << endl << "Paint inset fully" << endl;
+               }
        }
        if (refreshInside)
                inset->drawSelection(pi, int(x_), yo_);
        inset->draw(pi, int(x_), yo_);
        refreshInside = tmp;
        x_ += inset->width();
+#ifdef DEBUG_METRICS
+       Dimension dim;
+       BOOST_ASSERT(text_.maxwidth_ > 0);
+       int const w = text_.maxwidth_ - leftMargin() - text_.rightMargin(*bv_.buffer(), par_);
+       MetricsInfo mi(&bv_, font, w);
+       inset->metrics(mi, dim);
+       if (inset->width() > dim.wid) 
+               lyxerr << "Error: inset " << to_ascii(inset->getInsetName())
+                      << " draw width " << inset->width()
+                      << "> metrics width " << dim.wid << "." << std::endl;
+       if (inset->ascent() > dim.asc) 
+               lyxerr << "Error: inset " << to_ascii(inset->getInsetName())
+                      << " draw ascent " << inset->ascent()
+                      << "> metrics ascent " << dim.asc << "." << std::endl;
+       if (inset->descent() > dim.des) 
+               lyxerr << "Error: inset " << to_ascii(inset->getInsetName())
+                      << " draw ascent " << inset->descent()
+                      << "> metrics descent " << dim.des << "." << std::endl;
+       BOOST_ASSERT(inset->width() <= dim.wid);
+       BOOST_ASSERT(inset->ascent() <= dim.asc);
+       BOOST_ASSERT(inset->descent() <= dim.des);
+       int const x2 = x1 + dim.wid;
+       int const y1 = yo_ + dim.des;
+       int const y2 = yo_ - dim.asc;
+       pi.pain.line(x1, y1, x1, y2, LColor::green);
+       pi.pain.line(x1, y1, x2, y1, LColor::green);
+       pi.pain.line(x2, y1, x2, y2, LColor::green);
+       pi.pain.line(x1, y2, x2, y2, LColor::green);
+#endif
 }
 
 
@@ -202,9 +240,8 @@ void RowPainter::paintHebrewComposeChar(pos_type & vpos, LyXFont const & font)
                c = par_.getChar(i);
                if (!Encodings::isComposeChar_hebrew(c)) {
                        if (isPrintableNonspace(c)) {
-                               int const width2 =
-                                       text_.singleWidth(*bv_.buffer(), par_, i, c,
-                                               text_.getFont(*bv_.buffer(), par_, i));
+                               int const width2 = text_.singleWidth(par_, i, c,
+                                       text_.getFont(*bv_.buffer(), par_, i));
                                // FIXME UNICODE
                                // This does not work anymore, and non-ascii
                                // characters in source files are forbidden
@@ -242,8 +279,7 @@ void RowPainter::paintArabicComposeChar(pos_type & vpos, LyXFont const & font)
                c = par_.getChar(i);
                if (!Encodings::isComposeChar_arabic(c)) {
                        if (isPrintableNonspace(c)) {
-                               int const width2 =
-                                       text_.singleWidth(*bv_.buffer(), par_, i, c,
+                               int const width2 = text_.singleWidth(par_, i, c,
                                                text_.getFont(*bv_.buffer(), par_, i));
                                dx = (width2 - width) / 2;
                        }
@@ -370,7 +406,13 @@ void RowPainter::paintFromPos(pos_type & vpos)
 void RowPainter::paintChangeBar()
 {
        pos_type const start = row_.pos();
-       pos_type const end = row_.endpos();
+       pos_type end = row_.endpos();
+
+       if (par_.size() == end) {
+               // this is the last row of the paragraph;
+               // thus, we must also consider the imaginary end-of-par character
+               end++;
+       }
 
        if (start == end || !par_.isChanged(start, end))
                return;
@@ -594,7 +636,21 @@ void RowPainter::paintLast()
        bool const is_rtl = text_.isRTL(*bv_.buffer(), par_);
        int const endlabel = getEndLabel(pit_, text_.paragraphs());
 
+       // paint imaginary end-of-paragraph character
+
+       if (par_.isInserted(par_.size()) || par_.isDeleted(par_.size())) {
+               FontMetrics const & fm = theFontMetrics(bv_.buffer()->params().getFont());
+               int const length = fm.maxAscent() / 2;
+               LColor::color col = par_.isInserted(par_.size()) ? LColor::newtext : LColor::strikeout;
+               
+               pain_.line(int(x_) + 1, yo_ + 2, int(x_) + 1, yo_ + 2 - length, col,
+                          Painter::line_solid, Painter::line_thick);
+               pain_.line(int(x_) + 1 - length, yo_ + 2, int(x_) + 1, yo_ + 2, col,
+                          Painter::line_solid, Painter::line_thick);
+       }
+
        // draw an endlabel
+
        switch (endlabel) {
        case END_LABEL_BOX:
        case END_LABEL_FILLED_BOX: {
@@ -668,8 +724,8 @@ void RowPainter::paintText()
                        font = text_.getFont(buffer, par_, vpos);
                }
 
-               const int width_pos = text_.singleWidth(buffer, par_, pos,
-                       par_.getChar(pos), font);
+               const int width_pos =
+                       text_.singleWidth(par_, pos, par_.getChar(pos), font);
 
                if (x_ + width_pos < 0) {
                        x_ += width_pos;
@@ -839,12 +895,17 @@ void paintPar
                        text);
 
                // If this is the only object on the row, we can make it wide
+               //
+               // FIXME: there is a const_cast here because paintPar() is not supposed
+               // to touch the paragraph contents. So either we move this "wide"
+               // property out of InsetText or we localize the feature to the painting
+               // done here.
                for (pos_type i = rit->pos() ; i != rit->endpos(); ++i) {
                        InsetBase const * const in = par.getInset(i);
                        if (in) {
-                               InsetText const * const t = in->asTextInset();
+                               InsetText * t = const_cast<InsetText *>(in->asTextInset());
                                if (t)
-                                       t->Wide() = in_inset_alone_on_row;
+                                       t->setWide(in_inset_alone_on_row);
                        }
                }
 
@@ -875,20 +936,22 @@ void paintPar
 
                        // Instrumentation for testing row cache (see also
                        // 12 lines lower):
-                       if (text.isMainText(*pi.base.bv->buffer()))
-                               lyxerr[Debug::PAINTING] << "#";
-                       else
-                               lyxerr[Debug::PAINTING] << "[" <<
-                                   repaintAll << row_has_changed <<
-                                   cursor_on_row << "]";
+                       if (lyxerr.debugging(Debug::PAINTING)) {
+                               if (text.isMainText(*pi.base.bv->buffer()))
+                                       lyxerr[Debug::PAINTING] << "#";
+                               else
+                                       lyxerr[Debug::PAINTING] << "[" <<
+                                               repaintAll << row_has_changed <<
+                                               cursor_on_row << "]";
+                       }
                        rp.paintAppendix();
                        rp.paintDepthBar();
                        rp.paintChangeBar();
                        if (rit == rb)
                                rp.paintFirst();
+                       rp.paintText();
                        if (rit + 1 == re)
                                rp.paintLast();
-                       rp.paintText();
                }
                y += rit->descent();
                // Restore, see above
@@ -897,7 +960,9 @@ void paintPar
        // Re-enable screen drawing for future use of the painter.
        pi.pain.setDrawingEnabled(true);
 
-       lyxerr[Debug::PAINTING] << "." << endl;
+       if (lyxerr.debugging(Debug::PAINTING)) {
+               lyxerr[Debug::PAINTING] << "." << endl;
+       }
 }
 
 } // namespace anon
@@ -935,22 +1000,6 @@ void paintText(BufferView & bv,
                yy += par.descent();
        }
 
-       // Cache one paragraph above and one below
-       // Note MV: this cannot be suppressed even for singlepar.
-       // Try viewing the User Guide Mobius figure
-
-       if (vi.p1 > 0) {
-               text.redoParagraph(bv, vi.p1 - 1);
-               bv.coordCache().parPos()[&text][vi.p1 - 1] =
-                       Point(0, vi.y1 - text.getPar(vi.p1 - 1).descent());
-       }
-
-       if (vi.p2 < pit_type(text.paragraphs().size()) - 1) {
-               text.redoParagraph(bv, vi.p2 + 1);
-               bv.coordCache().parPos()[&text][vi.p2 + 1] =
-                       Point(0, vi.y2 + text.getPar(vi.p2 + 1).ascent());
-       }
-
        // and grey out above (should not happen later)
 //     lyxerr << "par ascent: " << text.getPar(vi.p1).ascent() << endl;
        if (vi.y1 > 0 && !vi.singlepar)
@@ -968,7 +1017,7 @@ void paintTextInset(LyXText const & text, PainterInfo & pi, int x, int y)
 //     lyxerr << "  paintTextInset: y: " << y << endl;
 
        y -= text.getPar(0).ascent();
-       // This flag can not be set from within same inset:
+       // This flag cannot be set from within same inset:
        bool repaintAll = refreshInside;
        for (int pit = 0; pit < int(text.paragraphs().size()); ++pit) {
                y += text.getPar(pit).ascent();