]> git.lyx.org Git - lyx.git/blobdiff - src/TextMetrics.cpp
Check path of Qt tools if qtchooser is detected
[lyx.git] / src / TextMetrics.cpp
index c10348d0d8ac6462316c7c5e898ca23aca7c9052..c7ccbac7fc2b9fea453c40c44f54d4ebb3a26e77 100644 (file)
@@ -48,6 +48,7 @@
 #include "support/debug.h"
 #include "support/lassert.h"
 
+#include <stdlib.h>
 #include <cmath>
 
 using namespace std;
@@ -472,12 +473,20 @@ bool TextMetrics::redoParagraph(pit_type const pit)
                pm.dim().des += row.height();
        } while (first < par.size() || need_new_row);
 
+       if (row_index < pm.rows().size())
+               pm.rows().resize(row_index);
+
        // FIXME: It might be better to move this in another method
        // specially tailored for the main text.
        // Top and bottom margin of the document (only at top-level)
        if (text_->isMainText()) {
                if (pit == 0) {
                        pm.rows().front().dimension().asc += 20;
+                       /* coverity[copy_paste_error]: coverity thinks that we
+                        * should update pm.dim().asc below, but all the rows
+                        * heights are actually counted as part of the paragraph metric
+                        * descent see loop above).
+                        */
                        pm.dim().des += 20;
                }
                ParagraphList const & pars = text_->paragraphs();
@@ -487,8 +496,12 @@ bool TextMetrics::redoParagraph(pit_type const pit)
                }
        }
 
-       if (row_index < pm.rows().size())
-               pm.rows().resize(row_index);
+       // The space above and below the paragraph.
+       int const top = parTopSpacing(pit);
+       pm.rows().front().dimension().asc += top;
+       int const bottom = parBottomSpacing(pit);
+       pm.rows().back().dimension().des += bottom;
+       pm.dim().des += top + bottom;
 
        pm.dim().asc += pm.rows()[0].ascent();
        pm.dim().des -= pm.rows()[0].ascent();
@@ -921,7 +934,7 @@ bool TextMetrics::breakRow(Row & row, int const right_margin) const
        // if the row is too large, try to cut at last separator. In case
        // of success, reset indication that the row was broken abruptly.
        if (row.shortenIfNeeded(body_pos, width))
-               row.right_boundary(false);
+               row.right_boundary(!row.empty() && row.back().endpos == row.endpos());
 
        // make sure that the RTL elements are in reverse ordering
        row.reverseRTL(is_rtl);
@@ -930,13 +943,109 @@ bool TextMetrics::breakRow(Row & row, int const right_margin) const
        return need_new_row;
 }
 
