-/* This file is part of
- * ======================================================
+/**
+ * \file text.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
*
- * LyX, The Document Processor
+ * \author Asger Alstrup
+ * \author Lars Gullik Bjønnes
+ * \author Jean-Marc Lasgouttes
+ * \author John Levon
+ * \author André Pönitz
+ * \author Dekel Tsur
+ * \author Jürgen Vigna
*
- * Copyright 1995 Matthias Ettrich
- * Copyright 1995-2001 The LyX Team.
- *
- * ====================================================== */
+ * Full author contact details are available in file CREDITS.
+ */
#include <config.h>
/// left margin
extern int const LEFT_MARGIN = PAPER_MARGIN + CHANGEBAR_MARGIN;
+
+
int bibitemMaxWidth(BufferView *, LyXFont const &);
void LyXText::updateRowPositions()
{
- RowList::iterator rit = rows().begin();
- RowList::iterator rend = rows().end();
- for (int y = 0; rit != rend ; ++rit) {
- rit->y(y);
- y += rit->height();
- }
-}
-
-
-int LyXText::top_y() const
-{
- if (anchor_row_ == rowlist_.end())
- return 0;
-
- return anchor_row_->y() + anchor_row_offset_;
-}
-
-
-void LyXText::top_y(int newy)
-{
- if (rows().empty())
- return;
-
- if (isInInset()) {
- anchor_row_ = rows().begin();
- anchor_row_offset_ = newy;
- return;
- }
-
- lyxerr[Debug::GUI] << "setting top y = " << newy << endl;
-
- int y = newy;
- RowList::iterator rit = getRowNearY(y);
-
- if (rit == anchor_row_ && anchor_row_offset_ == newy - y) {
- lyxerr[Debug::GUI] << "top_y to same value, skipping update" << endl;
- return;
+ ParagraphList::iterator pit = ownerParagraphs().begin();
+ ParagraphList::iterator end = ownerParagraphs().end();
+ for (height = 0; pit != end; ++pit) {
+ RowList::iterator rit = pit->rows.begin();
+ RowList::iterator rend = pit->rows.end();
+ for ( ; rit != rend ; rit = ++rit) {
+ rit->y(height);
+ height += rit->height();
+ }
}
-
- anchor_row_ = rit;
- anchor_row_offset_ = newy - y;
- lyxerr[Debug::GUI] << "changing reference to row: " << &*anchor_row_
- << " offset: " << anchor_row_offset_ << endl;
-}
-
-
-void LyXText::anchor_row(RowList::iterator rit)
-{
- int old_y = top_y();
- anchor_row_offset_ = 0;
- anchor_row_ = rit;
- anchor_row_offset_ = old_y - top_y();
- lyxerr[Debug::GUI] << "anchor_row(): changing reference to row: "
- << &*anchor_row_ << " offset: "
- << anchor_row_offset_ << endl;
}
return 0;
char const c = pit->getChar(pos);
- return singleWidth(pit, pos, c);
+ LyXFont const & font = getFont(pit, pos);
+ return singleWidth(pit, pos, c, font);
}
int LyXText::singleWidth(ParagraphList::iterator pit,
- pos_type pos, char c) const
+ pos_type pos, char c, LyXFont const & font) const
{
- if (pos >= pit->size())
+ if (pos >= pit->size()) {
+ lyxerr << "in singleWidth(), pos: " << pos << endl;
+ Assert(false);
return 0;
+ }
- LyXFont const & font = getFont(pit, pos);
// The most common case is handled first (Asger)
if (IsPrintable(c)) {
if (c == Paragraph::META_INSET) {
InsetOld * tmpinset = pit->getInset(pos);
- if (tmpinset) {
- if (tmpinset->lyxCode() == InsetOld::HFILL_CODE) {
- // Because of the representation as vertical lines
- return 3;
- }
-#if 0
-#warning enabling this fixes the 'insets of width 0 on load' problem
- // this IS needed otherwise on initialitation we don't get the fill
- // of the row right (ONLY on initialization if we read a file!)
- // should be changed! (Jug 20011204)
- //tmpinset->update(bv());
- Dimension dim;
- MetricsInfo mi(bv(), font, workWidth());
- tmpinset->metrics(mi, dim);
- return dim.wid;
-#else
- return tmpinset->width();
-#endif
+ Assert(tmpinset);
+ if (tmpinset->lyxCode() == InsetOld::HFILL_CODE) {
+ // Because of the representation as vertical lines
+ return 3;
}
- return 0;
+ return tmpinset->width();
}
if (IsSeparatorChar(c))
}
-void LyXText::computeBidiTables(ParagraphList::iterator row_par,
- Buffer const * buf, RowList::iterator row) const
+void LyXText::computeBidiTables(ParagraphList::iterator pit,
+ Buffer const & buf, RowList::iterator row) const
{
bidi_same_direction = true;
if (!lyxrc.rtl_support) {
return;
}
- InsetOld * inset = row_par->inInset();
+ InsetOld * inset = pit->inInset();
if (inset && inset->owner() &&
inset->owner()->lyxCode() == InsetOld::ERT_CODE) {
bidi_start = -1;
}
bidi_start = row->pos();
- bidi_end = lastPrintablePos(*this, row_par, row);
+ bidi_end = lastPrintablePos(*pit, row);
if (bidi_start > bidi_end) {
bidi_start = -1;
pos_type stack[2];
bool const rtl_par =
- row_par->isRightToLeftPar(buf->params);
+ pit->isRightToLeftPar(buf.params);
int level = 0;
bool rtl = false;
bool rtl0 = false;
- pos_type const body_pos = row_par->beginningOfBody();
+ pos_type const body_pos = pit->beginningOfBody();
for (pos_type lpos = bidi_start; lpos <= bidi_end; ++lpos) {
- bool is_space = row_par->isLineSeparator(lpos);
+ bool is_space = pit->isLineSeparator(lpos);
pos_type const pos =
(is_space && lpos + 1 <= bidi_end &&
- !row_par->isLineSeparator(lpos + 1) &&
- !row_par->isNewline(lpos + 1))
+ !pit->isLineSeparator(lpos + 1) &&
+ !pit->isNewline(lpos + 1))
? lpos + 1 : lpos;
- LyXFont font = row_par->getFontSettings(buf->params, pos);
+ LyXFont font = pit->getFontSettings(buf.params, pos);
if (pos != lpos && 0 < lpos && rtl0 && font.isRightToLeft() &&
font.number() == LyXFont::ON &&
- row_par->getFontSettings(buf->params, lpos - 1).number()
+ pit->getFontSettings(buf.params, lpos - 1).number()
== LyXFont::ON) {
- font = row_par->getFontSettings(buf->params, lpos);
+ font = pit->getFontSettings(buf.params, lpos);
is_space = false;
}
// This method requires a previous call to ComputeBidiTables()
-bool LyXText::isBoundary(Buffer const * buf, Paragraph const & par,
+bool LyXText::isBoundary(Buffer const & buf, Paragraph const & par,
pos_type pos) const
{
if (!lyxrc.rtl_support || pos == 0)
bool const rtl = bidi_level(pos - 1) % 2;
bool const rtl2 = bidi_InRange(pos)
? bidi_level(pos) % 2
- : par.isRightToLeftPar(buf->params);
+ : par.isRightToLeftPar(buf.params);
return rtl != rtl2;
}
-bool LyXText::isBoundary(Buffer const * buf, Paragraph const & par,
+bool LyXText::isBoundary(Buffer const & buf, Paragraph const & par,
pos_type pos, LyXFont const & font) const
{
if (!lyxrc.rtl_support)
bool const rtl = font.isVisibleRightToLeft();
bool const rtl2 = bidi_InRange(pos)
? bidi_level(pos) % 2
- : par.isRightToLeftPar(buf->params);
+ : par.isRightToLeftPar(buf.params);
return rtl != rtl2;
}
int LyXText::leftMargin(ParagraphList::iterator pit, Row const & row) const
{
- InsetOld * ins;
-
- if (row.pos() < pit->size())
- if (pit->getChar(row.pos()) == Paragraph::META_INSET &&
- (ins = pit->getInset(row.pos())) &&
- (ins->needFullRow() || ins->display()))
- return LEFT_MARGIN;
-
LyXTextClass const & tclass =
bv()->buffer()->params.getLyXTextClass();
LyXLayout_ptr const & layout = pit->layout();
// are *NOT* allowed in the LaTeX realisation of this layout.
// find the first row of this paragraph
- RowList::iterator rit = beginRow(pit);
- RowList::iterator end = endRow(pit);
+ RowList::iterator rit = pit->rows.begin();
+ RowList::iterator end = pit->rows.end();
int minfill = rit->fill();
for ( ; rit != end; ++rit)
if (rit->fill() < minfill)
int LyXText::rightMargin(ParagraphList::iterator pit,
- Buffer const & buf, Row const & row) const
+ Buffer const & buf, Row const &) const
{
- InsetOld * ins;
-
- if (row.pos() < pit->size())
- if ((pit->getChar(row.pos()) == Paragraph::META_INSET) &&
- (ins = pit->getInset(row.pos())) &&
- (ins->needFullRow() || ins->display()))
- return PAPER_MARGIN;
-
LyXTextClass const & tclass = buf.params.getLyXTextClass();
LyXLayout_ptr const & layout = pit->layout();
Row const & row) const
{
// maximum pixel width of a row.
- int width = workWidth() - rightMargin(pit, *bv()->buffer(), row);
+ int width = workWidth()
+ - rightMargin(pit, *bv()->buffer(), row);
// inset->textWidth() returns -1 via workWidth(),
// but why ?
// pixel width since last breakpoint
int chunkwidth = 0;
- bool fullrow = false;
pos_type i = pos;
}
char const c = pit->getChar(i);
+ if (i > endPosOfFontSpan) {
+ font = getFont(pit, i);
+ endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
+ }
int thiswidth;
int left_margin = labelEnd(pit, row);
if (thiswidth + x < left_margin)
thiswidth = left_margin - x;
- thiswidth += singleWidth(pit, i, c);
+ thiswidth += singleWidth(pit, i, c, font);
} else {
- // Manual inlined optimised version of common case of "thiswidth = singleWidth(pit, i, c);"
- if (IsPrintable(c)) {
- if (pos > endPosOfFontSpan) {
- // We need to get the next font
- font = getFont(pit, i);
- endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
- }
- if (! font.language()->RightToLeft()) {
- thiswidth = font_metrics::width(c, font);
- } else {
- // Fall-back to normal case
- thiswidth = singleWidth(pit, i, c);
- // And flush font cache
- endPosOfFontSpan = 0;
- }
- } else {
- // Fall-back to normal case
- thiswidth = singleWidth(pit, i, c);
- // And flush font cache
- endPosOfFontSpan = 0;
- }
+ thiswidth = singleWidth(pit, i, c, font);
}
x += thiswidth;
chunkwidth += thiswidth;
InsetOld * in = pit->isInset(i) ? pit->getInset(i) : 0;
- fullrow = in && (in->display() || in->needFullRow());
// break before a character that will fall off
// the right of the row
if (x >= width) {
- // if no break before or we are at an inset
- // that will take up a row, break here
- if (point == last || fullrow || chunkwidth >= (width - left)) {
+ // if no break before, break here
+ if (point == last || chunkwidth >= (width - left)) {
if (pos < i)
point = i - 1;
else
continue;
}
- if (!fullrow)
- continue;
-
- // full row insets start at a new row
- if (i == pos) {
- if (pos < last - 1) {
- point = i;
- if (pit->isLineSeparator(i + 1))
- ++point;
- } else {
- // to avoid extra rows
- point = last;
- }
- } else {
- point = i - 1;
- }
-
- return point;
+ continue;
}
if (point == last && x >= width) {
// manual labels cannot be broken in LaTeX. But we
// want to make our on-screen rendering of footnotes
// etc. still break
- if (!fullrow && body_pos && point < body_pos)
+ if (body_pos && point < body_pos)
point = body_pos - 1;
return point;
int w;
// get the pure distance
- pos_type const last = lastPrintablePos(*this, pit, row);
+ pos_type const last = lastPrintablePos(*pit, row);
LyXLayout_ptr const & layout = pit->layout();
if (w < left_margin)
w = left_margin;
}
- { // Manual inlined an optimised version of the common case of "w += singleWidth(pit, i);"
- char const c = pit->getChar(i);
-
- if (IsPrintable(c)) {
- if (i > endPosOfFontSpan) {
- // We need to get the next font
- font = getFont(pit, i);
- endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
- }
- if (!font.language()->RightToLeft()) {
- w += font_metrics::width(c, font);
- } else {
- // Fall-back to the normal case
- w += singleWidth(pit, i, c);
- // And flush font cache
- endPosOfFontSpan = 0;
- }
- } else {
- // Fall-back to the normal case
- w += singleWidth(pit, i, c);
- // And flush font cache
- endPosOfFontSpan = 0;
- }
+ char const c = pit->getChar(i);
+ if (IsPrintable(c) && i > endPosOfFontSpan) {
+ // We need to get the next font
+ font = getFont(pit, i);
+ endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
}
+ w += singleWidth(pit, i, c, font);
++i;
}
}
void LyXText::setHeightOfRow(ParagraphList::iterator pit, RowList::iterator rit)
{
- Assert(rit != rows().end());
-
// get the maximum ascent and the maximum descent
double layoutasc = 0;
double layoutdesc = 0;
int maxdesc = int(font_metrics::maxDescent(font) *
layout->spacing.getValue() * spacing_val);
- pos_type const pos_end = lastPos(*this, pit, rit);
+ pos_type const pos_end = lastPos(*pit, rit);
int labeladdon = 0;
int maxwidth = 0;
maxwidth += font_metrics::width(c, font);
} else {
// Fall-back to normal case
- maxwidth += singleWidth(pit, pos, c);
+ maxwidth += singleWidth(pit, pos, c, font);
// And flush font cache
endPosOfFontSpan = 0;
}
if (par.isInset(pos)) {
InsetOld const * tmpinset = par.getInset(pos);
if (tmpinset) {
-#if 1 // this is needed for deep update on initialitation
-#warning inset->update FIXME
- //tmpinset->update(bv());
- LyXFont const tmpfont = getFont(pit, pos);
- Dimension dim;
- MetricsInfo mi(bv(), tmpfont, workWidth());
- tmpinset->metrics(mi, dim);
- maxwidth += dim.wid;
- maxasc = max(maxasc, dim.asc);
- maxdesc = max(maxdesc, dim.des);
-#else
maxwidth += tmpinset->width();
maxasc = max(maxasc, tmpinset->ascent());
maxdesc = max(maxdesc, tmpinset->descent());
-#endif
}
} else {
// Fall-back to normal case
- maxwidth += singleWidth(pit, pos, c);
+ maxwidth += singleWidth(pit, pos, c, font);
// And flush font cache
endPosOfFontSpan = 0;
}
prev->getLabelWidthString() == pit->getLabelWidthString())
{
layoutasc = (layout->itemsep * defaultRowHeight());
- } else if (rit != rows().begin()) {
+ } else if (rit != firstRow()) {
tmptop = layout->topsep;
- if (boost::prior(pit)->getDepth() >= pit->getDepth()) {
- tmptop -= getPar(boost::prior(rit))->layout()->bottomsep;
- }
+ //if (boost::prior(pit)->getDepth() >= pit->getDepth())
+ // tmptop -= getPar(previousRow(rit))->layout()->bottomsep;
if (tmptop > 0)
layoutasc = (tmptop * defaultRowHeight());
}
// is it a bottom line?
- if (boost::next(rit) == endRow(pit)) {
+ if (boost::next(rit) == pit->rows.end()) {
// the bottom margin
ParagraphList::iterator nextpit = boost::next(pit);
- if (nextpit == ownerParagraphs().end() &&
- !isInInset())
+ if (nextpit == ownerParagraphs().end() && !isInInset())
maxdesc += PAPER_MARGIN;
// add the vertical spaces, that the user added
maxasc += int(layoutasc * 2 / (2 + pit->getDepth()));
maxdesc += int(layoutdesc * 2 / (2 + pit->getDepth()));
- // calculate the new height of the text
- height -= rit->height();
-
rit->height(maxasc + maxdesc + labeladdon);
rit->baseline(maxasc + labeladdon);
-
- height += rit->height();
-
rit->top_of_text(rit->baseline() - font_metrics::maxAscent(font));
double x = 0;
- if (layout->margintype != MARGIN_RIGHT_ADDRESS_BOX) {
- // this IS needed
- rit->width(maxwidth);
- double dummy;
- prepareToPrint(pit, rit, x, dummy, dummy, dummy, false);
- }
rit->width(int(maxwidth + x));
if (inset_owner) {
width = max(0, workWidth());
- RowList::iterator it = rows().begin();
- RowList::iterator end = rows().end();
- for (; it != end; ++it)
- if (it->width() > width)
- width = it->width();
+ RowList::iterator rit = firstRow();
+ RowList::iterator end = endRow();
+ ParagraphList::iterator it = ownerParagraphs().begin();
+ while (rit != end) {
+ if (rit->width() > width)
+ width = rit->width();
+ nextRow(it, rit);
+ }
}
}
::breakParagraph(bv()->buffer()->params, paragraphs, cursor.par(),
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(cursor.par());
+
// well this is the caption hack since one caption is really enough
if (layout->labeltype == LABEL_SENSITIVE) {
if (!cursor.pos())
cursor.par()->applyLayout(tclass.defaultLayout());
else
// set to standard-layout
- boost::next(cursor.par())->applyLayout(tclass.defaultLayout());
+ next_par->applyLayout(tclass.defaultLayout());
}
// if the cursor is at the beginning of a row without prior newline,
cursorLeft(bv());
}
- removeParagraph(cursor.par(), cursorRow());
-
-#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(cursor.par());
-
while (!next_par->empty() && next_par->isNewline(0))
next_par->erase(0);
- insertParagraph(next_par, boost::next(cursorRow()));
updateCounters();
+ redoParagraph(cursor.par());
+ redoParagraph(next_par);
// This check is necessary. Otherwise the new empty paragraph will
// be deleted automatically. And it is more friendly for the user!
setCursor(next_par, 0);
else
setCursor(cursor.par(), 0);
-
- redoParagraph(cursor.par());
}
void LyXText::charInserted()
{
- // Here we could call FinishUndo for every 20 characters inserted.
+ // Here we could call finishUndo for every 20 characters inserted.
// This is from my experience how emacs does it. (Lgb)
static unsigned int counter;
if (counter < 20) {
void LyXText::prepareToPrint(ParagraphList::iterator pit,
- RowList::iterator rit, double & x,
- double & fill_separator,
- double & fill_hfill,
- double & fill_label_hfill,
- bool bidi) const
+ RowList::iterator const rit) const
{
double w = rit->fill();
- fill_hfill = 0;
- fill_label_hfill = 0;
- fill_separator = 0;
- fill_label_hfill = 0;
+ double fill_hfill = 0;
+ double fill_label_hfill = 0;
+ double fill_separator = 0;
+ double x = 0;
bool const is_rtl =
pit->isRightToLeftPar(bv()->buffer()->params);
if (layout->margintype == MARGIN_MANUAL
&& layout->labeltype == LABEL_MANUAL) {
/// We might have real hfills in the label part
- int nlh = numberOfLabelHfills(*this, pit, rit);
+ int nlh = numberOfLabelHfills(*pit, rit);
// A manual label par (e.g. List) has an auto-hfill
// between the label text and the body of the
}
// are there any hfills in the row?
- int const nh = numberOfHfills(*this, pit, rit);
+ int const nh = numberOfHfills(*pit, rit);
if (nh) {
if (w > 0)
} else {
align = pit->params().align();
}
-
- // center displayed insets
InsetOld * inset = 0;
- if (rit->pos() < pit->size()
- && pit->isInset(rit->pos())
- && (inset = pit->getInset(rit->pos()))
- && (inset->display())) // || (inset->scroll() < 0)))
- align = (inset->lyxCode() == InsetOld::MATHMACRO_CODE)
- ? LYX_ALIGN_BLOCK : LYX_ALIGN_CENTER;
// ERT insets should always be LEFT ALIGNED on screen
inset = pit->inInset();
if (inset && inset->owner() &&
switch (align) {
case LYX_ALIGN_BLOCK:
- {
- int const ns = numberOfSeparators(*this, pit, rit);
+ {
+ int const ns = numberOfSeparators(*pit, rit);
RowList::iterator next_row = boost::next(rit);
if (ns
- && next_row != endRow(pit)
+ && next_row != pit->rows.end()
&& !pit->isNewline(next_row->pos() - 1)
- && !(pit->isInset(next_row->pos())
- && pit->getInset(next_row->pos())
- && pit->getInset(next_row->pos())->display())
) {
- fill_separator = w / ns;
+ fill_separator = w / ns;
} else if (is_rtl) {
x += w;
}
break;
}
}
- if (!bidi)
- return;
- computeBidiTables(pit, bv()->buffer(), rit);
+ computeBidiTables(pit, *bv()->buffer(), rit);
if (is_rtl) {
pos_type body_pos = pit->beginningOfBody();
- pos_type last = lastPos(*this, pit, rit);
+ pos_type last = lastPos(*pit, rit);
if (body_pos > 0 &&
- (body_pos - 1 > last ||
- !pit->isLineSeparator(body_pos - 1))) {
+ (body_pos - 1 > last ||
+ !pit->isLineSeparator(body_pos - 1))) {
x += font_metrics::width(layout->labelsep, getLabelFont(pit));
if (body_pos - 1 <= last)
x += fill_label_hfill;
}
}
+
+ rit->fill_hfill(fill_hfill);
+ rit->fill_label_hfill(fill_label_hfill);
+ rit->fill_separator(fill_separator);
+ rit->x(x);
}
cursorLeft(bv());
// the layout things can change the height of a row !
- setHeightOfRow(cursor.par(), cursorRow());
+ redoParagraph();
return;
}
}
}
ParagraphList::iterator tmppit = cursor.par();
- RowList::iterator tmprow = cursorRow();
-
// We used to do cursorLeftIntern() here, but it is
// not a good idea since it triggers the auto-delete
// mechanism. So we do a cursorLeftIntern()-lite,
// Pasting is not allowed, if the paragraphs have different
// layout. I think it is a real bug of all other
// word processors to allow it. It confuses the user.
- //Correction: Pasting is always allowed with standard-layout
+ // Correction: Pasting is always allowed with standard-layout
LyXTextClass const & tclass =
bv()->buffer()->params.getLyXTextClass();
&& (cursor.par()->layout() == tmppit->layout()
|| tmppit->layout() == tclass.defaultLayout())
&& cursor.par()->getAlign() == tmppit->getAlign()) {
- removeParagraph(cursor.par(), tmprow);
- removeRow(tmprow);
mergeParagraph(bv()->buffer()->params,
bv()->buffer()->paragraphs, cursor.par());
RowList::iterator
LyXText::getRow(ParagraphList::iterator pit, pos_type pos) const
{
- RowList::iterator rit = beginRow(pit);
- RowList::iterator end = endRow(pit);
-
-#warning Why is this next thing needed? (Andre)
- while (rit != end
- && rit->pos() < pos
- && boost::next(rit) != end
- && boost::next(rit)->pos() <= pos)
- ++rit;
-
- return rit;
-}
+ RowList::iterator rit = boost::prior(pit->rows.end());
+ RowList::iterator const begin = pit->rows.begin();
-
-// returns pointer to a specified row
-RowList::iterator
-LyXText::getRow(ParagraphList::iterator pit, pos_type pos, int & y) const
-{
- y = 0;
-
- if (rows().empty())
- return firstRow();
-
- RowList::iterator beg = beginRow(pit);
- RowList::iterator end = endRow(pit);
- RowList::iterator rit;
-
- // find the first row of the specified paragraph
- for (rit = firstRow(); rit != beg; rit = nextRow(rit))
- y += rit->height();
-
- // now find the wanted row
- while (rit != end
- && rit->pos() < pos
- && boost::next(rit) != end
- && boost::next(rit)->pos() <= pos) {
- y += rit->height();
- ++rit;
- }
+ while (rit != begin && rit->pos() > pos)
+ --rit;
return rit;
}
// returns pointer to some fancy row 'below' specified row
RowList::iterator LyXText::cursorIRow() const
{
- int y = 0;
- return getRow(cursor.par(), cursor.pos(), y);
+ return getRow(cursor.par(), cursor.pos());
}
-RowList::iterator LyXText::getRowNearY(int & y) const
+RowList::iterator LyXText::getRowNearY(int y,
+ ParagraphList::iterator & pit) const
{
- RowList::iterator rit = anchor_row_;
- RowList::iterator const beg = rows().begin();
- RowList::iterator const end = rows().end();
+ //lyxerr << "getRowNearY: y " << y << endl;
- if (rows().empty()) {
- y = 0;
- return end;
- }
- if (rit == end)
- rit = beg;
+ pit = boost::prior(ownerParagraphs().end());
- int tmpy = rit->y();
+ RowList::iterator rit = lastRow();
+ RowList::iterator rbegin = firstRow();
- if (tmpy <= y) {
- while (rit != end && tmpy <= y) {
- tmpy += rit->height();
- ++rit;
- }
- if (rit != beg) {
- --rit;
- tmpy -= rit->height();
- }
- } else {
- while (rit != beg && tmpy > y) {
- --rit;
- tmpy -= rit->height();
- }
- }
- if (tmpy < 0 || rit == end) {
- tmpy = 0;
- rit = beg;
- }
-
- // return the rel y
- y = tmpy;
+ while (rit != rbegin && static_cast<int>(rit->y()) > y)
+ previousRow(pit, rit);
return rit;
}
}
-#warning Expensive. Remove before 1.4!
-// computes a ParagraphList::iterator from RowList::iterator by
-// counting zeros in the sequence of pos values.
-
-ParagraphList::iterator LyXText::getPar(RowList::iterator row) const
-{
- if (row == rows().end()) {
- lyxerr << "getPar() pit at end " << endl;
- Assert(false);
- }
-
- if (row == rows().begin()) {
- return ownerParagraphs().begin();
- }
-
- ParagraphList::iterator pit = ownerParagraphs().begin();
- RowList::iterator rit = rows().begin();
- RowList::iterator rend = rows().end();
- for (++rit ; rit != rend; ++rit) {
- if (rit->pos() == 0) {
- ++pit;
- if (pit == ownerParagraphs().end()) {
- lyxerr << "unexpected in LyXText::getPar()" << endl;
- Assert(false);
- }
- }
- if (rit == row) {
- return pit;
- }
- }
-
- lyxerr << "LyXText::getPar: row not found " << endl;
- Assert(false);
- return ownerParagraphs().end(); // shut up compiler
-}
-
-
-RowList::iterator LyXText::beginRow(ParagraphList::iterator pit) const
+RowList::iterator LyXText::firstRow() const
{
- int n = std::distance(ownerParagraphs().begin(), pit);
-
- RowList::iterator rit = rows().begin();
- RowList::iterator end = rows().end();
- for ( ; rit != end; ++rit)
- if (rit->pos() == 0 && n-- == 0)
- return rit;
-
- return rit;
+ return ownerParagraphs().front().rows.begin();
}
-RowList::iterator LyXText::endRow(ParagraphList::iterator pit) const
+RowList::iterator LyXText::lastRow() const
{
- return beginRow(boost::next(pit));
+ return boost::prior(endRow());
}
-RowList::iterator LyXText::firstRow() const
+RowList::iterator LyXText::endRow() const
{
- return rowlist_.begin();
+ return ownerParagraphs().back().rows.end();
}
-RowList::iterator LyXText::lastRow() const
+void LyXText::nextRow(ParagraphList::iterator & pit,
+ RowList::iterator & rit) const
{
- return boost::prior(rowlist_.end());
+ ++rit;
+ if (rit == pit->rows.end()) {
+ ++pit;
+ if (pit == ownerParagraphs().end())
+ --pit;
+ else
+ rit = pit->rows.begin();
+ }
}
-RowList::iterator LyXText::nextRow(RowList::iterator rit) const
+void LyXText::previousRow(ParagraphList::iterator & pit,
+ RowList::iterator & rit) const
{
- return boost::next(rit);
+ if (rit != pit->rows.begin())
+ --rit;
+ else {
+ Assert(pit != ownerParagraphs().begin());
+ --pit;
+ rit = boost::prior(pit->rows.end());
+ }
}
-RowList::iterator LyXText::previousRow(RowList::iterator rit) const
+bool LyXText::noRows() const
{
- return boost::prior(rit);
+ return ownerParagraphs().begin()->rows.empty();
}