]> git.lyx.org Git - lyx.git/blobdiff - src/TextMetrics.cpp
Whitespace.
[lyx.git] / src / TextMetrics.cpp
index 722b7d6b274a1dbb54b95e8061402fda1b8b5dce..f78594f54dad9860e42a6f2f05aedc13224edb32 100644 (file)
@@ -40,6 +40,7 @@
 #include "Text.h"
 #include "TextClass.h"
 #include "VSpace.h"
+#include "WordLangTuple.h"
 
 #include "insets/InsetText.h"
 
 #include "frontends/Painter.h"
 
 #include "support/debug.h"
-#include <cstdlib>
+#include "support/docstring_list.h"
 #include "support/lassert.h"
 
+#include <cstdlib>
+
 using namespace std;
 
 
@@ -241,11 +244,9 @@ int TextMetrics::rightMargin(pit_type const pit) const
 
 void TextMetrics::applyOuterFont(Font & font) const
 {
-       Font lf(font_);
-       lf.fontInfo().reduce(bv_->buffer().params().getFont().fontInfo());
-       lf.fontInfo().realize(font.fontInfo());
-       lf.setLanguage(font.language());
-       font = lf;
+       FontInfo lf(font_.fontInfo());
+       lf.reduce(bv_->buffer().params().getFont().fontInfo());
+       font.fontInfo().realize(lf); 
 }
 
 
@@ -444,7 +445,7 @@ bool TextMetrics::redoParagraph(pit_type const pit)
                        - right_margin;
                Font const & font = ii->inset->noFontChange() ?
                        bufferfont : displayFont(pit, ii->pos);
-               MacroContext mc(buffer, parPos);
+               MacroContext mc(&buffer, parPos);
                MetricsInfo mi(bv_, font.fontInfo(), w, mc);
                ii->inset->metrics(mi, dim);
                Dimension const old_dim = pm.insetDimension(ii->inset);
@@ -791,8 +792,8 @@ private:
 
 } // anon namespace
 
