X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Ftext.C;h=db87337d15218dd1372cd68027957b1c09a2d8ff;hb=2292145ba3a0ae9c49acd351cfc6eb696041a81f;hp=d9df3f891cba1d07f6d62d219f9faaaaa0d9e602;hpb=0011b84a16d6507bdebda08e49121ccf6ac2ae1c;p=lyx.git diff --git a/src/text.C b/src/text.C index d9df3f891c..db87337d15 100644 --- a/src/text.C +++ b/src/text.C @@ -22,6 +22,7 @@ #include "bufferparams.h" #include "BufferView.h" #include "debug.h" +#include "dispatchresult.h" #include "encoding.h" #include "funcrequest.h" #include "gettext.h" @@ -97,6 +98,14 @@ BufferView * LyXText::bv() } +double LyXText::spacing(Paragraph const & par) const +{ + if (par.params().spacing().isDefault()) + return bv()->buffer()->params().spacing().getValue(); + return par.params().spacing().getValue(); +} + + BufferView * LyXText::bv() const { BOOST_ASSERT(bv_owner != 0); @@ -130,44 +139,6 @@ int LyXText::getRealCursorX() const } -#warning FIXME This function seems to belong outside of LyxText. -unsigned char LyXText::transformChar(unsigned char c, Paragraph const & par, - pos_type pos) const -{ - if (!Encodings::is_arabic(c)) - if (lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 && IsDigit(c)) - return c + (0xb0 - '0'); - else - return c; - - unsigned char const prev_char = pos > 0 ? par.getChar(pos - 1) : ' '; - unsigned char next_char = ' '; - - pos_type const par_size = par.size(); - - for (pos_type i = pos + 1; i < par_size; ++i) { - unsigned char const par_char = par.getChar(i); - if (!Encodings::IsComposeChar_arabic(par_char)) { - next_char = par_char; - break; - } - } - - if (Encodings::is_arabic(next_char)) { - if (Encodings::is_arabic(prev_char) && - !Encodings::is_arabic_special(prev_char)) - return Encodings::TransformChar(c, Encodings::FORM_MEDIAL); - else - return Encodings::TransformChar(c, Encodings::FORM_INITIAL); - } else { - if (Encodings::is_arabic(prev_char) && - !Encodings::is_arabic_special(prev_char)) - return Encodings::TransformChar(c, Encodings::FORM_FINAL); - else - return Encodings::TransformChar(c, Encodings::FORM_ISOLATED); - } -} - // This is the comments that some of the warnings below refers to. // There are some issues in this file and I don't think they are // really related to the FIX_DOUBLE_SPACE patch. I'd rather think that @@ -213,7 +184,6 @@ int LyXText::singleWidth(ParagraphList::iterator pit, return 0; } - // The most common case is handled first (Asger) if (IsPrintable(c)) { if (!font.language()->RightToLeft()) { @@ -223,7 +193,7 @@ int LyXText::singleWidth(ParagraphList::iterator pit, if (Encodings::IsComposeChar_arabic(c)) return 0; else - c = transformChar(c, *pit, pos); + c = pit->transformChar(c, pos); } else if (font.language()->lang() == "hebrew" && Encodings::IsComposeChar_hebrew(c)) return 0; @@ -231,15 +201,8 @@ int LyXText::singleWidth(ParagraphList::iterator pit, return font_metrics::width(c, font); } - if (c == Paragraph::META_INSET) { - InsetOld * tmpinset = pit->getInset(pos); - BOOST_ASSERT(tmpinset); - if (tmpinset->lyxCode() == InsetOld::HFILL_CODE) { - // Because of the representation as vertical lines - return 3; - } - return tmpinset->width(); - } + if (c == Paragraph::META_INSET) + return pit->getInset(pos)->width(); if (IsSeparatorChar(c)) c = ' '; @@ -247,192 +210,6 @@ int LyXText::singleWidth(ParagraphList::iterator pit, } -lyx::pos_type LyXText::log2vis(lyx::pos_type pos) const -{ - return (bidi_start == -1) ? pos : log2vis_list[pos - bidi_start]; -} - - -lyx::pos_type LyXText::vis2log(lyx::pos_type pos) const -{ - return (bidi_start == -1) ? pos : vis2log_list[pos - bidi_start]; -} - - -lyx::pos_type LyXText::bidi_level(lyx::pos_type pos) const -{ - return (bidi_start == -1) ? 0 : bidi_levels[pos - bidi_start]; -} - - -bool LyXText::bidi_InRange(lyx::pos_type pos) const -{ - return bidi_start == -1 || (bidi_start <= pos && pos <= bidi_end); -} - - -void LyXText::computeBidiTables(Paragraph const & par, - Buffer const & buf, Row & row) const -{ - bidi_same_direction = true; - if (!lyxrc.rtl_support) { - bidi_start = -1; - return; - } - - InsetOld * inset = par.inInset(); - if (inset && inset->owner() && - inset->owner()->lyxCode() == InsetOld::ERT_CODE) { - bidi_start = -1; - return; - } - - bidi_start = row.pos(); - bidi_end = lastPos(par, row); - - if (bidi_start > bidi_end) { - bidi_start = -1; - return; - } - - if (bidi_end + 2 - bidi_start > - static_cast(log2vis_list.size())) { - pos_type new_size = - (bidi_end + 2 - bidi_start < 500) ? - 500 : 2 * (bidi_end + 2 - bidi_start); - log2vis_list.resize(new_size); - vis2log_list.resize(new_size); - bidi_levels.resize(new_size); - } - - vis2log_list[bidi_end + 1 - bidi_start] = -1; - log2vis_list[bidi_end + 1 - bidi_start] = -1; - - BufferParams const & bufparams = buf.params(); - pos_type stack[2]; - bool const rtl_par = par.isRightToLeftPar(bufparams); - int level = 0; - bool rtl = false; - bool rtl0 = false; - pos_type const body_pos = par.beginningOfBody(); - - for (pos_type lpos = bidi_start; lpos <= bidi_end; ++lpos) { - bool is_space = par.isLineSeparator(lpos); - pos_type const pos = - (is_space && lpos + 1 <= bidi_end && - !par.isLineSeparator(lpos + 1) && - !par.isNewline(lpos + 1)) - ? lpos + 1 : lpos; - LyXFont font = par.getFontSettings(bufparams, pos); - if (pos != lpos && 0 < lpos && rtl0 && font.isRightToLeft() && - font.number() == LyXFont::ON && - par.getFontSettings(bufparams, lpos - 1).number() - == LyXFont::ON) { - font = par.getFontSettings(bufparams, lpos); - is_space = false; - } - - bool new_rtl = font.isVisibleRightToLeft(); - bool new_rtl0 = font.isRightToLeft(); - int new_level; - - if (lpos == body_pos - 1 - && row.pos() < body_pos - 1 - && is_space) { - new_level = rtl_par ? 1 : 0; - new_rtl0 = rtl_par; - new_rtl = rtl_par; - } else if (new_rtl0) - new_level = new_rtl ? 1 : 2; - else - new_level = rtl_par ? 2 : 0; - - if (is_space && new_level >= level) { - new_level = level; - new_rtl = rtl; - new_rtl0 = rtl0; - } - - int new_level2 = new_level; - - if (level == new_level && rtl0 != new_rtl0) { - --new_level2; - log2vis_list[lpos - bidi_start] = rtl ? 1 : -1; - } else if (level < new_level) { - log2vis_list[lpos - bidi_start] = rtl ? -1 : 1; - if (new_level > rtl_par) - bidi_same_direction = false; - } else - log2vis_list[lpos - bidi_start] = new_rtl ? -1 : 1; - rtl = new_rtl; - rtl0 = new_rtl0; - bidi_levels[lpos - bidi_start] = new_level; - - while (level > new_level2) { - pos_type old_lpos = stack[--level]; - int delta = lpos - old_lpos - 1; - if (level % 2) - delta = -delta; - log2vis_list[lpos - bidi_start] += delta; - log2vis_list[old_lpos - bidi_start] += delta; - } - while (level < new_level) - stack[level++] = lpos; - } - - while (level > 0) { - pos_type const old_lpos = stack[--level]; - int delta = bidi_end - old_lpos; - if (level % 2) - delta = -delta; - log2vis_list[old_lpos - bidi_start] += delta; - } - - pos_type vpos = bidi_start - 1; - for (pos_type lpos = bidi_start; - lpos <= bidi_end; ++lpos) { - vpos += log2vis_list[lpos - bidi_start]; - vis2log_list[vpos - bidi_start] = lpos; - log2vis_list[lpos - bidi_start] = vpos; - } -} - - -// This method requires a previous call to ComputeBidiTables() -bool LyXText::isBoundary(Buffer const & buf, Paragraph const & par, - pos_type pos) const -{ - if (!lyxrc.rtl_support || pos == 0) - return false; - - if (!bidi_InRange(pos - 1)) { - // This can happen if pos is the first char of a row. - // Returning false in this case is incorrect! - return false; - } - - bool const rtl = bidi_level(pos - 1) % 2; - bool const rtl2 = bidi_InRange(pos) - ? bidi_level(pos) % 2 - : par.isRightToLeftPar(buf.params()); - return rtl != rtl2; -} - - -bool LyXText::isBoundary(Buffer const & buf, Paragraph const & par, - pos_type pos, LyXFont const & font) const -{ - if (!lyxrc.rtl_support) - return false; // This is just for speedup - - bool const rtl = font.isVisibleRightToLeft(); - bool const rtl2 = bidi_InRange(pos) - ? bidi_level(pos) % 2 - : par.isRightToLeftPar(buf.params()); - return rtl != rtl2; -} - - int LyXText::leftMargin(ParagraphList::iterator pit, Row const & row) const { LyXTextClass const & tclass = @@ -448,50 +225,43 @@ int LyXText::leftMargin(ParagraphList::iterator pit, Row const & row) const // this is the way, LyX handles the LaTeX-Environments. // I have had this idea very late, so it seems to be a // later added hack and this is true - if (!pit->getDepth()) { + if (pit->getDepth() == 0) { if (pit->layout() == tclass.defaultLayout()) { // find the previous same level paragraph if (pit != ownerParagraphs().begin()) { ParagraphList::iterator newpit = - depthHook(pit, ownerParagraphs(), - pit->getDepth()); - if (newpit == pit && - newpit->layout()->nextnoindent) + depthHook(pit, ownerParagraphs(), pit->getDepth()); + if (newpit == pit && newpit->layout()->nextnoindent) parindent.erase(); } } } else { // find the next level paragraph - - ParagraphList::iterator newpar = outerHook(pit, - ownerParagraphs()); + ParagraphList::iterator newpar = + outerHook(pit, ownerParagraphs()); // make a corresponding row. Needed to call leftMargin() - // check wether it is a sufficent paragraph - if (newpar != ownerParagraphs().end() && - newpar->layout()->isEnvironment()) { + if (newpar != ownerParagraphs().end() + && newpar->layout()->isEnvironment()) { x = leftMargin(newpar, Row(newpar->size())); } - if (newpar != ownerParagraphs().end() && - pit->layout() == tclass.defaultLayout()) { + if (newpar != ownerParagraphs().end() + && pit->layout() == tclass.defaultLayout()) { if (newpar->params().noindent()) parindent.erase(); - else { + else parindent = newpar->layout()->parindent; - } - } } LyXFont const labelfont = getLabelFont(pit); switch (layout->margintype) { case MARGIN_DYNAMIC: - if (!layout->leftmargin.empty()) { + if (!layout->leftmargin.empty()) x += font_metrics::signedWidth(layout->leftmargin, tclass.defaultfont()); - } if (!pit->getLabelstring().empty()) { x += font_metrics::signedWidth(layout->labelindent, labelfont); @@ -500,6 +270,7 @@ int LyXText::leftMargin(ParagraphList::iterator pit, Row const & row) const x += font_metrics::width(layout->labelsep, labelfont); } break; + case MARGIN_MANUAL: x += font_metrics::signedWidth(layout->labelindent, labelfont); // The width of an empty par, even with manual label, should be 0 @@ -511,10 +282,12 @@ int LyXText::leftMargin(ParagraphList::iterator pit, Row const & row) const } } break; + case MARGIN_STATIC: x += font_metrics::signedWidth(layout->leftmargin, tclass.defaultfont()) * 4 / (pit->getDepth() + 4); break; + case MARGIN_FIRST_DYNAMIC: if (layout->labeltype == LABEL_MANUAL) { if (row.pos() >= pit->beginningOfBody()) { @@ -544,17 +317,16 @@ int LyXText::leftMargin(ParagraphList::iterator pit, Row const & row) const } break; - case MARGIN_RIGHT_ADDRESS_BOX: - { + case MARGIN_RIGHT_ADDRESS_BOX: { // ok, a terrible hack. The left margin depends on the widest // row in this paragraph. RowList::iterator rit = pit->rows.begin(); RowList::iterator end = pit->rows.end(); - int minfill = rit->fill(); +#warning This is wrong. + int minfill = workWidth() / 2; for ( ; rit != end; ++rit) if (rit->fill() < minfill) minfill = rit->fill(); - x += font_metrics::signedWidth(layout->leftmargin, tclass.defaultfont()); x += minfill; @@ -605,8 +377,7 @@ int LyXText::leftMargin(ParagraphList::iterator pit, Row const & row) const } -int LyXText::rightMargin(Paragraph const & par, - Buffer const & buf, Row const &) const +int LyXText::rightMargin(Paragraph const & par, Buffer const & buf) const { LyXTextClass const & tclass = buf.params().getLyXTextClass(); LyXLayout_ptr const & layout = par.layout(); @@ -622,16 +393,14 @@ int LyXText::rightMargin(Paragraph const & par, int LyXText::labelEnd(ParagraphList::iterator pit, Row const & row) const { - if (pit->layout()->margintype == MARGIN_MANUAL) { - Row tmprow = row; - tmprow.pos(pit->size()); - // return the beginning of the body - return leftMargin(pit, tmprow); - } + // labelEnd is only needed if the layout fills a flushleft label. + if (pit->layout()->margintype != MARGIN_MANUAL) + return 0; - // LabelEnd is only needed if the layout - // fills a flushleft label. - return 0; + Row tmprow = row; + tmprow.pos(pit->size()); + // return the beginning of the body + return leftMargin(pit, tmprow); } @@ -640,39 +409,47 @@ namespace { // this needs special handling - only newlines count as a break point pos_type addressBreakPoint(pos_type i, Paragraph const & par) { - for (; i < par.size(); ++i) + pos_type const end = par.size(); + + for (; i < end; ++i) if (par.isNewline(i)) - return i; + return i + 1; - return par.size(); + return end; } }; -pos_type LyXText::rowBreakPoint(ParagraphList::iterator pit, - Row const & row) const +void LyXText::rowBreakPoint(ParagraphList::iterator pit, Row & row) const { + pos_type const end = pit->size(); + pos_type const pos = row.pos(); + if (pos == end) { + row.endpos(end); + return; + } + // maximum pixel width of a row. - int width = workWidth() - rightMargin(*pit, *bv()->buffer(), row); + int width = workWidth() - rightMargin(*pit, *bv()->buffer()); +// - leftMargin(pit, row); // inset->textWidth() returns -1 via workWidth(), // but why ? - if (width < 0) - return pit->size(); + if (width < 0) { + row.endpos(end); + return; + } LyXLayout_ptr const & layout = pit->layout(); - if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) - return addressBreakPoint(row.pos(), *pit); + if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) { + row.endpos(addressBreakPoint(pos, *pit)); + return; + } - pos_type const pos = row.pos(); pos_type const body_pos = pit->beginningOfBody(); - pos_type const last = pit->size(); - pos_type point = last; - if (pos == last) - return last; // Now we iterate through until we reach the right margin // or the end of the par, then choose the possible break @@ -684,71 +461,76 @@ pos_type LyXText::rowBreakPoint(ParagraphList::iterator pit, // pixel width since last breakpoint int chunkwidth = 0; - pos_type i = pos; // We re-use the font resolution for the entire font span when possible - LyXFont font = getFont(pit, i); - lyx::pos_type endPosOfFontSpan = pit->getEndPosOfFontSpan(i); + LyXFont font = getFont(pit, pos); + lyx::pos_type endPosOfFontSpan = pit->getEndPosOfFontSpan(pos); - for (; i < last; ++i) { + pos_type point = end; + pos_type i = pos; + for ( ; i < end; ++i) { if (pit->isNewline(i)) { - point = i; + point = i + 1; break; } - // Break before... - if (i + 1 < last) { + // Break before... + if (i + 1 < end) { InsetOld * in = pit->getInset(i + 1); if (in && in->display()) { - point = i; + point = i + 1; break; } // ...and after. in = pit->getInset(i); if (in && in->display()) { - point = i; + point = i + 1; break; } } char const c = pit->getChar(i); + if (i > endPosOfFontSpan) { font = getFont(pit, i); endPosOfFontSpan = pit->getEndPosOfFontSpan(i); } - int thiswidth; - - // add the auto-hfill from label end to the body - if (body_pos && i == body_pos) { - thiswidth = font_metrics::width(layout->labelsep, getLabelFont(pit)); - if (pit->isLineSeparator(i - 1)) - thiswidth -= singleWidth(pit, i - 1); - int left_margin = labelEnd(pit, row); - if (thiswidth + x < left_margin) - thiswidth = left_margin - x; - thiswidth += singleWidth(pit, i, c, font); - } else { - thiswidth = singleWidth(pit, i, c, font); + { + int thiswidth = singleWidth(pit, i, c, font); + + // add the auto-hfill from label end to the body + if (body_pos && i == body_pos) { + int add = font_metrics::width(layout->labelsep, getLabelFont(pit)); + if (pit->isLineSeparator(i - 1)) + add -= singleWidth(pit, i - 1); + + add = std::max(add, labelEnd(pit, row) - x); + thiswidth += add; + } + + x += thiswidth; + //lyxerr << "i: " << i << " x: " + //<< x << " width: " << width << endl; + chunkwidth += thiswidth; } - x += thiswidth; - //lyxerr << "i: " << i << " x: " << x << " width: " << width << endl; - chunkwidth += thiswidth; // break before a character that will fall off // the right of the row if (x >= width) { // if no break before, break here - if (point == last || chunkwidth >= width - left) { - if (pos < i) { - point = i - 1; - // exit on last registered breakpoint: - break; + if (point == end || chunkwidth >= width - left) { + if (i > pos) { + point = i; + break; } } - // emergency exit: - if (i + 1 < last) - break; + // exit on last registered breakpoint: +#if 0 + // hack removed: + if (i + 1 < end) +#endif + break; } InsetOld * in = pit->getInset(i); @@ -756,69 +538,56 @@ pos_type LyXText::rowBreakPoint(ParagraphList::iterator pit, // some insets are line separators too if (pit->isLineSeparator(i)) { // register breakpoint: - point = i; + point = i + 1; chunkwidth = 0; } } } - if (point == last && x >= width) { +#if 0 + // hack removed (connected with the #if 0 above): + if (point == end && i != end && x >= width) { // didn't find one, break at the point we reached the edge - point = i; - } else if (i == last && x < width) { - // found one, but we fell off the end of the par, so prefer - // that. - point = last; + point = i + 1; + } else +#endif + if (i == end && x < width) { + // maybe found one, but the par is short enough. + point = end; } // manual labels cannot be broken in LaTeX. But we // want to make our on-screen rendering of footnotes // etc. still break if (body_pos && point < body_pos) - point = body_pos - 1; + point = body_pos; - return point; + row.endpos(point); } // returns the minimum space a row needs on the screen in pixel -int LyXText::fill(ParagraphList::iterator pit, Row & row, int paper_width) const +void LyXText::fill(ParagraphList::iterator pit, Row & row, int workwidth) const { - if (paper_width < 0) { - lyxerr << "paperwidth < 0: " << paper_width << " Why?" << endl; - return 0; - } - - int w; // get the pure distance - pos_type const last = lastPos(*pit, row); + pos_type const end = row.endpos(); LyXLayout_ptr const & layout = pit->layout(); - - // special handling of the right address boxes - if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) { - int const tmpfill = row.fill(); - row.fill(0); // the minfill in leftMargin() - w = leftMargin(pit, row); - row.fill(tmpfill); - } else - w = leftMargin(pit, row); + int w = leftMargin(pit, row); pos_type const body_pos = pit->beginningOfBody(); pos_type i = row.pos(); - if (! pit->empty() && i <= last) { + if (i < end) { // We re-use the font resolution for the entire span when possible LyXFont font = getFont(pit, i); lyx::pos_type endPosOfFontSpan = pit->getEndPosOfFontSpan(i); - while (i <= last) { + for ( ; i < end; ++i) { if (body_pos > 0 && i == body_pos) { w += font_metrics::width(layout->labelsep, getLabelFont(pit)); if (pit->isLineSeparator(i - 1)) w -= singleWidth(pit, i - 1); - int left_margin = labelEnd(pit, row); - if (w < left_margin) - w = left_margin; + w = max(w, labelEnd(pit, row)); } char const c = pit->getChar(i); if (IsPrintable(c) && i > endPosOfFontSpan) { @@ -827,33 +596,19 @@ int LyXText::fill(ParagraphList::iterator pit, Row & row, int paper_width) const endPosOfFontSpan = pit->getEndPosOfFontSpan(i); } w += singleWidth(pit, i, c, font); - ++i; } } - if (body_pos > 0 && body_pos > last) { + + if (body_pos > 0 && body_pos >= end) { w += font_metrics::width(layout->labelsep, getLabelFont(pit)); - if (last >= 0 && pit->isLineSeparator(last)) - w -= singleWidth(pit, last); - int const left_margin = labelEnd(pit, row); - if (w < left_margin) - w = left_margin; + if (end > 0 && pit->isLineSeparator(end - 1)) + w -= singleWidth(pit, end - 1); + w = max(w, labelEnd(pit, row)); } - int const fill = paper_width - w - rightMargin(*pit, *bv()->buffer(), row); - - // If this case happens, it means that our calculation - // of the widths of the chars when we do rowBreakPoint() - // went wrong for some reason. Typically in list bodies. - // Things just about hobble on anyway, though you'll end - // up with a "fill_separator" less than zero, which corresponds - // to inter-word spacing being too small. Hopefully this problem - // will die when the label hacks die. - if (lyxerr.debugging() && fill < 0) { - lyxerr[Debug::GUI] << "Eek, fill() was < 0: " << fill - << " w " << w << " paper_width " << paper_width - << " right margin " << rightMargin(*pit, *bv()->buffer(), row) << endl; - } - return fill; + int const fill = workwidth - w - rightMargin(*pit, *bv()->buffer()); + row.fill(fill); + row.width(workwidth - fill); } @@ -864,8 +619,7 @@ int LyXText::labelFill(ParagraphList::iterator pit, Row const & row) const BOOST_ASSERT(last > 0); - // -1 because a label ends either with a space that is in the label, - // or with the beginning of a footnote that is outside the label. + // -1 because a label ends with a space that is in the label --last; // a separator at this end does not count @@ -873,21 +627,14 @@ int LyXText::labelFill(ParagraphList::iterator pit, Row const & row) const --last; int w = 0; - pos_type i = row.pos(); - while (i <= last) { + for (pos_type i = row.pos(); i <= last; ++i) w += singleWidth(pit, i); - ++i; - } - int fill = 0; - string const & labwidstr = pit->params().labelWidthString(); - if (!labwidstr.empty()) { - LyXFont const labfont = getLabelFont(pit); - int const labwidth = font_metrics::width(labwidstr, labfont); - fill = max(labwidth - w, 0); - } + string const & label = pit->params().labelWidthString(); + if (label.empty()) + return 0; - return fill; + return max(0, font_metrics::width(label, getLabelFont(pit)) - w); } @@ -895,8 +642,7 @@ LColor_color LyXText::backgroundColor() const { if (inset_owner) return inset_owner->backgroundColor(); - else - return LColor::background; + return LColor::background; } @@ -905,7 +651,7 @@ void LyXText::setHeightOfRow(ParagraphList::iterator pit, Row & row) // get the maximum ascent and the maximum descent double layoutasc = 0; double layoutdesc = 0; - double tmptop = 0; + double const dh = defaultRowHeight(); // ok, let us initialize the maxasc and maxdesc value. // Only the fontsize count. The other properties @@ -923,77 +669,33 @@ void LyXText::setHeightOfRow(ParagraphList::iterator pit, Row & row) LyXFont labelfont = getLabelFont(pit); - double spacing_val = 1.0; - if (!pit->params().spacing().isDefault()) - spacing_val = pit->params().spacing().getValue(); - else - spacing_val = bv()->buffer()->params().spacing().getValue(); + // these are minimum values + double const spacing_val = layout->spacing.getValue() * spacing(*pit); //lyxerr << "spacing_val = " << spacing_val << endl; + int maxasc = int(font_metrics::maxAscent(font) * spacing_val); + int maxdesc = int(font_metrics::maxDescent(font) * spacing_val); - int maxasc = int(font_metrics::maxAscent(font) * - layout->spacing.getValue() * spacing_val); - int maxdesc = int(font_metrics::maxDescent(font) * - layout->spacing.getValue() * spacing_val); - - pos_type const pos_end = lastPos(*pit, row); - int labeladdon = 0; - int maxwidth = 0; - - if (!pit->empty()) { - // We re-use the font resolution for the entire font span when possible - LyXFont font = getFont(pit, row.pos()); - lyx::pos_type endPosOfFontSpan = pit->getEndPosOfFontSpan(row.pos()); - - // Optimisation - Paragraph const & par = *pit; - - // Check if any insets are larger - for (pos_type pos = row.pos(); pos <= pos_end; ++pos) { - // Manual inlined optimised version of common case of - // "maxwidth += singleWidth(pit, pos);" - char const c = par.getChar(pos); - - if (IsPrintable(c)) { - if (pos > endPosOfFontSpan) { - // We need to get the next font - font = getFont(pit, pos); - endPosOfFontSpan = par.getEndPosOfFontSpan(pos); - } - if (! font.language()->RightToLeft()) { - maxwidth += font_metrics::width(c, font); - } else { - // Fall-back to normal case - maxwidth += singleWidth(pit, pos, c, font); - // And flush font cache - endPosOfFontSpan = 0; - } - } else { - // Special handling of insets - are any larger? - if (par.isInset(pos)) { - InsetOld const * tmpinset = par.getInset(pos); - if (tmpinset) { - maxwidth += tmpinset->width(); - maxasc = max(maxasc, tmpinset->ascent()); - maxdesc = max(maxdesc, tmpinset->descent()); - } - } else { - // Fall-back to normal case - maxwidth += singleWidth(pit, pos, c, font); - // And flush font cache - endPosOfFontSpan = 0; - } - } + // insets may be taller + InsetList::iterator ii = pit->insetlist.begin(); + InsetList::iterator iend = pit->insetlist.end(); + for ( ; ii != iend; ++ii) { + if (ii->pos >= row.pos() && ii->pos < row.endpos()) { + maxasc = max(maxasc, ii->inset->ascent()); + maxdesc = max(maxdesc, ii->inset->descent()); } } // Check if any custom fonts are larger (Asger) // This is not completely correct, but we can live with the small, // cosmetic error for now. + int labeladdon = 0; + pos_type const pos_end = row.endpos(); + LyXFont::FONT_SIZE maxsize = pit->highestFontInRange(row.pos(), pos_end, size); if (maxsize > font.size()) { font.setSize(maxsize); - maxasc = max(maxasc, font_metrics::maxAscent(font)); + maxasc = max(maxasc, font_metrics::maxAscent(font)); maxdesc = max(maxdesc, font_metrics::maxDescent(font)); } @@ -1004,61 +706,34 @@ void LyXText::setHeightOfRow(ParagraphList::iterator pit, Row & row) row.ascent_of_text(maxasc); // is it a top line? - if (!row.pos()) { + if (row.pos() == 0) { BufferParams const & bufparams = bv()->buffer()->params(); // some parksips VERY EASY IMPLEMENTATION - if (bv()->buffer()->params().paragraph_separation == - BufferParams::PARSEP_SKIP) + if (bv()->buffer()->params().paragraph_separation + == BufferParams::PARSEP_SKIP + && pit != ownerParagraphs().begin() + && ((layout->isParagraph() && pit->getDepth() == 0) + || (boost::prior(pit)->layout()->isParagraph() + && boost::prior(pit)->getDepth() == 0))) { - if (layout->isParagraph() - && pit->getDepth() == 0 - && pit != ownerParagraphs().begin()) - { - maxasc += bufparams.getDefSkip().inPixels(*bv()); - } else if (pit != ownerParagraphs().begin() && - boost::prior(pit)->layout()->isParagraph() && - boost::prior(pit)->getDepth() == 0) - { - // is it right to use defskip here too? (AS) maxasc += bufparams.getDefSkip().inPixels(*bv()); - } } // the top margin if (pit == ownerParagraphs().begin() && !isInInset()) maxasc += PAPER_MARGIN; - // add the vertical spaces, that the user added + // add user added vertical space maxasc += getLengthMarkerHeight(*bv(), pit->params().spaceTop()); - // do not forget the DTP-lines! - // there height depends on the font of the nearest character - if (pit->params().lineTop()) - - maxasc += 2 * font_metrics::ascent('x', getFont(pit, 0)); - // and now the pagebreaks - if (pit->params().pagebreakTop()) - maxasc += 3 * defaultRowHeight(); - if (pit->params().startOfAppendix()) - maxasc += 3 * defaultRowHeight(); + maxasc += int(3 * dh); // This is special code for the chapter, since the label of this // layout is printed in an extra row if (layout->counter == "chapter" && bufparams.secnumdepth >= 0) { - float spacing_val = 1.0; - if (!pit->params().spacing().isDefault()) { - spacing_val = pit->params().spacing().getValue(); - } else { - spacing_val = bufparams.spacing().getValue(); - } - - labeladdon = int(font_metrics::maxDescent(labelfont) * - layout->spacing.getValue() * - spacing_val) - + int(font_metrics::maxAscent(labelfont) * - layout->spacing.getValue() * - spacing_val); + labeladdon = int(font_metrics::maxHeight(labelfont) + * layout->spacing.getValue() * spacing(*pit)); } // special code for the top label @@ -1068,56 +743,38 @@ void LyXText::setHeightOfRow(ParagraphList::iterator pit, Row & row) && isFirstInSequence(pit, ownerParagraphs()) && !pit->getLabelstring().empty()) { - float spacing_val = 1.0; - if (!pit->params().spacing().isDefault()) { - spacing_val = pit->params().spacing().getValue(); - } else { - spacing_val = bufparams.spacing().getValue(); - } - labeladdon = int( - (font_metrics::maxAscent(labelfont) + - font_metrics::maxDescent(labelfont)) * - layout->spacing.getValue() * - spacing_val - + layout->topsep * defaultRowHeight() - + layout->labelbottomsep * defaultRowHeight()); + font_metrics::maxHeight(labelfont) + * layout->spacing.getValue() + * spacing(*pit) + + (layout->topsep + layout->labelbottomsep) * dh); } // And now the layout spaces, for example before and after // a section, or between the items of a itemize or enumerate // environment. - if (!pit->params().pagebreakTop()) { - ParagraphList::iterator prev = - depthHook(pit, ownerParagraphs(), - pit->getDepth()); - if (prev != pit && prev->layout() == layout && - prev->getDepth() == pit->getDepth() && - prev->getLabelWidthString() == pit->getLabelWidthString()) - { - layoutasc = (layout->itemsep * defaultRowHeight()); - } else if (pit != ownerParagraphs().begin() || row.pos() != 0) { - tmptop = layout->topsep; - - if (tmptop > 0) - layoutasc = (tmptop * defaultRowHeight()); - } else if (pit->params().lineTop()) { - tmptop = layout->topsep; - - if (tmptop > 0) - layoutasc = (tmptop * defaultRowHeight()); - } + ParagraphList::iterator prev = + depthHook(pit, ownerParagraphs(), pit->getDepth()); + if (prev != pit + && prev->layout() == layout + && prev->getDepth() == pit->getDepth() + && prev->getLabelWidthString() == pit->getLabelWidthString()) + { + layoutasc = layout->itemsep * dh; + } else if (pit != ownerParagraphs().begin() || row.pos() != 0) { + if (layout->topsep > 0) + layoutasc = layout->topsep * dh; + } - prev = outerHook(pit, ownerParagraphs()); - if (prev != ownerParagraphs().end()) { - maxasc += int(prev->layout()->parsep * defaultRowHeight()); - } else if (pit != ownerParagraphs().begin()) { - ParagraphList::iterator prior_pit = boost::prior(pit); - if (prior_pit->getDepth() != 0 || - prior_pit->layout() == layout) { - maxasc += int(layout->parsep * defaultRowHeight()); - } + prev = outerHook(pit, ownerParagraphs()); + if (prev != ownerParagraphs().end()) { + maxasc += int(prev->layout()->parsep * dh); + } else if (pit != ownerParagraphs().begin()) { + ParagraphList::iterator prior_pit = boost::prior(pit); + if (prior_pit->getDepth() != 0 || + prior_pit->layout() == layout) { + maxasc += int(layout->parsep * dh); } } } @@ -1132,77 +789,56 @@ void LyXText::setHeightOfRow(ParagraphList::iterator pit, Row & row) // add the vertical spaces, that the user added maxdesc += getLengthMarkerHeight(*bv(), pit->params().spaceBottom()); - // do not forget the DTP-lines! - // there height depends on the font of the nearest character - if (pit->params().lineBottom()) - maxdesc += 2 * font_metrics::ascent('x', - getFont(pit, max(pos_type(0), pit->size() - 1))); - - // and now the pagebreaks - if (pit->params().pagebreakBottom()) - maxdesc += 3 * defaultRowHeight(); - // and now the layout spaces, for example before and after // a section, or between the items of a itemize or enumerate // environment - if (!pit->params().pagebreakBottom() - && nextpit != ownerParagraphs().end()) { - ParagraphList::iterator comparepit = pit; - float usual = 0; - float unusual = 0; - - if (comparepit->getDepth() > nextpit->getDepth()) { - usual = (comparepit->layout()->bottomsep * defaultRowHeight()); - comparepit = depthHook(comparepit, ownerParagraphs(), nextpit->getDepth()); - if (comparepit->layout()!= nextpit->layout() - || nextpit->getLabelWidthString() != - comparepit->getLabelWidthString()) + if (nextpit != ownerParagraphs().end()) { + ParagraphList::iterator cpit = pit; + double usual = 0; + double unusual = 0; + + if (cpit->getDepth() > nextpit->getDepth()) { + usual = cpit->layout()->bottomsep * dh; + cpit = depthHook(cpit, ownerParagraphs(), nextpit->getDepth()); + if (cpit->layout() != nextpit->layout() + || nextpit->getLabelWidthString() != cpit->getLabelWidthString()) { - unusual = (comparepit->layout()->bottomsep * defaultRowHeight()); + unusual = cpit->layout()->bottomsep * dh; } - if (unusual > usual) - layoutdesc = unusual; - else - layoutdesc = usual; - } else if (comparepit->getDepth() == nextpit->getDepth()) { - - if (comparepit->layout() != nextpit->layout() - || nextpit->getLabelWidthString() != - comparepit->getLabelWidthString()) - layoutdesc = int(comparepit->layout()->bottomsep * defaultRowHeight()); + layoutdesc = max(unusual, usual); + } else if (cpit->getDepth() == nextpit->getDepth()) { + if (cpit->layout() != nextpit->layout() + || nextpit->getLabelWidthString() != cpit->getLabelWidthString()) + layoutdesc = int(cpit->layout()->bottomsep * dh); } } } // incalculate the layout spaces - maxasc += int(layoutasc * 2 / (2 + pit->getDepth())); + maxasc += int(layoutasc * 2 / (2 + pit->getDepth())); maxdesc += int(layoutdesc * 2 / (2 + pit->getDepth())); row.height(maxasc + maxdesc + labeladdon); row.baseline(maxasc + labeladdon); row.top_of_text(row.baseline() - font_metrics::maxAscent(font)); - - row.width(maxwidth); - - if (inset_owner) - width = max(workWidth(), int(maxParagraphWidth(ownerParagraphs()))); } void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout) { // allow only if at start or end, or all previous is new text - if (cursor.pos() && cursor.pos() != cursorPar()->size() - && cursorPar()->isChangeEdited(0, cursor.pos())) + ParagraphList::iterator cpit = cursorPar(); + if (cursor.pos() && cursor.pos() != cpit->size() + && cpit->isChangeEdited(0, cursor.pos())) return; LyXTextClass const & tclass = bv()->buffer()->params().getLyXTextClass(); - LyXLayout_ptr const & layout = cursorPar()->layout(); + LyXLayout_ptr const & layout = cpit->layout(); // this is only allowed, if the current paragraph is not empty or caption // and if it has not the keepempty flag active - if (cursorPar()->empty() && !cursorPar()->allowEmpty() + if (cpit->empty() && !cpit->allowEmpty() && layout->labeltype != LABEL_SENSITIVE) return; @@ -1211,9 +847,8 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout) // Always break behind a space // // It is better to erase the space (Dekel) - if (cursor.pos() < cursorPar()->size() - && cursorPar()->isLineSeparator(cursor.pos())) - cursorPar()->erase(cursor.pos()); + if (cursor.pos() < cpit->size() && cpit->isLineSeparator(cursor.pos())) + cpit->erase(cursor.pos()); // break the paragraph if (keep_layout) @@ -1225,21 +860,22 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout) // breakParagraph call should return a bool if it inserts the // paragraph before or behind and we should react on that one // but we can fix this in 1.3.0 (Jug 20020509) - bool const isempty = (cursorPar()->allowEmpty() && cursorPar()->empty()); - ::breakParagraph(bv()->buffer()->params(), paragraphs, cursorPar(), + bool const isempty = cpit->allowEmpty() && cpit->empty(); + ::breakParagraph(bv()->buffer()->params(), paragraphs, cpit, cursor.pos(), keep_layout); #warning Trouble Point! (Lgb) // When ::breakParagraph is called from within an inset we must // ensure that the correct ParagraphList is used. Today that is not // the case and the Buffer::paragraphs is used. Not good. (Lgb) - ParagraphList::iterator next_par = boost::next(cursorPar()); + cpit = cursorPar(); + ParagraphList::iterator next_par = boost::next(cpit); // well this is the caption hack since one caption is really enough if (layout->labeltype == LABEL_SENSITIVE) { if (!cursor.pos()) // set to standard-layout - cursorPar()->applyLayout(tclass.defaultLayout()); + cpit->applyLayout(tclass.defaultLayout()); else // set to standard-layout next_par->applyLayout(tclass.defaultLayout()); @@ -1249,8 +885,9 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout) // move one row up! // This touches only the screen-update. Otherwise we would may have // an empty row on the screen - if (cursor.pos() && cursorRow()->pos() == cursor.pos() - && !cursorPar()->isNewline(cursor.pos() - 1)) + RowList::iterator crit = cpit->getRow(cursor.pos()); + if (cursor.pos() && crit->pos() == cursor.pos() + && !cpit->isNewline(cursor.pos() - 1)) { cursorLeft(bv()); } @@ -1259,7 +896,7 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout) next_par->erase(0); updateCounters(); - redoParagraph(cursorPar()); + redoParagraph(cpit); redoParagraph(next_par); // This check is necessary. Otherwise the new empty paragraph will @@ -1267,7 +904,7 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout) if (cursor.pos() || isempty) setCursor(next_par, 0); else - setCursor(cursorPar(), 0); + setCursor(cpit, 0); } @@ -1335,7 +972,6 @@ void LyXText::insertChar(char c) } } - // First check, if there will be two blanks together or a blank at // the beginning of a paragraph. // I decided to handle blanks like normal characters, the main @@ -1388,7 +1024,7 @@ void LyXText::insertChar(char c) void LyXText::charInserted() { - // Here we could call finishUndo for every 20 characters inserted. + // Here we call finishUndo for every 20 characters inserted. // This is from my experience how emacs does it. (Lgb) static unsigned int counter; if (counter < 20) { @@ -1411,7 +1047,7 @@ void LyXText::prepareToPrint(ParagraphList::iterator pit, Row & row) const bool const is_rtl = pit->isRightToLeftPar(bv()->buffer()->params()); if (is_rtl) - x = workWidth() > 0 ? rightMargin(*pit, *bv()->buffer(), row) : 0; + x = workWidth() > 0 ? rightMargin(*pit, *bv()->buffer()) : 0; else x = workWidth() > 0 ? leftMargin(pit, row) : 0; @@ -1431,9 +1067,8 @@ void LyXText::prepareToPrint(ParagraphList::iterator pit, Row & row) const if (!pit->empty()) ++nlh; - if (nlh && !pit->getLabelWidthString().empty()) { + if (nlh && !pit->getLabelWidthString().empty()) fill_label_hfill = labelFill(pit, row) / double(nlh); - } } // are there any hfills in the row? @@ -1449,72 +1084,64 @@ void LyXText::prepareToPrint(ParagraphList::iterator pit, Row & row) const // is it block, flushleft or flushright? // set x how you need it int align; - if (pit->params().align() == LYX_ALIGN_LAYOUT) { + if (pit->params().align() == LYX_ALIGN_LAYOUT) align = layout->align; - } else { + else align = pit->params().align(); - } - InsetOld * inset = 0; - // ERT insets should always be LEFT ALIGNED on screen - inset = pit->inInset(); - if (inset && inset->owner() && - inset->owner()->lyxCode() == InsetOld::ERT_CODE) - { - align = LYX_ALIGN_LEFT; - } // Display-style insets should always be on a centred row // The test on pit->size() is to catch zero-size pars, which // would trigger the assert in Paragraph::getInset(). //inset = pit->size() ? pit->getInset(row.pos()) : 0; - inset = pit->isInset(row.pos()) ? pit->getInset(row.pos()) : 0; - if (inset && inset->display()) { + if (!pit->empty() + && pit->isInset(row.pos()) + && pit->getInset(row.pos())->display()) + { align = LYX_ALIGN_CENTER; } - + switch (align) { - case LYX_ALIGN_BLOCK: - { - int const ns = numberOfSeparators(*pit, row); - bool disp_inset = false; - if (row.endpos() < pit->size()) { - InsetOld * in = pit->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() < pit->size() - && !pit->isNewline(row.endpos()) - && !disp_inset - ) { - fill_separator = w / ns; - } else if (is_rtl) { - x += w; + case LYX_ALIGN_BLOCK: { + int const ns = numberOfSeparators(*pit, row); + bool disp_inset = false; + if (row.endpos() < pit->size()) { + InsetOld * in = pit->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() < pit->size() + && !pit->isNewline(row.endpos() - 1) + && !disp_inset + ) { + fill_separator = w / ns; + } else if (is_rtl) { + x += w; + } + break; } - break; - } - case LYX_ALIGN_RIGHT: + case LYX_ALIGN_RIGHT: x += w; break; - case LYX_ALIGN_CENTER: + case LYX_ALIGN_CENTER: x += w / 2; break; } } - computeBidiTables(*pit, *bv()->buffer(), row); + bidi.computeTables(*pit, *bv()->buffer(), row); if (is_rtl) { pos_type body_pos = pit->beginningOfBody(); - pos_type last = lastPos(*pit, row); + pos_type end = row.endpos(); - if (body_pos > 0 && - (body_pos - 1 > last || - !pit->isLineSeparator(body_pos - 1))) { + if (body_pos > 0 + && (body_pos > end || !pit->isLineSeparator(body_pos - 1))) + { x += font_metrics::width(layout->labelsep, getLabelFont(pit)); - if (body_pos - 1 <= last) + if (body_pos <= end) x += fill_label_hfill; } } @@ -1776,10 +1403,10 @@ void LyXText::deleteWordBackward() // Kill to end of line. void LyXText::deleteLineForward() { - if (cursorPar()->empty()) + if (cursorPar()->empty()) { // Paragraph is empty, so we just go to the right cursorRight(bv()); - else { + } else { LyXCursor tmpcursor = cursor; // We can't store the row over a regular setCursor // so we set it to 0 and reset it afterwards. @@ -1790,11 +1417,10 @@ void LyXText::deleteLineForward() cursor = tmpcursor; setSelection(); // What is this test for ??? (JMarc) - if (!selection.set()) { + if (!selection.set()) deleteWordForward(); - } else { + else cutSelection(true, false); - } } } @@ -1851,27 +1477,11 @@ void LyXText::changeCase(LyXText::TextCase action) void LyXText::Delete() { // this is a very easy implementation - LyXCursor old_cursor = cursor; - int const old_cur_par_id = cursorPar()->id(); - int const old_cur_par_prev_id = - old_cursor.par() ? getPar(old_cursor.par() - 1)->id() : -1; // just move to the right cursorRight(bv()); - // CHECK Look at the comment here. - // This check is not very good... - // The cursorRightIntern calls DeleteEmptyParagraphMechanism - // and that can very well delete the par or par->previous in - // old_cursor. Will a solution where we compare paragraph id's - //work better? - int iid = cursor.par() ? getPar(cursor.par() - 1)->id() : -1; - if (iid == old_cur_par_prev_id && cursorPar()->id() != old_cur_par_id) { - // delete-empty-paragraph-mechanism has done it - return; - } - // if you had success make a backspace if (old_cursor.par() != cursor.par() || old_cursor.pos() != cursor.pos()) { recordUndo(Undo::DELETE, this, old_cursor.par()); @@ -1910,9 +1520,7 @@ void LyXText::backspace() && cursorPar()->getAlign() == tmppit->getAlign()) { // Inherit bottom DTD from the paragraph below. // (the one we are deleting) - tmppit->params().lineBottom(cursorPar()->params().lineBottom()); tmppit->params().spaceBottom(cursorPar()->params().spaceBottom()); - tmppit->params().pagebreakBottom(cursorPar()->params().pagebreakBottom()); } cursorLeft(bv()); @@ -1945,18 +1553,18 @@ void LyXText::backspace() Buffer & buf = *bv()->buffer(); BufferParams const & bufparams = buf.params(); LyXTextClass const & tclass = bufparams.getLyXTextClass(); + ParagraphList::iterator const cpit = cursorPar(); - if (cursorPar() != tmppit - && (cursorPar()->layout() == tmppit->layout() - || tmppit->layout() == tclass.defaultLayout()) - && cursorPar()->getAlign() == tmppit->getAlign()) { - mergeParagraph(bufparams, - buf.paragraphs(), cursorPar()); + if (cpit != tmppit + && (cpit->layout() == tmppit->layout() + || tmppit->layout() == tclass.defaultLayout()) + && cpit->getAlign() == tmppit->getAlign()) { + mergeParagraph(bufparams, buf.paragraphs(), cpit); - if (cursor.pos() && cursorPar()->isSeparator(cursor.pos() - 1)) + if (cursor.pos() && cpit->isSeparator(cursor.pos() - 1)) cursor.pos(cursor.pos() - 1); - // the row may have changed, block, hfills etc. + // the counters may have changed updateCounters(); setCursor(cursor.par(), cursor.pos(), false); } @@ -1978,13 +1586,23 @@ void LyXText::backspace() setCurrentFont(); redoParagraph(); - setCursor(cursor.par(), cursor.pos(), false, !cursor.boundary()); + setCursor(cursor.par(), cursor.pos(), false, cursor.boundary()); } ParagraphList::iterator LyXText::cursorPar() const { - return getPar(cursor.par()); + if (cursor.par() != cache_pos_) { + cache_pos_ = cursor.par(); + cache_par_ = getPar(cache_pos_); + } + return cache_par_; +} + + +RowList::iterator LyXText::cursorRow() const +{ + return cursorPar()->getRow(cursor.pos()); } @@ -2004,36 +1622,23 @@ ParagraphList::iterator LyXText::getPar(int par) const } - -RowList::iterator LyXText::cursorRow() const -{ - return getRow(*cursorPar(), cursor.pos()); -} - - -RowList::iterator LyXText::getRow(LyXCursor const & cur) const -{ - return getRow(*getPar(cur), cur.pos()); -} - - -RowList::iterator LyXText::getRow(Paragraph & par, pos_type pos) const -{ - RowList::iterator rit = boost::prior(par.rows.end()); - RowList::iterator const begin = par.rows.begin(); - - while (rit != begin && rit->pos() > pos) - --rit; - - return rit; -} - - RowList::iterator LyXText::getRowNearY(int y, ParagraphList::iterator & pit) const { //lyxerr << "getRowNearY: y " << y << endl; +#if 0 + ParagraphList::iterator const pend = ownerParagraphs().end(); + pit = ownerParagraphs().begin(); + while (int(pit->y + pit->height) < y && pit != pend) + ++pit; + RowList::iterator rit = pit->rows.begin(); + RowList::iterator const rend = pit->rows.end(); + while (int(pit->y + rit->y_offset()) < y && rit != rend) + ++rit; + return rit; + +#else pit = boost::prior(ownerParagraphs().end()); RowList::iterator rit = lastRow(); @@ -2043,6 +1648,7 @@ LyXText::getRowNearY(int y, ParagraphList::iterator & pit) const previousRow(pit, rit); return rit; +#endif } @@ -2154,21 +1760,20 @@ void LyXText::redoParagraphInternal(ParagraphList::iterator pit) // rebreak the paragraph int const ww = workWidth(); - for (pos_type z = 0; z < pit->size() + 1; ) { + pos_type z = 0; + do { Row row(z); - z = rowBreakPoint(pit, row) + 1; - row.endpos(z); - int const f = fill(pit, row, ww); - unsigned int const w = ww - f; - pit->width = std::max(pit->width, w); - row.fill(f); - row.width(w); + rowBreakPoint(pit, row); + z = row.endpos(); + fill(pit, row, ww); prepareToPrint(pit, row); setHeightOfRow(pit, row); row.y_offset(pit->height); - pit->height += row.height(); pit->rows.push_back(row); - } + pit->width = std::max(pit->width, row.width()); + pit->height += row.height(); + } while (z < pit->size()); + height += pit->height; //lyxerr << "redoParagraph: " << pit->rows.size() << " rows\n"; } @@ -2200,10 +1805,9 @@ void LyXText::fullRebreak() void LyXText::metrics(MetricsInfo & mi, Dimension & dim) { - lyxerr << "LyXText::metrics: width: " << mi.base.textwidth - << " workWidth: " << workWidth() << "\nfont: " << mi.base.font << endl; + //lyxerr << "LyXText::metrics: width: " << mi.base.textwidth + // << " workWidth: " << workWidth() << "\nfont: " << mi.base.font << endl; //BOOST_ASSERT(mi.base.textwidth); - //anchor_y_ = 0; // rebuild row cache. This recomputes height as well. redoParagraphs(ownerParagraphs().begin(), ownerParagraphs().end());