+int TextMetrics::parTopSpacing(pit_type const pit) const
+{
+       Paragraph const & par = text_->getPar(pit);
+       Layout const & layout = par.layout();
+
+       int asc = 0;
+       ParagraphList const & pars = text_->paragraphs();
+       double const dh = defaultRowHeight();
+
+       BufferParams const & bparams = bv_->buffer().params();
+       Inset const & inset = text_->inset();
+       // some parskips VERY EASY IMPLEMENTATION
+       if (bparams.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))) {
+               asc += bparams.getDefSkip().inPixels(*bv_);
+       }
+
+       if (par.params().startOfAppendix())
+               asc += int(3 * dh);
+
+       // special code for the top label
+       if (layout.labelIsAbove()
+           && (!layout.isParagraphGroup() || text_->isFirstInSequence(pit))
+           && !par.labelString().empty()) {
+               FontInfo labelfont = text_->labelFont(par);
+               FontMetrics const & lfm = theFontMetrics(labelfont);
+               asc += int(lfm.maxHeight() * layout.spacing.getValue()
+                                          * text_->spacing(par)
+                          + (layout.topsep + layout.labelbottomsep) * dh);
+       }
+
+       // Add the layout spaces, for example before and after
+       // a section, or between the items of a itemize or enumerate
+       // environment.
+
+       pit_type prev = text_->depthHook(pit, par.getDepth());
+       Paragraph const & prevpar = pars[prev];
+       double layoutasc = 0;
+       if (prev != pit
+           && prevpar.layout() == layout
+           && prevpar.getDepth() == par.getDepth()
+           && prevpar.getLabelWidthString() == par.getLabelWidthString()) {
+               layoutasc = layout.itemsep * dh;
+       } else if (pit != 0 && layout.topsep > 0)
+               layoutasc = layout.topsep * dh;
+
+       asc += int(layoutasc * 2 / (2 + pars[pit].getDepth()));
+
+       prev = text_->outerHook(pit);
+       if (prev != pit_type(pars.size())) {
+               asc += int(pars[prev].layout().parsep * dh);
+       } else if (pit != 0) {
+               Paragraph const & prevpar = pars[pit - 1];
+               if (prevpar.getDepth() != 0 || prevpar.layout() == layout)
+                       asc += int(layout.parsep * dh);
+       }
+
+       return asc;
+}
+
+
+int TextMetrics::parBottomSpacing(pit_type const pit) const
+{
+       double layoutdesc = 0;
+       ParagraphList const & pars = text_->paragraphs();
+       double const dh = defaultRowHeight();
+
+       // add the layout spaces, for example before and after
+       // a section, or between the items of a itemize or enumerate
+       // environment
+       pit_type nextpit = pit + 1;
+       if (nextpit != pit_type(pars.size())) {
+               pit_type cpit = pit;
+
+               if (pars[cpit].getDepth() > pars[nextpit].getDepth()) {
+                       double usual = pars[cpit].layout().bottomsep * dh;
+                       double unusual = 0;
+                       cpit = text_->depthHook(cpit, pars[nextpit].getDepth());
+                       if (pars[cpit].layout() != pars[nextpit].layout()
+                               || pars[nextpit].getLabelWidthString() != pars[cpit].getLabelWidthString())
+                               unusual = pars[cpit].layout().bottomsep * dh;
+                       layoutdesc = max(unusual, usual);
+               } else if (pars[cpit].getDepth() == pars[nextpit].getDepth()) {
+                       if (pars[cpit].layout() != pars[nextpit].layout()
+                               || pars[nextpit].getLabelWidthString() != pars[cpit].getLabelWidthString())
+                               layoutdesc = int(pars[cpit].layout().bottomsep * dh);
+               }
+       }
+
+       return int(layoutdesc * 2 / (2 + pars[pit].getDepth()));
+}
+
 
