/** * \file lyxrow.C * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * * \author unknown * * Full author contact details are available in file CREDITS * * Metrics for an on-screen text row. */ #include #include "lyxrow.h" #include "paragraph.h" #include "layout.h" #include "lyxlayout.h" using lyx::pos_type; using std::max; using std::min; Row::Row() : par_(0), pos_(0), fill_(0), height_(0), width_(0), ascent_of_text_(0), baseline_(0), next_(0), previous_(0) {} void Row::par(Paragraph * p) { par_ = p; } void Row::pos(pos_type p) { pos_ = p; } pos_type Row::pos() const { return pos_; } void Row::fill(int f) { fill_ = f; } int Row::fill() const { return fill_; } void Row::height(unsigned short h) { height_ = h; } void Row::width(unsigned int w) { width_ = w; } unsigned int Row::width() const { return width_; } void Row::ascent_of_text(unsigned short a) { ascent_of_text_ = a; } unsigned short Row::ascent_of_text() const { return ascent_of_text_; } void Row::top_of_text(unsigned int top) { top_of_text_ = top; } unsigned int Row::top_of_text() const { return top_of_text_; } void Row::baseline(unsigned int b) { baseline_ = b; } unsigned int Row::baseline() const { return baseline_; } void Row::next(Row * r) { next_ = r; } void Row::previous(Row * r) { previous_ = r; } Row * Row::previous() const { return previous_; } pos_type Row::lastPos() const { if (!par()->size()) return 0; if (!next() || next()->par() != par()) { return par()->size() - 1; } else { return next()->pos() - 1; } } namespace { bool nextRowIsAllInset(Row const & row, pos_type last) { if (!row.par()->isInset(last + 1)) return false; Inset * i = row.par()->getInset(last + 1); return i->needFullRow() || i->display(); } }; pos_type Row::lastPrintablePos() const { pos_type const last = lastPos(); // if this row is an end of par, just act like lastPos() if (!next() || par() != next()->par()) return last; bool const nextrownotinset = !nextRowIsAllInset(*this, last); if (nextrownotinset && par()->isSeparator(last)) return last - 1; return last; } int Row::numberOfSeparators() const { pos_type const last = lastPrintablePos(); pos_type p = max(pos(), par()->beginningOfMainBody()); int n = 0; for (; p <= last; ++p) { if (par()->isSeparator(p)) { ++n; } } return n; } int Row::numberOfHfills() const { pos_type const last = lastPos(); pos_type first = pos(); // hfill *DO* count at the beginning of paragraphs! if (first) { while (first <= last && par()->isHfill(first)) { ++first; } } first = max(first, par()->beginningOfMainBody()); int n = 0; // last, because the end is ignored! for (pos_type p = first; p <= last; ++p) { if (par()->isHfill(p)) ++n; } return n; } int Row::numberOfLabelHfills() const { pos_type last = lastPos(); pos_type first = pos(); // hfill *DO* count at the beginning of paragraphs! if (first) { while (first < last && par()->isHfill(first)) ++first; } last = min(last, par()->beginningOfMainBody()); int n = 0; // last, because the end is ignored! for (pos_type p = first; p < last; ++p) { if (par()->isHfill(p)) ++n; } return n; } bool Row::hfillExpansion(pos_type pos) const { if (!par()->isHfill(pos)) return false; // at the end of a row it does not count // unless another hfill exists on the line if (pos >= lastPos()) { pos_type i = this->pos(); while (i < pos && !par()->isHfill(i)) { ++i; } if (i == pos) { return false; } } // at the beginning of a row it does not count, if it is not // the first row of a paragaph if (!this->pos()) return true; // in some labels it does not count if (par()->layout()->margintype != MARGIN_MANUAL && pos < par()->beginningOfMainBody()) return false; // if there is anything between the first char of the row and // the sepcified position that is not a newline and not a hfill, // the hfill will count, otherwise not pos_type i = this->pos(); while (i < pos && (par()->isNewline(i) || par()->isHfill(i))) ++i; return i != pos; }