]> git.lyx.org Git - lyx.git/blobdiff - src/TextMetrics.cpp
Fix comparing a pointer with a char
[lyx.git] / src / TextMetrics.cpp
index 48dbdd7a69578ee98d6c09b26001e3d0a5843dfc..e122d6a6a1d74f005b66460fb9c8a45b33922811 100644 (file)
@@ -51,6 +51,7 @@
 
 #include "support/debug.h"
 #include "support/docstring_list.h"
+#include "support/gettext.h"
 #include "support/lassert.h"
 
 #include <cstdlib>
@@ -128,7 +129,7 @@ static int numberOfHfills(Paragraph const & par, Row const & row)
 TextMetrics::TextMetrics(BufferView * bv, Text * text)
        : bv_(bv), text_(text)
 {
-       LASSERT(bv_, /**/);
+       LBUFERR(bv_);
        max_width_ = bv_->workWidth();
        dim_.wid = max_width_;
        dim_.asc = 10;
@@ -158,6 +159,7 @@ pair<pit_type, ParagraphMetrics const *> TextMetrics::first() const
 
 pair<pit_type, ParagraphMetrics const *> TextMetrics::last() const
 {
+       LBUFERR(!par_metrics_.empty());
        ParMetricsCache::const_reverse_iterator it = par_metrics_.rbegin();
        return make_pair(it->first, &it->second);
 }
@@ -178,7 +180,7 @@ ParagraphMetrics & TextMetrics::parMetrics(pit_type pit, bool redo)
 
 bool TextMetrics::metrics(MetricsInfo & mi, Dimension & dim, int min_width)
 {
-       LASSERT(mi.base.textwidth > 0, /**/);
+       LBUFERR(mi.base.textwidth > 0);
        max_width_ = mi.base.textwidth;
        // backup old dimension.
        Dimension const old_dim = dim_;
@@ -232,13 +234,13 @@ void TextMetrics::applyOuterFont(Font & font) const
 {
        FontInfo lf(font_.fontInfo());
        lf.reduce(bv_->buffer().params().getFont().fontInfo());
-       font.fontInfo().realize(lf); 
+       font.fontInfo().realize(lf);
 }
 
 
 Font TextMetrics::displayFont(pit_type pit, pos_type pos) const
 {
-       LASSERT(pos >= 0, /**/);
+       LASSERT(pos >= 0, { static Font f; return f; });
 
        ParagraphList const & pars = text_->paragraphs();
        Paragraph const & par = pars[pit];
@@ -313,6 +315,9 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos) const
 }
 
 
+// isRTLBoundary returns false on a real end-of-line boundary,
+// because otherwise the two boundary types get mixed up.
+// This is the whole purpose of this being in TextMetrics.
 bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos,
                Font const & font) const
 {
@@ -341,19 +346,19 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos,
        // no RTL boundary at line break:
        // abc|\n    -> move right ->   abc\n       (and not:    abc\n|
        // FED                          FED|                     FED     )
-       if (startpos == pos && endpos == pos && endpos != par.size() 
-               && (par.isNewline(pos - 1) 
-                       || par.isLineSeparator(pos - 1) 
+       if (startpos == pos && endpos == pos && endpos != par.size()
+               && (par.isNewline(pos - 1)
+                       || par.isLineSeparator(pos - 1)
                        || par.isSeparator(pos - 1)))
                return false;
-       
+
        bool left = font.isVisibleRightToLeft();
        bool right;
        if (pos == par.size())
                right = par.isRTL(bv_->buffer().params());
        else
                right = displayFont(pit, pos).isVisibleRightToLeft();
-       
+
        return left != right;
 }
 
@@ -371,19 +376,28 @@ bool TextMetrics::redoParagraph(pit_type const pit)
        main_text_ = (text_ == &buffer.text());
        bool changed = false;
 
+       // Check whether there are InsetBibItems that need fixing
        // FIXME: This check ought to be done somewhere else. It is the reason
-       // why text_ is not     const. But then, where else to do it?
+       // why text_ is not const. But then, where else to do it?
        // Well, how can you end up with either (a) a biblio environment that
        // has no InsetBibitem or (b) a biblio environment with more than one
        // InsetBibitem? I think the answer is: when paragraphs are merged;
        // when layout is set; when material is pasted.
-       int const moveCursor = par.checkBiblio(buffer);
-       if (moveCursor > 0)
-               const_cast<Cursor &>(bv_->cursor()).posForward();
-       else if (moveCursor < 0) {
-               Cursor & cursor = const_cast<Cursor &>(bv_->cursor());
-               if (cursor.pos() >= -moveCursor)
-                       cursor.posBackward();
+       if (par.brokenBiblio()) {
+               Cursor & cur = const_cast<Cursor &>(bv_->cursor());
+               // In some cases, we do not know how to record undo
+               if (&cur.inset() == &text_->inset())
+                       cur.recordUndo(ATOMIC_UNDO, pit, pit);
+
+               int const moveCursor = par.fixBiblio(buffer);
+
+               // Is it necessary to update the cursor?
+               if (&cur.inset() == &text_->inset() && cur.pit() == pit) {
+                       if (moveCursor > 0)
+                               cur.posForward();
+                       else if (moveCursor < 0 && cur.pos() >= -moveCursor)
+                               cur.posBackward();
+               }
        }
 
        // Optimisation: this is used in the next two loops
@@ -403,17 +417,16 @@ bool TextMetrics::redoParagraph(pit_type const pit)
                // should be.
                bv_->buffer().updateBuffer();
                parPos = text_->macrocontextPosition();
-               LASSERT(!parPos.empty(), /**/);
+               LBUFERR(!parPos.empty());
                parPos.pit() = pit;
        }
 
        // redo insets
-       // FIXME: We should always use getFont(), see documentation of
-       // noFontChange() in Inset.h.
        Font const bufferfont = buffer.params().getFont();
        InsetList::const_iterator ii = par.insetList().begin();
        InsetList::const_iterator iend = par.insetList().end();
        for (; ii != iend; ++ii) {
+               // FIXME Doesn't this HAVE to be non-empty?
                // position already initialized?
                if (!parPos.empty()) {
                        parPos.pos() = ii->pos;
@@ -430,8 +443,8 @@ bool TextMetrics::redoParagraph(pit_type const pit)
                Dimension dim;
                int const w = max_width_ - leftMargin(max_width_, pit, ii->pos)
                        - right_margin;
-               Font const & font = ii->inset->noFontChange() ?
-                       bufferfont : displayFont(pit, ii->pos);
+               Font const & font = ii->inset->inheritFont() ?
+                       displayFont(pit, ii->pos) : bufferfont;
                MacroContext mc(&buffer, parPos);
                MetricsInfo mi(bv_, font.fontInfo(), w, mc);
                ii->inset->metrics(mi, dim);
@@ -568,7 +581,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
                        case LYX_ALIGN_CENTER:
                        case LYX_ALIGN_LEFT:
                        case LYX_ALIGN_RIGHT:
-                               if (align == LYX_ALIGN_NONE 
+                               if (align == LYX_ALIGN_NONE
                                    || align == LYX_ALIGN_BLOCK)
                                        align = owner.contentAlignment();
                                break;
@@ -595,6 +608,11 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
                        }
                }
 
+               // Has the user requested we not justify stuff?
+               if (!bv_->buffer().params().justification
+                   && align == LYX_ALIGN_BLOCK)
+                       align = LYX_ALIGN_LEFT;
+
                switch (align) {
                case LYX_ALIGN_BLOCK: {
                        int const ns = numberOfSeparators(par, row);
@@ -675,7 +693,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const
        Paragraph const & par = text_->getPar(pit);
 
        pos_type last = par.beginOfBody();
-       LASSERT(last > 0, /**/);
+       LBUFERR(last > 0);
 
        // -1 because a label ends with a space that is in the label
        --last;
@@ -699,6 +717,8 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const
 }
 
 
+#if 0
+// Not used, see TextMetrics::rowBreakPoint.
 // this needs special handling - only newlines count as a break point
 static pos_type addressBreakPoint(pos_type i, Paragraph const & par)
 {
@@ -710,6 +730,7 @@ static pos_type addressBreakPoint(pos_type i, Paragraph const & par)
 
        return end;
 }
+#endif
 
 
 int TextMetrics::labelEnd(pit_type const pit) const
@@ -750,7 +771,7 @@ public:
        FontIterator & operator++()
        {
                ++pos_;
-               if (pos_ > endspan_ || pos_ == bodypos_) {
+               if (pos_ < par_.size() && (pos_ > endspan_ || pos_ == bodypos_)) {
                        font_ = tm_.displayFont(pit_, pos_);
                        endspan_ = par_.fontSpan(pos_).last;
                }
@@ -790,8 +811,13 @@ pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit,
 
        Layout const & layout = par.layout();
 
+#if 0
+       //FIXME: As long as leftMargin() is not correctly implemented for
+       // MARGIN_RIGHT_ADDRESS_BOX, we should also not do this here.
+       // Otherwise, long rows will be painted off the screen.
        if (layout.margintype == MARGIN_RIGHT_ADDRESS_BOX)
                return addressBreakPoint(pos, par);
+#endif
 
        pos_type const body_pos = par.beginOfBody();
 
@@ -827,10 +853,10 @@ pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit,
        ParagraphList const & pars_ = text_->paragraphs();
        bool const draw_par_end_marker = lyxrc.paragraph_markers
                && size_type(pit + 1) < pars_.size();
-                               
+
        for ( ; i < end; ++i, ++fi) {
                int thiswidth = pm.singleWidth(i, *fi);
-               
+
                if (draw_par_end_marker && i == end - 1)
                        // enlarge the last character to hold the end-of-par marker
                        thiswidth += par_marker_width;
@@ -947,8 +973,8 @@ int TextMetrics::rowWidth(int right_margin, pit_type const pit,
                                        w -= singleWidth(pit, i - 1);
                                w = max(w, label_end);
                        }
-                       
-                       // a line separator at the end of a line (but not at the end of a 
+
+                       // a line separator at the end of a line (but not at the end of a
                        // paragraph) will not be drawn and should therefore not count for
                        // the row width.
                        if (!par.isLineSeparator(i) || i != end - 1 || end == par.size())
@@ -1064,35 +1090,22 @@ Dimension TextMetrics::rowHeight(pit_type const pit, pos_type const first,
        if (first == 0 && topBottomSpace) {
                BufferParams const & bufparams = buffer.params();
                // some parskips VERY EASY IMPLEMENTATION
-               if (bufparams.paragraph_separation
-                   == BufferParams::ParagraphSkipSeparation
-                       && inset.lyxCode() != ERT_CODE
-                       && inset.lyxCode() != LISTINGS_CODE
-                       && pit > 0
-                       && ((layout.isParagraph() && par.getDepth() == 0)
-                           || (pars[pit - 1].layout().isParagraph()
-                               && pars[pit - 1].getDepth() == 0)))
-               {
-                               maxasc += bufparams.getDefSkip().inPixels(*bv_);
+               if (bufparams.paragraph_separation == BufferParams::ParagraphSkipSeparation
+                   && !inset.getLayout().parbreakIsNewline()
+                   && !par.layout().parbreak_is_newline
+                   && pit > 0
+                   && ((layout.isParagraph() && par.getDepth() == 0)
+                       || (pars[pit - 1].layout().isParagraph()
+                           && pars[pit - 1].getDepth() == 0))) {
+                       maxasc += bufparams.getDefSkip().inPixels(*bv_);
                }
 
                if (par.params().startOfAppendix())
                        maxasc += int(3 * dh);
 
-               // This is special code for the chapter, since the label of this
-               // layout is printed in an extra row
-               if (layout.counter == "chapter"
-                   && !par.params().labelString().empty()) {
-                       labeladdon = int(labelfont_metrics.maxHeight()
-                                    * layout.spacing.getValue()
-                                    * text_->spacing(par));
-               }
-
                // special code for the top label
-               if ((layout.labeltype == LABEL_TOP_ENVIRONMENT
-                    || layout.labeltype == LABEL_BIBLIO
-                    || layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT)
-                   && text_->isFirstInSequence(pit)
+               if (layout.labelIsAbove()
+                   && (!layout.isParagraphGroup() || text_->isFirstInSequence(pit))
                    && !par.labelString().empty())
                {
                        labeladdon = int(
@@ -1225,13 +1238,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
 
        // If lastrow is false, we don't need to compute
        // the value of rtl.
-       bool const rtl = lastrow ? text_->isRTL(par) : false;
-
-       // if the first character is a separator, and we are in RTL
-       // text, this character will not be painted on screen
-       // and thus we should not count it and skip to the next.
-       if (rtl && par.isSeparator(bidi.vis2log(vc)))
-               ++vc;
+       bool const rtl_on_lastrow = lastrow ? text_->isRTL(par) : false;
 
        while (vc < end && tmpx <= x) {
                c = bidi.vis2log(vc);
@@ -1255,13 +1262,14 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
                left_side = true;
        }
 
-       LASSERT(vc <= end, /**/);  // This shouldn't happen.
+       // This shouldn't happen. But we can reset and try to continue.
+       LASSERT(vc <= end, vc = end);
 
        boundary = false;
 
        if (lastrow &&
-           ((rtl  &&  left_side && vc == row.pos() && x < tmpx - 5) ||
-            (!rtl && !left_side && vc == end  && x > tmpx + 5))) {
+           ((rtl_on_lastrow  &&  left_side && vc == row.pos() && x < tmpx - 5) ||
+            (!rtl_on_lastrow && !left_side && vc == end  && x > tmpx + 5))) {
                if (!par.isNewline(end - 1))
                        c = end;
        } else if (vc == row.pos()) {
@@ -1328,7 +1336,7 @@ pos_type TextMetrics::x2pos(pit_type pit, int row, int x) const
        // upDownInText() while in selection mode.
        ParagraphMetrics const & pm = parMetrics(pit);
 
-       LASSERT(row < int(pm.rows().size()), /**/);
+       LBUFERR(row < int(pm.rows().size()));
        bool bound = false;
        Row const & r = pm.rows()[row];
        return r.pos() + getColumnNearX(pit, r, x, bound);
@@ -1374,7 +1382,8 @@ pit_type TextMetrics::getPitNearY(int y)
        int yy = -1;
        ParMetricsCache::const_iterator it = par_metrics_.begin();
        ParMetricsCache::const_iterator et = par_metrics_.end();
-       ParMetricsCache::const_iterator last = et; last--;
+       ParMetricsCache::const_iterator last = et;
+       --last;
 
        ParagraphMetrics const & pm = it->second;
 
@@ -1430,7 +1439,7 @@ Row const & TextMetrics::getPitAndRowNearY(int & y, pit_type & pit,
        ParagraphMetrics const & pm = par_metrics_[pit];
 
        int yy = pm.position() - pm.ascent();
-       LASSERT(!pm.rows().empty(), /**/);
+       LBUFERR(!pm.rows().empty());
        RowList::const_iterator rit = pm.rows().begin();
        RowList::const_iterator rlast = pm.rows().end();
        --rlast;
@@ -1479,7 +1488,7 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
        }
        pit_type pit = getPitNearY(y);
        LASSERT(pit != -1, return 0);
-       
+
        int yy = y; // is modified by getPitAndRowNearY
        Row const & row = getPitAndRowNearY(yy, pit, assert_in_view, up);
 
@@ -1496,10 +1505,6 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
        Inset * inset = checkInsetHit(x, yy);
        //lyxerr << "inset " << inset << " hit at x: " << x << " y: " << y << endl;
        if (!inset) {
-               // Either we deconst editXY or better we move current_font
-               // and real_current_font to Cursor
-               // FIXME: what is needed now that current_font and real_current_font
-               // are transferred?
                cur.setCurrentFont();
                return 0;
        }
@@ -1509,8 +1514,8 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
 
        // This should be just before or just behind the
        // cursor position set above.
-       LASSERT(inset == inset_before 
-               || inset == pars[pit].getInset(pos), /**/);
+       LASSERT(inset == inset_before
+               || inset == pars[pit].getInset(pos), return 0);
 
        // Make sure the cursor points to the position before
        // this inset.
@@ -1530,8 +1535,8 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
 
 void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const y)
 {
-       LASSERT(text_ == cur.text(), /**/);
-       pit_type pit = getPitNearY(y);
+       LASSERT(text_ == cur.text(), return);
+       pit_type const pit = getPitNearY(y);
        LASSERT(pit != -1, return);
 
        ParagraphMetrics const & pm = par_metrics_[pit];
@@ -1541,7 +1546,7 @@ void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const
                " pit: " << pit << " yy: " << yy);
 
        int r = 0;
-       LASSERT(pm.rows().size(), /**/);
+       LBUFERR(pm.rows().size());
        for (; r < int(pm.rows().size()) - 1; ++r) {
                Row const & row = pm.rows()[r];
                if (int(yy + row.height()) > y)
@@ -1611,7 +1616,7 @@ Inset * TextMetrics::checkInsetHit(int x, int y)
 int TextMetrics::cursorX(CursorSlice const & sl,
                bool boundary) const
 {
-       LASSERT(sl.text() == text_, /**/);
+       LASSERT(sl.text() == text_, return 0);
        pit_type const pit = sl.pit();
        Paragraph const & par = text_->paragraphs()[pit];
        ParagraphMetrics const & pm = par_metrics_[pit];
@@ -1786,7 +1791,7 @@ int TextMetrics::cursorY(CursorSlice const & sl, bool boundary) const
 
 bool TextMetrics::cursorHome(Cursor & cur)
 {
-       LASSERT(text_ == cur.text(), /**/);
+       LASSERT(text_ == cur.text(), return false);
        ParagraphMetrics const & pm = par_metrics_[cur.pit()];
        Row const & row = pm.getRow(cur.pos(),cur.boundary());
        return text_->setCursor(cur, cur.pit(), row.pos());
@@ -1795,7 +1800,7 @@ bool TextMetrics::cursorHome(Cursor & cur)
 
 bool TextMetrics::cursorEnd(Cursor & cur)
 {
-       LASSERT(text_ == cur.text(), /**/);
+       LASSERT(text_ == cur.text(), return false);
        // if not on the last row of the par, put the cursor before
        // the final space exept if I have a spanning inset or one string
        // is so long that we force a break.
@@ -1817,7 +1822,7 @@ bool TextMetrics::cursorEnd(Cursor & cur)
 
 void TextMetrics::deleteLineForward(Cursor & cur)
 {
-       LASSERT(text_ == cur.text(), /**/);
+       LASSERT(text_ == cur.text(), return);
        if (cur.lastpos() == 0) {
                // Paragraph is empty, so we just go forward
                text_->cursorForward(cur);
@@ -1852,8 +1857,6 @@ bool TextMetrics::isFirstRow(pit_type pit, Row const & row) const
 
 int TextMetrics::leftMargin(int max_width, pit_type pit) const
 {
-       LASSERT(pit >= 0, /**/);
-       LASSERT(pit < int(text_->paragraphs().size()), /**/);
        return leftMargin(max_width, pit, text_->paragraphs()[pit].size());
 }
 
@@ -1863,11 +1866,11 @@ int TextMetrics::leftMargin(int max_width,
 {
        ParagraphList const & pars = text_->paragraphs();
 
-       LASSERT(pit >= 0, /**/);
-       LASSERT(pit < int(pars.size()), /**/);
+       LASSERT(pit >= 0, return 0);
+       LASSERT(pit < int(pars.size()), return 0);
        Paragraph const & par = pars[pit];
-       LASSERT(pos >= 0, /**/);
-       LASSERT(pos <= par.size(), /**/);
+       LASSERT(pos >= 0, return 0);
+       LASSERT(pos <= par.size(), return 0);
        Buffer const & buffer = bv_->buffer();
        //lyxerr << "TextMetrics::leftMargin: pit: " << pit << " pos: " << pos << endl;
        DocumentClass const & tclass = buffer.params().documentClass();
@@ -1956,10 +1959,7 @@ int TextMetrics::leftMargin(int max_width,
                               && layout.latextype == LATEX_ENVIRONMENT
                               && !text_->isFirstInSequence(pit))) {
                        l_margin += labelfont_metrics.signedWidth(layout.leftmargin);
-               } else if (layout.labeltype != LABEL_TOP_ENVIRONMENT
-                          && layout.labeltype != LABEL_BIBLIO
-                          && layout.labeltype !=
-                          LABEL_CENTERED_TOP_ENVIRONMENT) {
+               } else if (!layout.labelIsAbove()) {
                        l_margin += labelfont_metrics.signedWidth(layout.labelindent);
                        l_margin += labelfont_metrics.width(layout.labelsep);
                        l_margin += labelfont_metrics.width(par.labelString());
@@ -1968,16 +1968,18 @@ int TextMetrics::leftMargin(int max_width,
 
        case MARGIN_RIGHT_ADDRESS_BOX: {
 #if 0
-               // ok, a terrible hack. The left margin depends on the widest
-               // row in this paragraph.
-               RowList::iterator rit = par.rows().begin();
-               RowList::iterator end = par.rows().end();
-               // FIXME: This is wrong.
+               // The left margin depends on the widest row in this paragraph.
+               // This code is wrong because it depends on the rows, but at the
+               // same time this function is used in redoParagraph to construct
+               // the rows.
+               ParagraphMetrics const & pm = par_metrics_[pit];
+               RowList::const_iterator rit = pm.rows().begin();
+               RowList::const_iterator end = pm.rows().end();
                int minfill = max_width;
                for ( ; rit != end; ++rit)
                        if (rit->fill() < minfill)
                                minfill = rit->fill();
-               l_margin += theFontMetrics(params.getFont()).signedWidth(layout.leftmargin);
+               l_margin += theFontMetrics(buffer.params().getFont()).signedWidth(layout.leftmargin);
                l_margin += minfill;
 #endif
                // also wrong, but much shorter.
@@ -1999,12 +2001,12 @@ int TextMetrics::leftMargin(int max_width,
        // set the correct parindent
        if (pos == 0
            && (layout.labeltype == LABEL_NO_LABEL
-              || layout.labeltype == LABEL_TOP_ENVIRONMENT
-              || layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT
+              || layout.labeltype == LABEL_ABOVE
+              || layout.labeltype == LABEL_CENTERED
               || (layout.labeltype == LABEL_STATIC
                   && layout.latextype == LATEX_ENVIRONMENT
                   && !text_->isFirstInSequence(pit)))
-           && align == LYX_ALIGN_BLOCK
+           && (align == LYX_ALIGN_BLOCK || align == LYX_ALIGN_LEFT)
            && !par.params().noindent()
            // in some insets, paragraphs are never indented
            && !text_->inset().neverIndent()
@@ -2014,7 +2016,7 @@ int TextMetrics::leftMargin(int max_width,
                    && par.getInset(pos)->display())
                        && (!(tclass.isDefaultLayout(par.layout())
                 || tclass.isPlainLayout(par.layout()))
-               || buffer.params().paragraph_separation 
+               || buffer.params().paragraph_separation
                                == BufferParams::ParagraphIndentSeparation)
            )
                {
@@ -2026,7 +2028,7 @@ int TextMetrics::leftMargin(int max_width,
                        else
                                l_margin += buffer.params().getIndentation().inPixels(*bv_);
                }
-       
+
        return l_margin;
 }
 
@@ -2087,7 +2089,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
        // We store the begin and end pos of the selection relative to this par
        DocIterator sel_beg_par = cur.selectionBegin();
        DocIterator sel_end_par = cur.selectionEnd();
-       
+
        // We care only about visible selection.
        if (selection) {
                if (pit != sel_beg.pit()) {
@@ -2116,7 +2118,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
                        row.setSelectionAndMargins(sel_beg_par, sel_end_par);
                else
                        row.setSelection(-1, -1);
-               
+
                // The row knows nothing about the paragraph, so we have to check
                // whether this row is the first or last and update the margins.
                if (row.selection()) {
@@ -2132,15 +2134,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
 
                // Take this opportunity to spellcheck the row contents.
                if (row_has_changed && lyxrc.spellcheck_continuously) {
-                       WordLangTuple wl;
-                       // dummy variable, not used.
-                       static docstring_list suggestions;
-                       pos_type from = row.pos();
-                       pos_type to = row.endpos();
-                       while (from < row.endpos()) {
-                               text_->getPar(pit).spellCheck(from, to, wl, suggestions, false);
-                               from = to + 1;
-                       }
+                       text_->getPar(pit).spellCheck();
                }
 
                // Don't paint the row if a full repaint has not been requested
@@ -2159,9 +2153,6 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
                        pi.pain.fillRectangle(x, y - row.ascent(),
                                width(), row.height(), pi.background_color);
                }
-               
-               if (row.selection())
-                       drawRowSelection(pi, x, row, cur, pit);
 
                // Instrumentation for testing row cache (see also
                // 12 lines lower):
@@ -2179,6 +2170,8 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
                // for inner insets as the Row has been cleared out.
                bool tmp = pi.full_repaint;
                pi.full_repaint = true;
+
+               rp.paintSelection();
                rp.paintAppendix();
                rp.paintDepthBar();
                rp.paintChangeBar();
@@ -2193,6 +2186,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
                if (i == 0 && is_rtl)
                        rp.paintFirst();
                y += row.descent();
+
                // Restore full_repaint status.
                pi.full_repaint = tmp;
        }
@@ -2203,102 +2197,6 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
 }
 
 
-void TextMetrics::drawRowSelection(PainterInfo & pi, int x, Row const & row,
-               Cursor const & curs, pit_type pit) const
-{
-       DocIterator beg = curs.selectionBegin();
-       beg.pit() = pit;
-       beg.pos() = row.sel_beg;
-
-       DocIterator end = curs.selectionEnd();
-       end.pit() = pit;
-       end.pos() = row.sel_end;
-
-       bool const begin_boundary = beg.pos() >= row.endpos();
-       bool const end_boundary = row.sel_end == row.endpos();
-
-       DocIterator cur = beg;
-       cur.boundary(begin_boundary);
-       int x1 = cursorX(beg.top(), begin_boundary);
-       int x2 = cursorX(end.top(), end_boundary);
-       int const y1 = bv_->getPos(cur).y_ - row.ascent();
-       int const y2 = y1 + row.height();
-
-       int const rm = text_->isMainText() ? bv_->rightMargin() : 0;
-       int const lm = text_->isMainText() ? bv_->leftMargin() : 0;
-
-       // draw the margins
-       if (row.begin_margin_sel) {
-               if (text_->isRTL(beg.paragraph())) {
-                       pi.pain.fillRectangle(x + x1, y1,  width() - rm - x1, y2 - y1,
-                               Color_selection);
-               } else {
-                       pi.pain.fillRectangle(x + lm, y1, x1 - lm, y2 - y1,
-                               Color_selection);
-               }
-       }
-
-       if (row.end_margin_sel) {
-               if (text_->isRTL(beg.paragraph())) {
-                       pi.pain.fillRectangle(x + lm, y1, x2 - lm, y2 - y1,
-                               Color_selection);
-               } else {
-                       pi.pain.fillRectangle(x + x2, y1, width() - rm - x2, y2 - y1,
-                               Color_selection);
-               }
-       }
-
-       // if we are on a boundary from the beginning, it's probably
-       // a RTL boundary and we jump to the other side directly as this
-       // segement is 0-size and confuses the logic below
-       if (cur.boundary())
-               cur.boundary(false);
-
-       // go through row and draw from RTL boundary to RTL boundary
-       while (cur < end) {
-               bool draw_now = false;
-
-               // simplified cursorForward code below which does not
-               // descend into insets and which does not go into the
-               // next line. Compare the logic with the original cursorForward
-
-               // if left of boundary -> just jump to right side, but
-               // for RTL boundaries don't, because: abc|DDEEFFghi -> abcDDEEF|Fghi
-               if (cur.boundary()) {
-                       cur.boundary(false);
-               }       else if (isRTLBoundary(cur.pit(), cur.pos() + 1)) {
-                       // in front of RTL boundary -> Stay on this side of the boundary
-                       // because:  ab|cDDEEFFghi -> abc|DDEEFFghi
-                       ++cur.pos();
-                       cur.boundary(true);
-                       draw_now = true;
-               } else {
-                       // move right
-                       ++cur.pos();
-
-                       // line end?
-                       if (cur.pos() == row.endpos())
-                               cur.boundary(true);
-               }
-
-               if (x1 == -1) {
-                       // the previous segment was just drawn, now the next starts
-                       x1 = cursorX(cur.top(), cur.boundary());
-               }
-
-               if (!(cur < end) || draw_now) {
-                       x2 = cursorX(cur.top(), cur.boundary());
-                       pi.pain.fillRectangle(x + min(x1,x2), y1, abs(x2 - x1), y2 - y1,
-                               Color_selection);
-
-                       // reset x1, so it is set again next round (which will be on the
-                       // right side of a boundary or at the selection end)
-                       x1 = -1;
-               }
-       }
-}
-
-
 void TextMetrics::completionPosAndDim(Cursor const & cur, int & x, int & y,
        Dimension & dim) const
 {