-void TextMetrics::setRowHeight(Row & row, bool topBottomSpace) const
+void TextMetrics::setRowHeight(Row & row) const
 {
        Paragraph const & par = text_->getPar(row.pit());
        Layout const & layout = par.layout();
-       double const spacing_val = layout.spacing.getValue()
-               * text_->spacing(par);
+       double const spacing_val = layout.spacing.getValue() * text_->spacing(par);
 
        // Initial value for ascent (useful if row is empty).
        Font const font = displayFont(row.pit(), row.pos());
@@ -962,103 +1071,7 @@ void TextMetrics::setRowHeight(Row & row, bool topBottomSpace) const
        ++maxasc;
        ++maxdes;
 
-       // Now use the layout information.
-       double layoutasc = 0;
-       double layoutdesc = 0;
-       int labeladdon = 0;
-       ParagraphList const & pars = text_->paragraphs();
-       Inset const & inset = text_->inset();
-       double const dh = defaultRowHeight();
-
-       // is it a top line?
-       if (row.pos() == 0 && topBottomSpace) {
-               BufferParams const & bufparams = bv_->buffer().params();
-               // some parskips VERY EASY IMPLEMENTATION
-               if (bufparams.paragraph_separation == BufferParams::ParagraphSkipSeparation
-                   && !inset.getLayout().parbreakIsNewline()
-                   && !par.layout().parbreak_is_newline
-                   && row.pit() > 0
-                   && ((layout.isParagraph() && par.getDepth() == 0)
-                           || (pars[row.pit() - 1].layout().isParagraph()
-                                   && pars[row.pit() - 1].getDepth() == 0))) {
-                       maxasc += bufparams.getDefSkip().inPixels(*bv_);
-               }
-
-               if (par.params().startOfAppendix())
-                       maxasc += int(3 * dh);
-
-               // special code for the top label
-               if (layout.labelIsAbove()
-                   && (!layout.isParagraphGroup() || text_->isFirstInSequence(row.pit()))
-                   && !par.labelString().empty()) {
-                       FontInfo labelfont = text_->labelFont(par);
-                       FontMetrics const & lfm = theFontMetrics(labelfont);
-                       labeladdon = int(
-                                 lfm.maxHeight()
-                                       * layout.spacing.getValue()
-                                       * text_->spacing(par)
-                               + (layout.topsep + layout.labelbottomsep) * dh);
-               }
-
-               // Add the layout spaces, for example before and after
-               // a section, or between the items of a itemize or enumerate
-               // environment.
-
-               pit_type prev = text_->depthHook(row.pit(), par.getDepth());
-               Paragraph const & prevpar = pars[prev];
-               if (prev != row.pit()
-                   && prevpar.layout() == layout
-                   && prevpar.getDepth() == par.getDepth()
-                   && prevpar.getLabelWidthString()
-                                       == par.getLabelWidthString()) {
-                       layoutasc = layout.itemsep * dh;
-               } else if (row.pit() != 0 || row.pos() != 0) {
-                       if (layout.topsep > 0)
-                               layoutasc = layout.topsep * dh;
-               }
-
-               prev = text_->outerHook(row.pit());
-               if (prev != pit_type(pars.size())) {
-                       maxasc += int(pars[prev].layout().parsep * dh);
-               } else if (row.pit() != 0) {
-                       Paragraph const & prevpar = pars[row.pit() - 1];
-                       if (prevpar.getDepth() != 0 ||
-                                       prevpar.layout() == layout) {
-                               maxasc += int(layout.parsep * dh);
-                       }
-               }
-       }
-
-       // is it a bottom line?
-       if (row.endpos() >= par.size() && topBottomSpace) {
-               // add the layout spaces, for example before and after
-               // a section, or between the items of a itemize or enumerate
-               // environment
-               pit_type nextpit = row.pit() + 1;
-               if (nextpit != pit_type(pars.size())) {
-                       pit_type cpit = row.pit();
-
-                       if (pars[cpit].getDepth() > pars[nextpit].getDepth()) {
-                               double usual = pars[cpit].layout().bottomsep * dh;
-                               double unusual = 0;
-                               cpit = text_->depthHook(cpit, pars[nextpit].getDepth());
-                               if (pars[cpit].layout() != pars[nextpit].layout()
-                                   || pars[nextpit].getLabelWidthString() != pars[cpit].getLabelWidthString())
-                                       unusual = pars[cpit].layout().bottomsep * dh;
-                               layoutdesc = max(unusual, usual);
-                       } else if (pars[cpit].getDepth() == pars[nextpit].getDepth()) {
-                               if (pars[cpit].layout() != pars[nextpit].layout()
-                                       || pars[nextpit].getLabelWidthString() != pars[cpit].getLabelWidthString())
-                                       layoutdesc = int(pars[cpit].layout().bottomsep * dh);
-                       }
-               }
-       }
-
-       // incalculate the layout spaces
-       maxasc += int(layoutasc  * 2 / (2 + pars[row.pit()].getDepth()));
-       maxdes += int(layoutdesc * 2 / (2 + pars[row.pit()].getDepth()));
-
-       row.dimension().asc = maxasc + labeladdon;
+       row.dimension().asc = maxasc;
        row.dimension().des = maxdes;
 }
 
@@ -1850,7 +1863,6 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
                return;
        }
 
-       BufferParams const & bparams = bv_->buffer().params();
        int const ww = bv_->workHeight();
        Cursor const & cur = bv_->cursor();
        DocIterator sel_beg = cur.selectionBegin();
@@ -1916,7 +1928,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
                }
 
                // Row signature; has row changed since last paint?
-               row.setCrc(pm.computeRowSignature(row, bparams));
+               row.setCrc(pm.computeRowSignature(row, *bv_));
                bool row_has_changed = row.changed()
                        || bv_->hadHorizScrollOffset(text_, pit, row.pos());
 
@@ -2001,18 +2013,19 @@ void TextMetrics::completionPosAndDim(Cursor const & cur, int & x, int & y,
        DocIterator wordStart = bvcur;
        wordStart.pos() -= word.length();
 
-       // get position on screen of the word start and end
-       //FIXME: Is it necessary to explicitly set this to false?
-       wordStart.boundary(false);
-       Point lxy = cur.bv().getPos(wordStart);
-       Point rxy = cur.bv().getPos(bvcur);
-
        // calculate dimensions of the word
        Row row;
+       row.pit(bvcur.pit());
        row.pos(wordStart.pos());
        row.endpos(bvcur.pos());
-       setRowHeight(row, false);
+       setRowHeight(row);
        dim = row.dimension();
+
+       // get position on screen of the word start and end
+       //FIXME: Is it necessary to explicitly set this to false?
+       wordStart.boundary(false);
+       Point lxy = cur.bv().getPos(wordStart);
+       Point rxy = cur.bv().getPos(bvcur);
        dim.wid = abs(rxy.x_ - lxy.x_);
 
        // calculate position of word