X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FTextMetrics.cpp;h=874cb17607f716e9551e53720237300f57c1f699;hb=449c766e03d94ddf6c823cfcae845f76f83c0e1c;hp=d4a7f56de3ba1320923e4f5e934b88c0b19255ad;hpb=f215bb3b926d8b7d9240f0f08793fc3d731d5398;p=lyx.git diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index d4a7f56de3..874cb17607 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -15,13 +15,10 @@ * Full author contact details are available in file CREDITS. */ -//#define KEEP_OLD_METRICS_CODE 1 - #include #include "TextMetrics.h" -#include "Bidi.h" #include "Buffer.h" #include "buffer_funcs.h" #include "BufferParams.h" @@ -35,7 +32,7 @@ #include "LyXRC.h" #include "MetricsInfo.h" #include "ParagraphParameters.h" -#include "rowpainter.h" +#include "RowPainter.h" #include "Text.h" #include "TextClass.h" #include "VSpace.h" @@ -293,7 +290,7 @@ Font TextMetrics::displayFont(pit_type pit, pos_type pos) const bool TextMetrics::isRTL(CursorSlice const & sl, bool boundary) const { - if (!lyxrc.rtl_support || !sl.text()) + if (!sl.text()) return false; int correction = 0; @@ -307,7 +304,7 @@ bool TextMetrics::isRTL(CursorSlice const & sl, bool boundary) const bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos) const { // no RTL boundary at paragraph start - if (!lyxrc.rtl_support || pos == 0) + if (pos == 0) return false; Font const & left_font = displayFont(pit, pos - 1); @@ -322,9 +319,8 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos) const bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos, Font const & font) const { - if (!lyxrc.rtl_support - // no RTL boundary at paragraph start - || pos == 0 + if (// no RTL boundary at paragraph start + pos == 0 // if the metrics have not been calculated, then we are not // on screen and can safely ignore issues about boundaries. || !contains(pit)) @@ -349,6 +345,7 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos, // FED FED| FED ) 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; @@ -509,11 +506,11 @@ bool TextMetrics::redoParagraph(pit_type const pit) } -int TextMetrics::getAlign(Paragraph const & par, pos_type const pos) const +LyXAlignment TextMetrics::getAlign(Paragraph const & par, pos_type const pos) const { Layout const & layout = par.layout(); - int align; + LyXAlignment align; if (par.params().align() == LYX_ALIGN_LAYOUT) align = layout.align; else @@ -568,19 +565,15 @@ void TextMetrics::computeRowMetrics(pit_type const pit, Paragraph const & par = text_->getPar(pit); - double w = width - row.width(); + double const w = width - row.right_margin - row.width(); // FIXME: put back this assertion when the crash on new doc is solved. //LASSERT(w >= 0, /**/); - //lyxerr << "\ndim_.wid " << dim_.wid << endl; - //lyxerr << "row.width() " << row.width() << endl; - //lyxerr << "w " << w << endl; - bool const is_rtl = text_->isRTL(par); if (is_rtl) - row.x = rightMargin(pit); + row.left_margin = rightMargin(pit); else - row.x = leftMargin(max_width_, pit, row.pos()); + row.left_margin = leftMargin(max_width_, pit, row.pos()); // is there a manual margin with a manual label Layout const & layout = par.layout(); @@ -614,69 +607,51 @@ void TextMetrics::computeRowMetrics(pit_type const pit, } else if (int(row.width()) < max_width_) { // is it block, flushleft or flushright? // set x how you need it - int const align = getAlign(par, row.pos()); - - switch (align) { + switch (getAlign(par, row.pos())) { case LYX_ALIGN_BLOCK: { int const ns = numberOfSeparators(row); - bool disp_inset = false; - if (row.endpos() < par.size()) { - Inset const * in = par.getInset(row.endpos()); - if (in) - disp_inset = in->display(); - } - // If we have separators, this is not the last row of a - // par, does not end in newline, and is not row above a - // display inset... then stretch it - if (ns && row.endpos() < par.size() - && !par.isNewline(row.endpos() - 1) - && !disp_inset) { + /** If we have separators, and this row has + * not be broken abruptly by a display inset + * or newline, then stretch it */ + if (ns && !row.right_boundary() + && row.endpos() != par.size()) { setSeparatorWidth(row, w / ns); row.dimension().wid = width; - //lyxerr << "row.separator " << row.separator << endl; - //lyxerr << "ns " << ns << endl; } else if (is_rtl) { - row.x += w; + row.dimension().wid = width; + row.left_margin += w; } break; } case LYX_ALIGN_RIGHT: - row.x += w; + row.left_margin += w; break; case LYX_ALIGN_CENTER: - row.x += w / 2; + row.dimension().wid = width - int(w / 2); + row.left_margin += w / 2; + break; + case LYX_ALIGN_LEFT: + case LYX_ALIGN_NONE: + case LYX_ALIGN_LAYOUT: + case LYX_ALIGN_SPECIAL: + case LYX_ALIGN_DECIMAL: break; } } -#if 0 - if (is_rtl) { - pos_type body_pos = par.beginOfBody(); - pos_type end = row.endpos(); - - if (body_pos > 0 - && (body_pos > end || !par.isLineSeparator(body_pos - 1))) { - row.x += theFontMetrics(text_->labelFont(par)). - width(layout.labelsep); - if (body_pos <= end) - row.x += row.label_hfill; - } - } -#endif - + // Finally, handle hfill insets pos_type const endpos = row.endpos(); pos_type body_pos = par.beginOfBody(); if (body_pos > 0 && (body_pos > endpos || !par.isLineSeparator(body_pos - 1))) body_pos = 0; - ParagraphMetrics & pm = par_metrics_[pit]; Row::iterator cit = row.begin(); Row::iterator const cend = row.end(); for ( ; cit != cend; ++cit) { if (row.label_hfill && cit->endpos == body_pos && cit->type == Row::SPACE) - cit->dim.wid -= row.label_hfill * (nlh - 1); + cit->dim.wid -= int(row.label_hfill * (nlh - 1)); if (!cit->inset || !cit->inset->isHfill()) continue; if (pm.hfillExpansion(row, cit->pos)) @@ -694,7 +669,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit, int TextMetrics::labelFill(pit_type const pit, Row const & row) const { Paragraph const & par = text_->getPar(pit); - LBUFERR(par.beginOfBody() > 0); + LBUFERR(par.beginOfBody() > 0 || par.isEnvSeparator(0)); int w = 0; Row::const_iterator cit = row.begin(); @@ -702,7 +677,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const // iterate over elements before main body (except the last one, // which is extra space). while (cit!= end && cit->endpos < par.beginOfBody()) { - w += cit->width(); + w += cit->dim.wid; ++cit; } @@ -800,6 +775,10 @@ private: } // anon namespace +/** This is the function where the hard work is done. The code here is + * very sensitive to small changes :) Note that part of the + * intelligence is also in Row::shorten_if_needed + */ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit) const { Paragraph const & par = text_->getPar(pit); @@ -808,11 +787,12 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit int const width = max_width_ - right_margin; pos_type const body_pos = par.beginOfBody(); row.clear(); - row.dimension().wid = leftMargin(max_width_, pit, pos); + // This make get changed in computeRowMetrics depending on RTL + row.left_margin = leftMargin(max_width_, pit, pos); + row.dimension().wid = row.left_margin; row.right_margin = right_margin; if (pos >= end || row.width() > width) { - row.dimension().wid += right_margin; row.endpos(end); return; } @@ -849,6 +829,17 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit Inset const * ins = par.getInset(i); Dimension dim = pm.insetDimension(ins); row.add(i, ins, dim, *fi, par.lookupChange(i)); + } else if (c == ' ' && i + 1 == body_pos) { + // There is a space at i, but it should not be + // added as a separator, because it is just + // before body_pos. Instead, insert some spacing to + // align text + FontMetrics const & fm = theFontMetrics(text_->labelFont(par)); + // this is needed to make sure that the row width is correct + row.finalizeLast(); + int const add = max(fm.width(par.layout().labelsep), + labelEnd(pit) - row.width()); + row.addSpace(i, add, *fi, par.lookupChange(i)); } else if (par.isLineSeparator(i)) { // In theory, no inset has this property. If // this is done, a new addSeparator which @@ -862,15 +853,6 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit else row.add(i, c, *fi, par.lookupChange(i)); - // end of paragraph marker - if (lyxrc.paragraph_markers - && i == end - 1 && size_type(pit + 1) < pars.size()) { - // enlarge the last character to hold the end-of-par marker - Font f(text_->layoutFont(pit)); - f.fontInfo().setColor(Color_paragraphmarker); - row.addVirtual(i, docstring(1, char_type(0x00B6)), f, Change()); - } - // add inline completion width if (inlineCompletionLPos == i && !bv_->inlineCompletion().empty()) { @@ -885,39 +867,38 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit // - Before a display inset // - After a display inset Inset const * inset = 0; - if (par.isNewline(i) + if (par.isNewline(i) || par.isEnvSeparator(i) || (i + 1 < end && (inset = par.getInset(i + 1)) && inset->display()) || (!row.empty() && row.back().inset && row.back().inset->display())) { + row.right_boundary(true); ++i; break; } ++i; ++fi; - - // add the auto-hfill from label end to the body - if (body_pos && i == body_pos) { - FontMetrics const & fm = theFontMetrics(text_->labelFont(par)); - pos_type j = i; - if (!row.empty() - && row.back().type == Row::SEPARATOR) { - row.pop_back(); - --j; - } - int const add = max(fm.width(par.layout().labelsep), - labelEnd(pit) - row.width()); - row.addSpace(j, add, *fi, par.lookupChange(i)); - } - } - row.finalizeLast(); row.endpos(i); + + // End of paragraph marker + if (lyxrc.paragraph_markers + && i == end && size_type(pit + 1) < pars.size()) { + // add a virtual element for the end-of-paragraph + // marker; it is shown on screen, but does not exist + // in the paragraph. + Font f(text_->layoutFont(pit)); + f.fontInfo().setColor(Color_paragraphmarker); + BufferParams const & bparams + = text_->inset().buffer().params(); + f.setLanguage(par.getParLanguage(bparams)); + row.addVirtual(end, docstring(1, char_type(0x00B6)), f, Change()); + } + // if the row is too large, try to cut at last separator. - if (row.width() >= width) - row.separate_back(body_pos); + row.shortenIfNeeded(body_pos, width); // if the row ends with a separator that is not at end of // paragraph, remove it @@ -925,10 +906,8 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit && row.endpos() < par.size()) row.pop_back(); - // make sure that the RtL elements are in reverse ordering - row.reverseRtL(); - - row.dimension().wid += right_margin; + // make sure that the RTL elements are in reverse ordering + row.reverseRTL(text_->isRTL(par)); } @@ -1111,169 +1090,65 @@ void TextMetrics::setRowHeight(Row & row, pit_type const pit, // x is an absolute screen coord // returns the column near the specified x-coordinate of the row // x is set to the real beginning of this column -pos_type TextMetrics::getColumnNearX(pit_type const pit, - Row const & row, int & x, bool & boundary) const +pos_type TextMetrics::getPosNearX(Row const & row, int & x, + bool & boundary) const { - // FIXME: handle properly boundary (not done now) + /// For the main Text, it is possible that this pit is not + /// yet in the CoordCache when moving cursor up. + /// x Paragraph coordinate is always 0 for main text anyway. + int const xo = origin_.x_; + x -= xo; + pos_type pos = row.pos(); - if (row.x >= x || row.empty()) - x = row.x; - else if (x >= row.width() - row.right_margin) { - x = row.width() - row.right_margin; - pos = row.back().endpos; + boundary = false; + if (row.empty()) + x = row.left_margin; + else if (x <= row.left_margin) { + pos = row.front().left_pos(); + x = row.left_margin; + } else if (x >= row.width()) { + pos = row.back().right_pos(); + x = row.width(); } else { - double w = row.x; + double w = row.left_margin; Row::const_iterator cit = row.begin(); Row::const_iterator cend = row.end(); for ( ; cit != cend; ++cit) { - if (w <= x && w + cit->width() > x) { - double x_offset = x - w; + if (w <= x && w + cit->full_width() > x) { + int x_offset = int(x - w); pos = cit->x2pos(x_offset); - x = x_offset + w; + x = int(x_offset + w); break; } - w += cit->width(); - } - if (cit == row.end()) - lyxerr << "NOT FOUND!! x=" << x << ", wid=" << row.width() << endl; - } - -#if !defined(KEEP_OLD_METRICS_CODE) - return pos - row.pos(); -#else - Buffer const & buffer = bv_->buffer(); - - /// For the main Text, it is possible that this pit is not - /// yet in the CoordCache when moving cursor up. - /// x Paragraph coordinate is always 0 for main text anyway. - int const xo = origin_.x_; - int x2 = x - xo; - Paragraph const & par = text_->getPar(pit); - Bidi bidi; - bidi.computeTables(par, buffer, row); - - pos_type vc = row.pos(); - pos_type const end = row.endpos(); - pos_type c = 0; - Layout const & layout = par.layout(); - - bool left_side = false; - - pos_type body_pos = par.beginOfBody(); - - double tmpx = row.x; - double last_tmpx = tmpx; - - if (body_pos > 0 && - (body_pos > end || !par.isLineSeparator(body_pos - 1))) - body_pos = 0; - - // check for empty row - if (vc == end) { - x2 = int(tmpx) + xo; - return 0; - } - - // This (rtl_support test) is not needed, but gives - // some speedup if rtl_support == false - bool const lastrow = lyxrc.rtl_support && row.endpos() == par.size(); - - // If lastrow is false, we don't need to compute - // the value of rtl. - bool const rtl_on_lastrow = lastrow ? text_->isRTL(par) : false; - - while (vc < end && tmpx <= x2) { - c = bidi.vis2log(vc); - last_tmpx = tmpx; - if (body_pos > 0 && c == body_pos - 1) { - FontMetrics const & fm = theFontMetrics( - text_->labelFont(par)); - tmpx += row.label_hfill + fm.width(layout.labelsep); - if (par.isLineSeparator(body_pos - 1)) - tmpx -= singleWidth(pit, body_pos - 1); + w += cit->full_width(); } - - tmpx += singleWidth(pit, c); - if (par.isSeparator(c) && c >= body_pos) - tmpx += row.separator; - ++vc; - } - - if ((tmpx + last_tmpx) / 2 > x2) { - tmpx = last_tmpx; - left_side = true; - } - - // This shouldn't happen. But we can reset and try to continue. - LASSERT(vc <= end, vc = end); - - bool boundary2 = false; - - if (lastrow && - ((rtl_on_lastrow && left_side && vc == row.pos() && x2 < tmpx - 5) || - (!rtl_on_lastrow && !left_side && vc == end && x2 > tmpx + 5))) { - if (!par.isNewline(end - 1)) - c = end; - } else if (vc == row.pos()) { - c = bidi.vis2log(vc); - if (bidi.level(c) % 2 == 1) - ++c; - } else { - c = bidi.vis2log(vc - 1); - bool const rtl = (bidi.level(c) % 2 == 1); - if (left_side == rtl) { - ++c; - boundary2 = isRTLBoundary(pit, c); + if (cit == row.end()) { + pos = row.back().right_pos(); + x = row.width(); } + /** This tests for the case where the cursor is placed + * just before a font direction change. See comment on + * the boundary_ member in DocIterator.h to understand + * how boundary helps here. + */ + else if (pos == cit->endpos + && cit + 1 != row.end() + && cit->font.isVisibleRightToLeft() != (cit + 1)->font.isVisibleRightToLeft()) + boundary = true; } -// I believe this code is not needed anymore (Jug 20050717) -#if 0 - // The following code is necessary because the cursor position past - // the last char in a row is logically equivalent to that before - // the first char in the next row. That's why insets causing row - // divisions -- Newline and display-style insets -- must be treated - // specially, so cursor up/down doesn't get stuck in an air gap -- MV - // Newline inset, air gap below: - if (row.pos() < end && c >= end && par.isNewline(end - 1)) { - if (bidi.level(end -1) % 2 == 0) - tmpx -= singleWidth(pit, end - 1); - else - tmpx += singleWidth(pit, end - 1); - c = end - 1; - } - - // Air gap above display inset: - if (row.pos() < end && c >= end && end < par.size() - && par.isInset(end) && par.getInset(end)->display()) { - c = end - 1; - } - // Air gap below display inset: - if (row.pos() < end && c >= end && par.isInset(end - 1) - && par.getInset(end - 1)->display()) { - c = end - 1; - } -#endif - - x2 = int(tmpx) + xo; - pos_type const col = c - row.pos(); - - if (abs(x2 - x) > 0.1 || boundary != boundary - || c != pos) { - lyxerr << "new=(x=" << x << ", b=" << boundary << ", p=" << pos << "), " - << "old=(x=" << x2 << ", b=" << boundary2 << ", p=" << c << "), " << row; - } - - if (!c || end == par.size()) - return col; - - if (c==end && !par.isLineSeparator(c-1) && !par.isNewline(c-1)) { - boundary2 = true; - return col; - } - - return min(col, end - 1 - row.pos()); -#endif + /** This tests for the case where the cursor is set at the end + * of a row which has been broken due something else than a + * separator (a display inset or a forced breaking of the + * row). We know that there is a separator when the end of the + * row is larger than the end of its last element. + */ + if (!row.empty() && pos == row.back().endpos + && row.back().endpos == row.endpos()) + boundary = true; + + x += xo; + return pos; } @@ -1288,7 +1163,7 @@ pos_type TextMetrics::x2pos(pit_type pit, int row, int x) const LBUFERR(row < int(pm.rows().size())); bool bound = false; Row const & r = pm.rows()[row]; - return r.pos() + getColumnNearX(pit, r, x, bound); + return getPosNearX(r, x, bound); } @@ -1448,10 +1323,9 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y, 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); + bool bound = false; // is modified by getPosNearX + int xx = x; // is modified by getPosNearX + cur.pos() = getPosNearX(row, xx, bound); cur.boundary(bound); cur.setCurrentFont(); cur.setTargetX(xx); @@ -1502,7 +1376,7 @@ void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const bool bound = false; int xx = x; - pos_type const pos = row.pos() + getColumnNearX(pit, row, xx, bound); + pos_type const pos = getPosNearX(row, xx, bound); LYXERR(Debug::DEBUG, "setting cursor pit: " << pit << " pos: " << pos); @@ -1568,196 +1442,52 @@ int TextMetrics::cursorX(CursorSlice const & sl, bool boundary) const { LASSERT(sl.text() == text_, return 0); - pit_type const pit = sl.pit(); - pos_type pos = sl.pos(); - ParagraphMetrics const & pm = par_metrics_[pit]; + ParagraphMetrics const & pm = par_metrics_[sl.pit()]; if (pm.rows().empty()) return 0; Row const & row = pm.getRow(sl.pos(), boundary); - - double x = row.x; + pos_type const pos = sl.pos(); /** - * When boundary is true, position is on the row element (pos, endpos) + * When boundary is true, position i is in the row element (pos, endpos) * if - * pos < pos <= endpos + * pos < i <= endpos * whereas, when boundary is false, the test is - * pos <= pos < endpos + * pos <= i < endpos * The correction below allows to handle both cases. */ int const boundary_corr = (boundary && pos) ? -1 : 0; + /** Early return in trivial cases + * 1) the row is empty + * 2) the position is the left-most position of the row; there + * is a quirck herehowever: if the first element is virtual + * (end-of-par marker for example), then we have to look + * closer + */ if (row.empty() - || (row.begin()->font.isRightToLeft() - && pos == row.begin()->endpos)) - return int(x); + || (pos == row.begin()->left_pos() + && pos != row.begin()->right_pos())) + return row.left_margin; Row::const_iterator cit = row.begin(); + double x = row.left_margin; for ( ; cit != row.end() ; ++cit) { + /** Look whether the cursor is inside the element's + * span. Note that it is necessary to take the + * boundary in account, and to accept virtual + * elements, which have pos == endpos. + */ if (pos + boundary_corr >= cit->pos - && pos + boundary_corr < cit->endpos) { + && (pos + boundary_corr < cit->endpos + || cit->pos == cit->endpos)) { x += cit->pos2x(pos); break; } - x += cit->width(); + x += cit->full_width(); } - if (cit == row.end() - && (row.back().font.isRightToLeft() || pos != row.back().endpos)) - lyxerr << "NOT FOUND!" - << "pos=" << pos << "(" << boundary_corr << ")" << "\n" - << row; - -#ifdef KEEP_OLD_METRICS_CODE - Paragraph const & par = text_->paragraphs()[pit]; - - // Correct position in front of big insets - bool const boundary_correction = pos != 0 && boundary; - if (boundary_correction) - --pos; - - pos_type cursor_vpos = 0; - - Buffer const & buffer = bv_->buffer(); - double x2 = row.x; - Bidi bidi; - bidi.computeTables(par, buffer, row); - - pos_type const row_pos = row.pos(); - pos_type const end = row.endpos(); - // Spaces at logical line breaks in bidi text must be skipped during - // cursor positioning. However, they may appear visually in the middle - // of a row; they must be skipped, wherever they are... - // * logically "abc_[HEBREW_\nHEBREW]" - // * visually "abc_[_WERBEH\nWERBEH]" - pos_type skipped_sep_vpos = -1; - - if (end <= row_pos) - cursor_vpos = row_pos; - else if (pos >= end) - cursor_vpos = text_->isRTL(par) ? row_pos : end; - else if (pos > row_pos && pos >= 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(pos - 1) % 2 == 0) - ? bidi.log2vis(pos - 1) + 1 : bidi.log2vis(pos - 1); - else - // Place cursor before char at (logical) position pos - cursor_vpos = (bidi.level(pos) % 2 == 0) - ? bidi.log2vis(pos) : bidi.log2vis(pos) + 1; - - pos_type body_pos = par.beginOfBody(); - if (body_pos > 0 && - (body_pos > end || !par.isLineSeparator(body_pos - 1))) - body_pos = 0; - - // check for possible inline completion in this row - DocIterator const & inlineCompletionPos = bv_->inlineCompletionPos(); - pos_type inlineCompletionVPos = -1; - if (inlineCompletionPos.inTexted() - && inlineCompletionPos.text() == text_ - && inlineCompletionPos.pit() == pit - && inlineCompletionPos.pos() - 1 >= row_pos - && inlineCompletionPos.pos() - 1 < end) { - // draw logically behind the previous character - inlineCompletionVPos = bidi.log2vis(inlineCompletionPos.pos() - 1); - } - - // Use font span to speed things up, see below - FontSpan font_span; - Font font; - - // If the last logical character is a separator, skip it, unless - // it's in the last row of a paragraph; see skipped_sep_vpos declaration - 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)); - x2 += 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) { - font = displayFont(pit, row_pos + 1); - docstring const & completion = bv_->inlineCompletion(); - if (font.isRightToLeft() && completion.length() > 0) - x2 += theFontMetrics(font.fontInfo()).width(completion); - } - - for (pos_type vpos = row_pos; vpos < cursor_vpos; ++vpos) { - // Skip the separator which is at the logical end of the row - if (vpos == skipped_sep_vpos) - continue; - pos_type pos = bidi.vis2log(vpos); - if (body_pos > 0 && pos == body_pos - 1) { - FontMetrics const & labelfm = theFontMetrics( - text_->labelFont(par)); - x2 += row.label_hfill + labelfm.width(par.layout().labelsep); - if (par.isLineSeparator(body_pos - 1)) - x2 -= singleWidth(pit, body_pos - 1); - } - - // Use font span to speed things up, see above - if (pos < font_span.first || pos > font_span.last) { - font_span = par.fontSpan(pos); - font = displayFont(pit, pos); - } - - x2 += pm.singleWidth(pos, font); - - // Inline completion RTL case: - // "a__|b", __ of b => non-boundary a-pos is right of __ - if (vpos + 1 == inlineCompletionVPos - && (vpos + 1 < cursor_vpos || !boundary_correction)) { - font = displayFont(pit, vpos + 1); - docstring const & completion = bv_->inlineCompletion(); - if (font.isRightToLeft() && completion.length() > 0) - x2 += theFontMetrics(font.fontInfo()).width(completion); - } - - // Inline completion LTR case: - // "b|__a", __ of b => non-boundary a-pos is in front of __ - if (vpos == inlineCompletionVPos - && (vpos + 1 < cursor_vpos || boundary_correction)) { - font = displayFont(pit, vpos); - docstring const & completion = bv_->inlineCompletion(); - if (!font.isRightToLeft() && completion.length() > 0) - x2 += theFontMetrics(font.fontInfo()).width(completion); - } - - if (par.isSeparator(pos) && pos >= body_pos) - x2 += row.separator; - } - - // see correction above - if (boundary_correction) { - if (isRTL(sl, boundary)) - x2 -= singleWidth(pit, pos); - else - x2 += singleWidth(pit, pos); - } - - if (abs(x2 - x) > 0.01) { - lyxerr << "cursorX: x2=" << x2 << ", x=" << x; - if (cit == row.end()) - lyxerr << "Element not found for " - << pos - boundary_corr << "(" << boundary_corr << ")"; - else - lyxerr << " in [" << cit->pos << "/" - << pos - boundary_corr << "(" << boundary_corr << ")" - << "/" << cit->endpos << "] of " << *cit << "\n"; - lyxerr << row < 0 - && pars[pit - 1].getDepth() >= par.getDepth()) { + 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 (pars[prev < pit ? prev : pit - 1].layout().nextnoindent) + 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(); } @@ -2041,15 +1780,6 @@ int TextMetrics::leftMargin(int max_width, } -#ifdef KEEP_OLD_METRICS_CODE -int TextMetrics::singleWidth(pit_type pit, pos_type pos) const -{ - ParagraphMetrics const & pm = par_metrics_[pit]; - - return pm.singleWidth(pos, displayFont(pit, pos)); -} -#endif - void TextMetrics::draw(PainterInfo & pi, int x, int y) const { if (par_metrics_.empty()) @@ -2080,7 +1810,6 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co if (pm.rows().empty()) return; - Bidi bidi; bool const original_drawing_state = pi.pain.isDrawingEnabled(); int const ww = bv_->workHeight(); size_t const nrows = pm.rows().size(); @@ -2121,7 +1850,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co && y - row.ascent() < ww); // It is not needed to draw on screen if we are not inside. pi.pain.setDrawingEnabled(inside && original_drawing_state); - RowPainter rp(pi, *text_, pit, row, bidi, x, y); + RowPainter rp(pi, *text_, pit, row, x, y); if (selection) row.setSelectionAndMargins(sel_beg_par, sel_end_par); @@ -2238,15 +1967,6 @@ void TextMetrics::completionPosAndDim(Cursor const & cur, int & x, int & y, //lyxerr << " wordstart=" << wordStart << " bvcur=" << bvcur << " cur=" << cur << std::endl; } -//int TextMetrics::pos2x(pit_type pit, pos_type pos) const -//{ -// ParagraphMetrics const & pm = par_metrics_[pit]; -// Row const & r = pm.rows()[row]; -// int x = 0; -// pos -= r.pos(); -//} - - int defaultRowHeight() { return int(theFontMetrics(sane_font).maxHeight() * 1.2);