#include "Row.h"
+#include "DocIterator.h"
+
#include "support/debug.h"
Row::Row()
: separator(0), label_hfill(0), x(0),
- sel_beg(-1), sel_end(-1), changed_(false), crc_(0), pos_(0), end_(0)
+ sel_beg(-1), sel_end(-1), changed_(false), crc_(0),
+ pos_(0), end_(0), left_margin_sel(false), right_margin_sel(false)
{}
Row::Row(pos_type pos)
: separator(0), label_hfill(0), x(0),
- sel_beg(-1), sel_end(-1), changed_(false), crc_(0), pos_(pos), end_(0)
+ sel_beg(-1), sel_end(-1), changed_(false), crc_(0),
+ pos_(0), end_(0), left_margin_sel(false), right_margin_sel(false)
{}
}
+bool Row::isMarginSelected(bool margin_begin, DocIterator const & beg,
+ DocIterator const & end) const
+{
+ pos_type const sel_pos = margin_begin ? sel_beg : sel_end;
+ pos_type const margin_pos = margin_begin ? pos_ : end_;
+
+ // Is the chosen margin selected ?
+ if (sel_pos == margin_pos) {
+ if (beg.pos() == end.pos())
+ // This is a special case in which the space between after
+ // pos i-1 and before pos i is selected, i.e. the margins
+ // (see DocIterator::boundary_).
+ return beg.boundary() && !end.boundary();
+ else if (end.pos() == margin_pos)
+ // If the selection ends around the margin, it is only
+ // drawn if the cursor is after the margin.
+ return !end.boundary();
+ else if (beg.pos() == margin_pos)
+ // If the selection begins around the margin, it is
+ // only drawn if the cursor is before the margin.
+ return beg.boundary();
+ else
+ return true;
+ }
+ return false;
+}
+
+
+void Row::setSelectionAndMargins(DocIterator const & beg,
+ DocIterator const & end) const
+{
+ setSelection(beg.pos(), end.pos());
+
+ if (selection()) {
+ right_margin_sel = isMarginSelected(false, beg, end);
+ left_margin_sel = isMarginSelected(true, beg, end);
+ }
+}
+
+
void Row::setSelection(pos_type beg, pos_type end) const
{
if (pos_ >= beg && pos_ <= end)
}
+bool Row::selection() const
+{
+ return sel_beg != -1 && sel_end != -1;
+}
+
+
void Row::dump(char const * s) const
{
LYXERR0(s << " pos: " << pos_ << " end: " << end_
&& cur.anchor().text() == text_
&& pit >= sel_beg.pit() && pit <= sel_end.pit();
+ // We store the begin and end pos of the selection relative to this par
+ DocIterator sel_beg_par = cur.selectionBegin();
+ DocIterator sel_end_par = cur.selectionEnd();
+
// We care only about visible selection.
if (selection) {
if (pit != sel_beg.pit()) {
- sel_beg.pit() = pit;
- sel_beg.pos() = 0;
+ sel_beg_par.pit() = pit;
+ sel_beg_par.pos() = 0;
}
if (pit != sel_end.pit()) {
- sel_end.pit() = pit;
- sel_end.pos() = sel_end.lastpos();
+ sel_end_par.pit() = pit;
+ sel_end_par.pos() = sel_end_par.lastpos();
}
}
RowPainter rp(pi, *text_, pit, row, bidi, x, y);
if (selection)
- row.setSelection(sel_beg.pos(), sel_end.pos());
+ row.setSelectionAndMargins(sel_beg_par, sel_end_par);
else
row.setSelection(-1, -1);
+
+ // The row knows nothing about the paragraph, so we have to check
+ // whether this row is the first or last and update the margins.
+ if (row.selection()) {
+ if (row.sel_beg == 0)
+ row.left_margin_sel = sel_beg.pit() < pit;
+ if (row.sel_end == sel_end_par.lastpos())
+ row.right_margin_sel = sel_end.pit() > pit;
+ }
// Row signature; has row changed since last paint?
row.setCrc(pm.computeRowSignature(row, bparams));
pi.pain.fillRectangle(x, y - row.ascent(),
width(), row.height(), pi.background_color);
}
-
- bool row_selection = row.sel_beg != -1 && row.sel_end != -1;
- if (row_selection) {
- DocIterator beg = bv_->cursor().selectionBegin();
- DocIterator end = bv_->cursor().selectionEnd();
- // FIXME (not here): pit is not updated when extending
- // a selection to a new row with cursor right/left
- bool const beg_margin = beg.pit() < pit;
- bool const end_margin = end.pit() > pit;
- beg.pit() = pit;
- beg.pos() = row.sel_beg;
- end.pit() = pit;
- end.pos() = row.sel_end;
- if (end.pos() == row.endpos()) {
- // selection goes till the end of the row.
- end.boundary(true);
- }
- drawRowSelection(pi, x, row, beg, end, beg_margin, end_margin);
- }
+
+ if (row.selection())
+ drawRowSelection(pi, x, row, cur, pit);
// Instrumentation for testing row cache (see also
// 12 lines lower):
if (lyxerr.debugging(Debug::PAINTING) && inside
- && (row_selection || pi.full_repaint || row_has_changed)) {
+ && (row.selection() || pi.full_repaint || row_has_changed)) {
string const foreword = text_->isMainText(bv_->buffer()) ?
"main text redraw " : "inset text redraw: ";
LYXERR(Debug::PAINTING, foreword << "pit=" << pit << " row=" << i
- << " row_selection=" << row_selection
+ << " row_selection=" << row.selection()
<< " full_repaint=" << pi.full_repaint
<< " row_has_changed=" << row_has_changed);
}
void TextMetrics::drawRowSelection(PainterInfo & pi, int x, Row const & row,
- DocIterator const & beg, DocIterator const & end,
- bool drawOnBegMargin, bool drawOnEndMargin) const
+ Cursor const & curs, pit_type pit) const
{
+ DocIterator beg = curs.selectionBegin();
+ beg.pit() = pit;
+ beg.pos() = row.sel_beg;
+
+ DocIterator end = curs.selectionEnd();
+ end.pit() = pit;
+ end.pos() = row.sel_end;
+
+ bool const begin_boundary = beg.pos() >= row.endpos();
+ bool const end_boundary = row.sel_end == row.endpos();
+
Buffer & buffer = bv_->buffer();
DocIterator cur = beg;
- int x1 = cursorX(beg.top(), beg.boundary());
- int x2 = cursorX(end.top(), end.boundary());
+ cur.boundary(begin_boundary);
+ int x1 = cursorX(beg.top(), begin_boundary);
+ int x2 = cursorX(end.top(), end_boundary);
int y1 = bv_->getPos(cur, cur.boundary()).y_ - row.ascent();
int y2 = y1 + row.height();
// draw the margins
- if (drawOnBegMargin) {
+ if (row.left_margin_sel) {
if (text_->isRTL(buffer, beg.paragraph())) {
- int lm = bv_->leftMargin();
- pi.pain.fillRectangle(x + x1, y1, width() - lm - x1, y2 - y1, Color_selection);
+ int const w = width() - bv_->leftMargin() - x1;
+ pi.pain.fillRectangle(x + x1, y1, w, y2 - y1, Color_selection);
} else {
- int rm = bv_->rightMargin();
+ int const rm = bv_->rightMargin();
pi.pain.fillRectangle(rm, y1, x1 - rm, y2 - y1, Color_selection);
}
}
- if (drawOnEndMargin) {
+ if (row.right_margin_sel) {
if (text_->isRTL(buffer, beg.paragraph())) {
int rm = bv_->rightMargin();
pi.pain.fillRectangle(x + rm, y1, x2 - rm, y2 - y1, Color_selection);