mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
145af7c2ac
The code is not ready for situations where some paragraphs that are
not visible have metrics available. This has been made visible by
a4d9315b
, which removes a couple of full metrics updates: the screen
was not correctly scrolled after a scrollToCursor() call.
In PararagraphMetrics, some methods are added to be able to handle the
fact that paragraphs have or do not have a position.
In TextMetrics, a new method returns the first visible paragraph.
Finally, in BufferView::updateMetrics, the paragraphs' positions are
reset (in the case where everything is not cleared) and some care is
taken to skip the ones that are not relevant.
The assumption outside of this method is that all the paragraphs that
are in the TextMetrics are visible (we are talking about top-level
TextMetrics here). This could be changed (in order to avoid
recomputing paragraph metrics), but the cost is high in terms of
complexity and it is not clear that the gain in terms of performance
would be important.
186 lines
3.9 KiB
C++
186 lines
3.9 KiB
C++
/**
|
|
* \file Paragraph.cpp
|
|
* This file is part of LyX, the document processor.
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* \author Asger Alstrup
|
|
* \author Lars Gullik Bjønnes
|
|
* \author Jean-Marc Lasgouttes
|
|
* \author Angus Leeming
|
|
* \author John Levon
|
|
* \author André Pönitz
|
|
* \author Dekel Tsur
|
|
* \author Jürgen Vigna
|
|
*
|
|
* Full author contact details are available in file CREDITS.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "ParagraphMetrics.h"
|
|
|
|
#include "Buffer.h"
|
|
#include "BufferParams.h"
|
|
#include "BufferView.h"
|
|
#include "Font.h"
|
|
#include "Layout.h"
|
|
#include "LayoutEnums.h"
|
|
#include "Paragraph.h"
|
|
#include "TextClass.h"
|
|
|
|
#include "frontends/FontMetrics.h"
|
|
|
|
#include "support/lassert.h"
|
|
#include "support/debug.h"
|
|
|
|
#include <sstream>
|
|
|
|
using namespace std;
|
|
using namespace lyx::support;
|
|
|
|
namespace lyx {
|
|
|
|
const int pm_npos = -10000;
|
|
|
|
ParagraphMetrics::ParagraphMetrics(Paragraph const & par) :
|
|
position_(pm_npos), id_(par.id()), par_(&par)
|
|
{}
|
|
|
|
|
|
ParagraphMetrics & ParagraphMetrics::operator=(
|
|
ParagraphMetrics const & pm)
|
|
{
|
|
rows_ = pm.rows_;
|
|
dim_ = pm.dim_;
|
|
par_ = pm.par_;
|
|
position_ = pm.position_;
|
|
return *this;
|
|
}
|
|
|
|
|
|
void ParagraphMetrics::reset(Paragraph const & par)
|
|
{
|
|
par_ = ∥
|
|
dim_ = Dimension();
|
|
//position_ = pm_npos;
|
|
}
|
|
|
|
|
|
int ParagraphMetrics::position() const
|
|
{
|
|
LASSERT(hasPosition(), return pm_npos);
|
|
return position_;
|
|
}
|
|
|
|
|
|
void ParagraphMetrics::setPosition(int position)
|
|
{
|
|
position_ = position;
|
|
}
|
|
|
|
|
|
void ParagraphMetrics::resetPosition()
|
|
{
|
|
position_ = pm_npos;
|
|
}
|
|
|
|
|
|
bool ParagraphMetrics::hasPosition() const
|
|
{
|
|
return position_ != pm_npos;
|
|
}
|
|
|
|
|
|
Row const & ParagraphMetrics::getRow(pos_type pos, bool boundary) const
|
|
{
|
|
LBUFERR(!rows().empty());
|
|
|
|
// If boundary is set we should return the row on which
|
|
// the character before is inside.
|
|
if (pos > 0 && boundary)
|
|
--pos;
|
|
|
|
RowList::const_iterator rit = rows_.end();
|
|
RowList::const_iterator const begin = rows_.begin();
|
|
|
|
for (--rit; rit != begin && rit->pos() > pos; --rit)
|
|
;
|
|
|
|
return *rit;
|
|
}
|
|
|
|
|
|
size_t ParagraphMetrics::pos2row(pos_type pos) const
|
|
{
|
|
LBUFERR(!rows().empty());
|
|
|
|
RowList::const_iterator rit = rows_.end();
|
|
RowList::const_iterator const begin = rows_.begin();
|
|
|
|
for (--rit; rit != begin && rit->pos() > pos; --rit)
|
|
;
|
|
|
|
return rit - begin;
|
|
}
|
|
|
|
|
|
void ParagraphMetrics::dump() const
|
|
{
|
|
lyxerr << "Paragraph::dump: rows.size(): " << rows_.size() << endl;
|
|
for (size_t i = 0; i != rows_.size(); ++i) {
|
|
lyxerr << " row " << i << ": " << rows_[i];
|
|
}
|
|
}
|
|
|
|
int ParagraphMetrics::rightMargin(BufferView const & bv) const
|
|
{
|
|
BufferParams const & params = bv.buffer().params();
|
|
DocumentClass const & tclass = params.documentClass();
|
|
frontend::FontMetrics const & fm = theFontMetrics(params.getFont());
|
|
int const r_margin =
|
|
bv.rightMargin()
|
|
+ fm.signedWidth(tclass.rightmargin())
|
|
+ fm.signedWidth(par_->layout().rightmargin)
|
|
* 4 / (par_->getDepth() + 4);
|
|
|
|
return r_margin;
|
|
}
|
|
|
|
|
|
// FIXME: this code seems bogus. Audit and rewrite (see bug #9860).
|
|
bool ParagraphMetrics::hfillExpansion(Row const & row, pos_type pos) const
|
|
{
|
|
if (!par_->isHfill(pos))
|
|
return false;
|
|
|
|
LASSERT(pos >= row.pos() && pos < row.endpos(), return false);
|
|
|
|
// expand at the end of a row only if there is another hfill on the same row
|
|
if (pos == row.endpos() - 1) {
|
|
for (pos_type i = row.pos(); i < pos; i++) {
|
|
if (par_->isHfill(i))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// expand at the beginning of a row only if it is the first row of a paragraph
|
|
if (pos == row.pos())
|
|
return pos == 0;
|
|
|
|
// do not expand in some labels
|
|
if (par_->layout().margintype != MARGIN_MANUAL && pos < par_->beginOfBody())
|
|
return false;
|
|
|
|
// if there is anything between the first char of the row and
|
|
// the specified position that is neither a newline nor an hfill,
|
|
// the hfill will be expanded, otherwise it won't
|
|
for (pos_type i = row.pos(); i < pos; i++) {
|
|
if (!par_->isNewline(i) && !par_->isEnvSeparator(i) && !par_->isHfill(i))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
} // namespace lyx
|