]> git.lyx.org Git - lyx.git/blobdiff - src/TextMetrics.cpp
A couple comments and some very minor cleanup.
[lyx.git] / src / TextMetrics.cpp
index fe9cb929476ac165869b38f7e327dc913143eddc..a3f7550468dda2cae6c7d654d16c6aa6f2c0a426 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;
 
 
@@ -292,7 +295,7 @@ Font TextMetrics::displayFont(pit_type pit, pos_type pos) const
        // NOTE: the cast to pit_type should be removed when pit_type
        // changes to a unsigned integer.
        if (pit < pit_type(pars.size()))
-               font.fontInfo().realize(outerFont(pit, pars).fontInfo());
+               font.fontInfo().realize(text_->outerFont(pit).fontInfo());
 
        // Realize with the fonts of lesser depth.
        font.fontInfo().realize(params.getFont().fontInfo());
@@ -791,8 +794,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 +831,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) {
@@ -946,7 +962,12 @@ int TextMetrics::rowWidth(int right_margin, pit_type const pit,
                                        w -= singleWidth(pit, i - 1);
                                w = max(w, label_end);
                        }
-                       w += pm.singleWidth(i, *fi);
+                       
+                       // 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())
+                               w += pm.singleWidth(i, *fi);
 
                        // add inline completion width
                        if (inlineCompletionLPos == i) {
@@ -957,6 +978,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));
@@ -1074,7 +1107,7 @@ Dimension TextMetrics::rowHeight(pit_type const pit, pos_type const first,
                if ((layout.labeltype == LABEL_TOP_ENVIRONMENT
                     || layout.labeltype == LABEL_BIBLIO
                     || layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT)
-                   && isFirstInSequence(pit, pars)
+                   && text_->isFirstInSequence(pit)
                    && !par.labelString().empty())
                {
                        labeladdon = int(
@@ -1088,7 +1121,7 @@ Dimension TextMetrics::rowHeight(pit_type const pit, pos_type const first,
                // a section, or between the items of a itemize or enumerate
                // environment.
 
-               pit_type prev = depthHook(pit, pars, par.getDepth());
+               pit_type prev = text_->depthHook(pit, par.getDepth());
                Paragraph const & prevpar = pars[prev];
                if (prev != pit
                    && prevpar.layout() == layout
@@ -1101,7 +1134,7 @@ Dimension TextMetrics::rowHeight(pit_type const pit, pos_type const first,
                                layoutasc = layout.topsep * dh;
                }
 
-               prev = outerHook(pit, pars);
+               prev = text_->outerHook(pit);
                if (prev != pit_type(pars.size())) {
                        maxasc += int(pars[prev].layout().parsep * dh);
                } else if (pit != 0) {
@@ -1126,7 +1159,7 @@ Dimension TextMetrics::rowHeight(pit_type const pit, pos_type const first,
 
                        if (pars[cpit].getDepth() > pars[nextpit].getDepth()) {
                                usual = pars[cpit].layout().bottomsep * dh;
-                               cpit = depthHook(cpit, pars, pars[nextpit].getDepth());
+                               cpit = text_->depthHook(cpit, pars[nextpit].getDepth());
                                if (pars[cpit].layout() != pars[nextpit].layout()
                                        || pars[nextpit].getLabelWidthString() != pars[cpit].getLabelWidthString())
                                {
@@ -1398,7 +1431,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];
@@ -1414,23 +1447,27 @@ Row const & TextMetrics::getPitAndRowNearY(int y, pit_type & pit,
 
        if (assert_in_view && yy + rit->height() != y) {
                if (!up) {
-                       if (rit != pm.rows().begin())
+                       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)
+                       if (rit != rlast) {
+                               y = yy + rit->height();
                                ++rit;
-                       else if (pit != int(par_metrics_.size())) {
+                       else if (pit != int(par_metrics_.size())) {
                                ++pit;
                                newParMetricsDown();
                                ParagraphMetrics const & pm2 = par_metrics_[pit];
                                rit = pm2.rows().begin();
+                               y = pm2.position();
                        }
                }
        }
@@ -1449,8 +1486,9 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
        }
        pit_type pit = getPitNearY(y);
        LASSERT(pit != -1, return 0);
-
-       Row const & row = getPitAndRowNearY(y, pit, assert_in_view, up);
+       
+       int yy = y; // is modified by getPitAndRowNearY
+       Row const & row = getPitAndRowNearY(yy, pit, assert_in_view, up);
        bool bound = false;
 
        int xx = x; // is modified by getColumnNearX
@@ -1462,7 +1500,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
@@ -1490,7 +1528,7 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
        }
 
        // 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();
@@ -1651,6 +1689,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) {
@@ -1844,7 +1891,7 @@ int TextMetrics::leftMargin(int max_width,
 
        if (par.getDepth() != 0) {
                // find the next level paragraph
-               pit_type newpar = outerHook(pit, pars);
+               pit_type newpar = text_->outerHook(pit);
                if (newpar != pit_type(pars.size())) {
                        if (pars[newpar].layout().isEnvironment()) {
                                l_margin = leftMargin(max_width, newpar);
@@ -1913,7 +1960,7 @@ int TextMetrics::leftMargin(int max_width,
                           // theorems (JMarc)
                           || (layout.labeltype == LABEL_STATIC
                               && layout.latextype == LATEX_ENVIRONMENT
-                              && !isFirstInSequence(pit, pars))) {
+                              && !text_->isFirstInSequence(pit))) {
                        l_margin += labelfont_metrics.signedWidth(layout.leftmargin);
                } else if (layout.labeltype != LABEL_TOP_ENVIRONMENT
                           && layout.labeltype != LABEL_BIBLIO
@@ -1962,7 +2009,7 @@ int TextMetrics::leftMargin(int max_width,
               || layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT
               || (layout.labeltype == LABEL_STATIC
                   && layout.latextype == LATEX_ENVIRONMENT
-                  && !isFirstInSequence(pit, pars)))
+                  && !text_->isFirstInSequence(pit)))
            && align == LYX_ALIGN_BLOCK
            && !par.params().noindent()
            // in some insets, paragraphs are never indented
@@ -2088,6 +2135,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) {
@@ -2127,11 +2187,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;