-pit_type TextMetrics::rowBreakPoint(int width, pit_type const pit,
-               pit_type pos) const
+pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit,
+               pos_type pos) const
 {
        ParagraphMetrics const & pm = par_metrics_[pit];
        Paragraph const & par = text_->getPar(pit);
@@ -828,11 +829,24 @@ pit_type TextMetrics::rowBreakPoint(int width, pit_type const pit,
        // pixel width since last breakpoint
        int chunkwidth = 0;
 
+       docstring const s(1, char_type(0x00B6));
+       Font f;
+       int par_marker_width = theFontMetrics(f).width(s);
+
        FontIterator fi = FontIterator(*this, par, pit, pos);
        pos_type point = end;
        pos_type i = pos;
+
+       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;
 
                // add inline completion width
                if (inlineCompletionLPos == i) {
@@ -962,6 +976,18 @@ int TextMetrics::rowWidth(int right_margin, pit_type const pit,
                }
        }
 
+       // count the paragraph end marker.
+       if (end == par.size() && lyxrc.paragraph_markers) {
+               ParagraphList const & pars_ = text_->paragraphs();
+               if (size_type(pit + 1) < pars_.size()) {
+                       // enlarge the last character to hold the
+                       // end-of-par marker
+                       docstring const s(1, char_type(0x00B6));
+                       Font f;
+                       w += theFontMetrics(f).width(s);
+               }
+       }
+
        if (body_pos > 0 && body_pos >= end) {
                FontMetrics const & fm = theFontMetrics(
                        text_->labelFont(par));
@@ -1206,6 +1232,12 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
                return 0;
        }
 
+       // if the first character is a separator, 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 (par.isSeparator(bidi.vis2log(vc)))
+               ++vc;
+
        while (vc < end && tmpx <= x) {
                c = bidi.vis2log(vc);
                last_tmpx = tmpx;
@@ -1403,7 +1435,7 @@ pit_type TextMetrics::getPitNearY(int y)
 }
 
 
-Row const & TextMetrics::getPitAndRowNearY(int y, pit_type & pit,
+Row const & TextMetrics::getPitAndRowNearY(int y, pit_type & pit,
        bool assert_in_view, bool up)
 {
        ParagraphMetrics const & pm = par_metrics_[pit];
@@ -1417,25 +1449,29 @@ Row const & TextMetrics::getPitAndRowNearY(int y, pit_type & pit,
                if (yy + rit->height() > y)
                        break;
 
-       if (assert_in_view && yy + rit->height() != y) {
-               if (!up) {
-                       if (rit != pm.rows().begin())
+       if (assert_in_view) {
+               if (!up && yy + rit->height() > y) {
+                       if (rit != pm.rows().begin()) {
+                               y = yy;
                                --rit;
-                       else if (pit != 0) {
+                       else if (pit != 0) {
                                --pit;
                                newParMetricsUp();
                                ParagraphMetrics const & pm2 = par_metrics_[pit];
                                rit = pm2.rows().end();
                                --rit;
+                               y = yy;
                        }
-               } else  {
-                       if (rit != rlast)
+               } else if (up && yy != y) {
+                       if (rit != rlast) {
+                               y = yy + rit->height();
                                ++rit;
-                       else if (pit != int(par_metrics_.size())) {
+                       } else if (pit < int(text_->paragraphs().size()) - 1) {
                                ++pit;
                                newParMetricsDown();
                                ParagraphMetrics const & pm2 = par_metrics_[pit];
                                rit = pm2.rows().begin();
+                               y = pm2.position();
                        }
                }
        }
@@ -1454,10 +1490,11 @@ 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);
 
-       Row const & row = getPitAndRowNearY(y, pit, assert_in_view, up);
-       bool bound = false;
-
+       bool bound = false; // is modified by getColumnNearX
        int xx = x; // is modified by getColumnNearX
        pos_type const pos = row.pos()
                + getColumnNearX(pit, row, xx, bound);
@@ -1467,7 +1504,7 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
        cur.setTargetX(x);
 
        // try to descend into nested insets
-       Inset * inset = checkInsetHit(x, 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
@@ -1479,23 +1516,22 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
        }
 
        ParagraphList const & pars = text_->paragraphs();
-       Inset const * insetBefore = pos ? pars[pit].getInset(pos - 1) : 0;
-       //Inset * insetBehind = pars[pit].getInset(pos);
+       Inset const * inset_before = pos ? pars[pit].getInset(pos - 1) : 0;
 
        // This should be just before or just behind the
        // cursor position set above.
-       LASSERT((pos != 0 && inset == insetBefore)
+       LASSERT(inset == inset_before 
                || inset == pars[pit].getInset(pos), /**/);
 
        // Make sure the cursor points to the position before
        // this inset.
-       if (inset == insetBefore) {
+       if (inset == inset_before) {
                --cur.pos();
                cur.boundary(false);
        }
 
        // Try to descend recursively inside the inset.
-       inset = inset->editXY(cur, x, y);
+       inset = inset->editXY(cur, x, yy);
 
        if (cur.top().text() == text_)
                cur.setCurrentFont();
@@ -1622,6 +1658,8 @@ int TextMetrics::cursorX(CursorSlice const & sl,
        else if (ppos >= end)
                cursor_vpos = text_->isRTL(par) ? row_pos : end;
        else if (ppos > row_pos && ppos >= end)
+               //FIXME: this code is never reached!
+               //       (see http://www.lyx.org/trac/changeset/8251)
                // Place cursor after char at (logical) position pos - 1
                cursor_vpos = (bidi.level(ppos - 1) % 2 == 0)
                        ? bidi.log2vis(ppos - 1) + 1 : bidi.log2vis(ppos - 1);
@@ -1656,6 +1694,15 @@ int TextMetrics::cursorX(CursorSlice const & sl,
        if (end > 0 && end < par.size() && par.isSeparator(end - 1))
                skipped_sep_vpos = bidi.log2vis(end - 1);
 
+       if (lyxrc.paragraph_markers && text_->isRTL(par)) {
+               ParagraphList const & pars_ = text_->paragraphs();
+               if (size_type(pit + 1) < pars_.size()) {
+                       FontInfo f;
+                       docstring const s = docstring(1, char_type(0x00B6));
+                       x += theFontMetrics(f).width(s);
+               }
+       }
+
        // Inline completion RTL special case row_pos == cursor_pos:
        // "__|b" => cursor_pos is right of __
        if (row_pos == inlineCompletionVPos && row_pos == cursor_vpos) {
@@ -2093,6 +2140,19 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
                row.setCrc(pm.computeRowSignature(row, bparams));
                bool row_has_changed = row.changed();
 
+               // 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;
+                       }
+               }
+
                // Don't paint the row if a full repaint has not been requested
                // and if it has not changed.
                if (!pi.full_repaint && !row_has_changed) {
@@ -2132,11 +2192,16 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
                rp.paintAppendix();
                rp.paintDepthBar();
                rp.paintChangeBar();
-               if (i == 0)
+               bool const is_rtl = text_->isRTL(text_->getPar(pit));
+               if (i == 0 && !is_rtl)
                        rp.paintFirst();
+               if (i == nrows - 1 && is_rtl)
+                       rp.paintLast();
                rp.paintText();
-               if (i == nrows - 1)
+               if (i == nrows - 1 && !is_rtl)
                        rp.paintLast();
+               if (i == 0 && is_rtl)
+                       rp.paintFirst();
                y += row.descent();
                // Restore full_repaint status.
                pi.full_repaint = tmp;