]> git.lyx.org Git - lyx.git/blobdiff - src/TextMetrics.cpp
Fix scale parameter for fonts.
[lyx.git] / src / TextMetrics.cpp
index 4e70dc0b82091b5b207a45e49d8f3c43d648796d..1b434a503c75a9951abf42542af3080c57adff28 100644 (file)
@@ -234,7 +234,7 @@ 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);
 }
 
 
@@ -346,19 +346,20 @@ 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.isEnvSeparator(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;
 }
 
@@ -581,7 +582,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;
@@ -628,6 +629,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
                        if (ns
                            && row.endpos() < par.size()
                            && !par.isNewline(row.endpos() - 1)
+                           && !par.isEnvSeparator(row.endpos() - 1)
                            && !disp_inset
                                ) {
                                row.separator = w / ns;
@@ -693,13 +695,13 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const
        Paragraph const & par = text_->getPar(pit);
 
        pos_type last = par.beginOfBody();
-       LBUFERR(last > 0);
+       LBUFERR(last > 0 || par.isEnvSeparator(0));
 
        // -1 because a label ends with a space that is in the label
        --last;
 
        // a separator at this end does not count
-       if (par.isLineSeparator(last))
+       if (last >= 0 && par.isLineSeparator(last))
                --last;
 
        int w = 0;
@@ -718,7 +720,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const
 
 
 #if 0
-// Not used, see TextMetrics::rowBreakPoint. 
+// 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)
 {
@@ -812,7 +814,7 @@ 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 
+       //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)
@@ -853,10 +855,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;
@@ -897,7 +899,7 @@ pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit,
                        break;
                }
 
-               if (par.isNewline(i)) {
+               if (par.isNewline(i) || par.isEnvSeparator(i)) {
                        point = i + 1;
                        break;
                }
@@ -973,8 +975,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())
@@ -1152,11 +1154,10 @@ Dimension TextMetrics::rowHeight(pit_type const pit, pos_type const first,
                pit_type nextpit = pit + 1;
                if (nextpit != pit_type(pars.size())) {
                        pit_type cpit = pit;
-                       double usual = 0;
-                       double unusual = 0;
 
                        if (pars[cpit].getDepth() > pars[nextpit].getDepth()) {
-                               usual = pars[cpit].layout().bottomsep * dh;
+                               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())
@@ -1240,13 +1241,6 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
        // the value of rtl.
        bool const rtl_on_lastrow = 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. Only
-       // in freespacing paragraphs, this first character is painted.
-       if (!par.isFreeSpacing() && par.isSeparator(bidi.vis2log(vc)))
-               ++vc;
-
        while (vc < end && tmpx <= x) {
                c = bidi.vis2log(vc);
                last_tmpx = tmpx;
@@ -1277,7 +1271,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
        if (lastrow &&
            ((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))
+               if (!(par.isNewline(end - 1) || par.isEnvSeparator(end - 1)))
                        c = end;
        } else if (vc == row.pos()) {
                c = bidi.vis2log(vc);
@@ -1326,7 +1320,9 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
        if (!c || end == par.size())
                return col;
 
-       if (c==end && !par.isLineSeparator(c-1) && !par.isNewline(c-1)) {
+       if (c==end && !par.isLineSeparator(c-1)
+                  && !par.isNewline(c-1)
+                  && !par.isEnvSeparator(c-1)) {
                boundary = true;
                return col;
        }
@@ -1495,45 +1491,34 @@ 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);
 
-       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);
        cur.pit() = pit;
-       cur.pos() = pos;
-       cur.boundary(bound);
-       cur.setTargetX(x);
 
-       // try to descend into nested insets
-       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?
+       // Do we cover an inset?
+       InsetList::InsetTable * it = checkInsetHit(pit, x, yy);
+
+       if (!it) {
+               // No inset, set position in the text
+               bool bound = false; // is modified by getColumnNearX
+               int xx = x; // is modified by getColumnNearX
+               cur.pos() = row.pos()
+                       + getColumnNearX(pit, row, xx, bound);
+               cur.boundary(bound);
                cur.setCurrentFont();
+               cur.setTargetX(xx);
                return 0;
        }
 
-       ParagraphList const & pars = text_->paragraphs();
-       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(inset == inset_before 
-               || inset == pars[pit].getInset(pos), return 0);
-
-       // Make sure the cursor points to the position before
-       // this inset.
-       if (inset == inset_before) {
-               --cur.pos();
-               cur.boundary(false);
-       }
+       Inset * inset = it->inset;
+       //lyxerr << "inset " << inset << " hit at x: " << x << " y: " << y << endl;
+
+       // Set position in front of inset
+       cur.pos() = it->pos;
+       cur.boundary(false);
+       cur.setTargetX(x);
 
        // Try to descend recursively inside the inset.
        inset = inset->editXY(cur, x, yy);
@@ -1582,11 +1567,8 @@ void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const
 
 
 //takes screen x,y coordinates
-Inset * TextMetrics::checkInsetHit(int x, int y)
+InsetList::InsetTable * TextMetrics::checkInsetHit(pit_type pit, int x, int y)
 {
-       pit_type pit = getPitNearY(y);
-       LASSERT(pit != -1, return 0);
-
        Paragraph const & par = text_->paragraphs()[pit];
        ParagraphMetrics const & pm = par_metrics_[pit];
 
@@ -1615,7 +1597,7 @@ Inset * TextMetrics::checkInsetHit(int x, int y)
                        && y >= p.y_ - dim.asc
                        && y <= p.y_ + dim.des) {
                        LYXERR(Debug::DEBUG, "Hit inset: " << inset);
-                       return inset;
+                       return const_cast<InsetList::InsetTable *>(&(*iit));
                }
        }
 
@@ -1624,6 +1606,20 @@ Inset * TextMetrics::checkInsetHit(int x, int y)
 }
 
 
+//takes screen x,y coordinates
+Inset * TextMetrics::checkInsetHit(int x, int y)
+{
+       pit_type const pit = getPitNearY(y);
+       LASSERT(pit != -1, return 0);
+       InsetList::InsetTable * it = checkInsetHit(pit, x, y);
+
+       if (!it)
+               return 0;
+
+       return it->inset;
+}
+
+
 int TextMetrics::cursorX(CursorSlice const & sl,
                bool boundary) const
 {
@@ -1822,7 +1818,8 @@ bool TextMetrics::cursorEnd(Cursor & cur)
        bool boundary = false;
        if (end != cur.lastpos()) {
                if (!cur.paragraph().isLineSeparator(end-1)
-                   && !cur.paragraph().isNewline(end-1))
+                   && !cur.paragraph().isNewline(end-1)
+                   && !cur.paragraph().isEnvSeparator(end-1))
                        boundary = true;
                else
                        --end;
@@ -1903,6 +1900,15 @@ int TextMetrics::leftMargin(int max_width,
                if (newpar != pit_type(pars.size())) {
                        if (pars[newpar].layout().isEnvironment()) {
                                l_margin = leftMargin(max_width, newpar);
+                               // Remove the parindent that has been added
+                               // if the paragraph was empty.
+                               if (pars[newpar].empty() &&
+                                   buffer.params().paragraph_separation ==
+                                   BufferParams::ParagraphIndentSeparation) {
+                                       docstring pi = pars[newpar].layout().parindent;
+                                       l_margin -= theFontMetrics(
+                                               buffer.params().getFont()).signedWidth(pi);
+                               }
                        }
                        if (tclass.isDefaultLayout(par.layout())
                            || tclass.isPlainLayout(par.layout())) {
@@ -1914,12 +1920,20 @@ int TextMetrics::leftMargin(int max_width,
                }
        }
 
-       // This happens after sections in standard classes. The 1.3.x
-       // code compared depths too, but it does not seem necessary
-       // (JMarc)
-       if (tclass.isDefaultLayout(par.layout())
-           && pit > 0 && pars[pit - 1].layout().nextnoindent)
+       // This happens after sections or environments in standard classes.
+       // We have to check the previous layout at same depth.
+       if (buffer.params().paragraph_separation ==
+                       BufferParams::ParagraphSkipSeparation)
                parindent.erase();
+       else if (pit > 0 && pars[pit - 1].getDepth() >= par.getDepth()) {
+               pit_type prev = text_->depthHook(pit, par.getDepth());
+               if (par.layout() == pars[prev].layout()) {
+                       if (prev != pit - 1
+                           && pars[pit - 1].layout().nextnoindent)
+                               parindent.erase();
+               } else if (pars[prev].layout().nextnoindent)
+                       parindent.erase();
+       }
 
        FontInfo const labelfont = text_->labelFont(par);
        FontMetrics const & labelfont_metrics = theFontMetrics(labelfont);
@@ -1982,7 +1996,7 @@ int TextMetrics::leftMargin(int max_width,
                // 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. 
+               // the rows.
                ParagraphMetrics const & pm = par_metrics_[pit];
                RowList::const_iterator rit = pm.rows().begin();
                RowList::const_iterator end = pm.rows().end();
@@ -2027,7 +2041,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)
            )
                {
@@ -2039,7 +2053,7 @@ int TextMetrics::leftMargin(int max_width,
                        else
                                l_margin += buffer.params().getIndentation().inPixels(*bv_);
                }
-       
+
        return l_margin;
 }
 
@@ -2100,7 +2114,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()) {
@@ -2129,7 +2143,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()) {
@@ -2164,7 +2178,7 @@ 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);
                }
-               
+
                // Instrumentation for testing row cache (see also
                // 12 lines lower):
                if (lyxerr.debugging(Debug::PAINTING) && inside