Abdelrazak Younes wrote:
Yes, that sounds a better and cleaner solution. We basically only keep
rows that are shown on screen in memory so adding two move variable is
not a big problem.
Abdel.
Hi,
I sort of cut the new code in four. It is no longer computed for and
after the checksum and the code is generalized for both the begin as end
margin. Besides it is mostly transferred into Row, so the drawParagraph
function is now as clean as it used to be.
The most important things are:
+ ///
+ mutable bool margin_beg_sel;
+ ///
+ mutable bool margin_end_sel;
Two new members added to Row.
- row.setSelection(sel_beg.pos(), sel_end.pos());
+ row.setSelectionAndMargins(sel_beg_par, sel_end_par);
I added this function Row::setSelectionAndMargins(..), which now sets
the selection and immediately computes whether the margins are selected
or not.
+ if (row.sel_beg == 0)
+ row.setBeginMarginSelection(sel_beg.pit() < pit);
+ if (row.sel_end == sel_end_par.lastpos())
+ row.setEndMarginSelection(sel_end.pit() > pit);
This is needed because the Row does not know a thing about other
paragraphs. This is just old code with two if statements.
+ char_type const b[] = { row.sel_beg, row.sel_end,
+ row.margin_beg_sel, row.margin_end_sel, d.wid, d.asc, d.des};
+ // Each of the variable to process is 4 bytes: 4x7 = 28
+ crc.process_bytes(b, 28);
This is all code left for calculating the checksum. Only two terms are added
I also added Row::isMarginSelected( .. ). This function computes for
both the begin margin (first argument true) as for the end margin
whether they are selected. The essential code in this function is now
very easy to understand and consists mostly of comments.
Further, just some access functions and a Row::selection().. just for ease.
Thank you for your critics,
Vincent
Index: src/TextMetrics.cpp
===================================================================
--- src/TextMetrics.cpp (revision 26384)
+++ src/TextMetrics.cpp (working copy)
@@ -1987,15 +1987,19 @@
&& 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();
}
}
@@ -2012,9 +2016,18 @@
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.setBeginMarginSelection(sel_beg.pit() <
pit);
+ if (row.sel_end == sel_end_par.lastpos())
+ row.setEndMarginSelection(sel_end.pit() > pit);
+ }
// Row signature; has row changed since last paint?
row.setCrc(pm.computeRowSignature(row, bparams));
@@ -2036,34 +2049,18 @@
pi.pain.fillRectangle(x, y - row.ascent(),
width(), row.height(), pi.background_color);
}
+
+ if (row.selection())
+ drawRowSelection(pi, x, row, cur, pit);
- 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);
- }
-
// 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);
}
@@ -2092,13 +2089,26 @@
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
{
+ bool drawOnBegMargin = row.margin_beg_sel;
+ bool drawOnEndMargin = row.margin_end_sel;
+ 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();
Index: src/TextMetrics.h
===================================================================
--- src/TextMetrics.h (revision 26384)
+++ src/TextMetrics.h (working copy)
@@ -160,8 +160,7 @@
/// draw selection for a single row
void drawRowSelection(PainterInfo & pi, int x, Row const & row,
- DocIterator const & beg, DocIterator const & end,
- bool drawOnBegMargin, bool drawOnEndMargin) const;
+ Cursor const & cur, pit_type const pit) const;
// Temporary public:
public:
Index: src/ParagraphMetrics.cpp
===================================================================
--- src/ParagraphMetrics.cpp (revision 26384)
+++ src/ParagraphMetrics.cpp (working copy)
@@ -103,9 +103,10 @@
}
Dimension const & d = row.dimension();
- char_type const b[] = { row.sel_beg, row.sel_end, d.wid, d.asc, d.des};
- // Each of the variable to process is 4 bytes: 4x5 = 20
- crc.process_bytes(b, 20);
+ char_type const b[] = { row.sel_beg, row.sel_end,
+ row.margin_beg_sel, row.margin_end_sel, d.wid, d.asc, d.des};
+ // Each of the variable to process is 4 bytes: 4x7 = 28
+ crc.process_bytes(b, 28);
return crc.checksum();
}
Index: src/Row.cpp
===================================================================
--- src/Row.cpp (revision 26384)
+++ src/Row.cpp (working copy)
@@ -18,6 +18,8 @@
#include "Row.h"
+#include "DocIterator.h"
+
#include "support/debug.h"
@@ -26,13 +28,15 @@
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), margin_beg_sel(false), margin_end_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), margin_beg_sel(false), margin_end_sel(false)
{}
@@ -60,7 +64,48 @@
end_ = p;
}
+// This function decides whether the margin (according to margin_begin)
+// is selected.
+bool Row::isMarginSelected(bool const 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()) {
+ margin_end_sel = isMarginSelected(false, beg, end);
+ margin_beg_sel = isMarginSelected(true, beg, end);
+ }
+}
+
+
void Row::setSelection(pos_type beg, pos_type end) const
{
if (pos_ >= beg && pos_ <= end)
@@ -79,6 +124,24 @@
}
+void Row::setEndMarginSelection(bool const end_margin) const
+{
+ margin_end_sel = end_margin;
+}
+
+
+void Row::setBeginMarginSelection(bool const beg_margin) const
+{
+ margin_beg_sel = beg_margin;
+}
+
+
+bool Row::selection() const
+{
+ return sel_beg != -1 && sel_end != -1;
+}
+
+
void Row::dump(char const * s) const
{
LYXERR0(s << " pos: " << pos_ << " end: " << end_
Index: src/Row.h
===================================================================
--- src/Row.h (revision 26384)
+++ src/Row.h (working copy)
@@ -22,6 +22,8 @@
namespace lyx {
+class DocIterator;
+
/**
* An on-screen row of text. A paragraph is broken into a
* RowList for display. Each Row contains position pointers
@@ -45,6 +47,19 @@
* time.
*/
void setSelection(pos_type sel_beg, pos_type sel_end) const;
+ ///
+ bool selection() const;
+ /// Set the selection begin and end and whether the margin begin and end
+ /// are selected.
+ void setSelectionAndMargins(DocIterator const & beg,
+ DocIterator const & end) const;
+ ///
+ bool isMarginSelected(bool const margin_begin, DocIterator const &
beg,
+ DocIterator const & end) const;
+ ///
+ void setEndMarginSelection(bool const end_margin) const;
+ ///
+ void setBeginMarginSelection(bool const beg_margin) const;
///
void pos(pos_type p);
@@ -80,6 +95,10 @@
mutable pos_type sel_beg;
///
mutable pos_type sel_end;
+ ///
+ mutable bool margin_beg_sel;
+ ///
+ mutable bool margin_end_sel;
private:
/// has the Row appearance changed since last drawing?
mutable bool changed_;