The attached patch gets rid of the internal xo_ cache of LyXText.
The needed infrastructure was already in Andre's initial patch, but some
text operations used coordinates when not available.

The last situation where coords are used is when moving the cursor while it
is off-screen. With the patch, we cleanly abort there ;-) There are at
least two options: either we do nothing and just recenter the screen, so
this first keystroke is lost (I think that operations that need coordinates
are: cursor{up,down},page{up,down},{home,end} plus "selection" brothers)
*or* we try to do it "right", by first updating the screen and then doing
the cursor movement. In this case, we would obviously try to optimize for
the case in which the cursor is on-screen (only the first keystroke is in
the other case). 

I'm ambivalent between the two, mostly because I find myself countlesss
times pressing cursor-right just to make the screen recenter... Still, I
don't think that the second option is particularly more work (will see).

Comments?

Alfredo
Index: BufferView_pimpl.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView_pimpl.C,v
retrieving revision 1.558.2.11
diff -u -p -u -r1.558.2.11 BufferView_pimpl.C
--- BufferView_pimpl.C	10 Nov 2004 20:16:21 -0000	1.558.2.11
+++ BufferView_pimpl.C	14 Nov 2004 14:34:47 -0000
@@ -92,6 +92,7 @@ using std::endl;
 using std::istringstream;
 using std::make_pair;
 using std::min;
+using std::max;
 using std::string;
 using std::mem_fun_ref;
 
@@ -417,7 +418,7 @@ void BufferView::Pimpl::updateScrollbar(
 
 	//it would be better to fix the scrollbar to understand
 	//values in [0..1] and divide everything by wh
-	int const wh = workarea().workHeight();
+	int const wh = workarea().workHeight() / 4;
 	int const h = t.getPar(anchor_ref_).height();
 	workarea().setScrollbarParams(t.paragraphs().size() * wh, anchor_ref_ * wh + int(offset_ref_ * wh / float(h)), int (wh * defaultRowHeight() / float(h)));
 //	workarea().setScrollbarParams(t.paragraphs().size(), anchor_ref_, 1);
@@ -433,7 +434,7 @@ void BufferView::Pimpl::scrollDocView(in
 
 	screen().hideCursor();
 
-	int const wh = workarea().workHeight();
+	int const wh = workarea().workHeight() / 4;
 
 	LyXText & t = *bv_->text();
 
@@ -445,25 +446,34 @@ void BufferView::Pimpl::scrollDocView(in
 	offset_ref_ = int((bar * t.paragraphs().size() - anchor_ref_) * h);
 	lyxerr << "scrolling: " << value << std::endl;
 	update();
-	
-	
-//	if (!lyxrc.cursor_follows_scrollbar)
-//		return;
-//
-//	int const height = defaultRowHeight();
-//	int const first = top_y() + height;
-//	int const last = top_y() + workarea().workHeight() - height;
-//
-//	bv_->cursor().reset(bv_->buffer()->inset());
-//	LyXText * text = bv_->text();
-//	int y = text->cursorY(bv_->cursor().front());
-//	if (y < first)
-//		y = first;
-//	if (y > last)
-//		y = last;
-//	text->setCursorFromCoordinates(bv_->cursor(), 0, y);
 
+	if (!lyxrc.cursor_follows_scrollbar)
+		return;
+
+	int const height = 2 * defaultRowHeight();
+	int const first = height;
+	int const last = workarea().workHeight() - height;
+	LCursor & cur = bv_->cursor();
+	
+	bv_funcs::CurStatus st = bv_funcs::status(bv_, cur);
 
+	switch (st) {
+	case bv_funcs::CUR_ABOVE:
+		t.setCursorFromCoordinates(cur, 0, first);
+		cur.clearSelection();
+		break;
+	case bv_funcs::CUR_BELOW:
+		t.setCursorFromCoordinates(cur, 0, last);
+		cur.clearSelection();
+		break;
+	case bv_funcs::CUR_INSIDE:
+		int const y = bv_funcs::getPos(cur).y_;
+		int const newy = min(last, max(y, first));
+		if (y != newy) {
+			cur.reset(bv_->buffer()->inset());
+			t.setCursorFromCoordinates(cur, 0, newy);
+		}
+	}
 	owner_->updateLayoutChoice();
 }
 
@@ -579,7 +589,7 @@ bool BufferView::Pimpl::fitCursor()
 		int asc, des;
 		bv_->cursor().getDim(asc, des);
 		Point p = bv_funcs::getPos(bv_->cursor());
-		if (p.y_ - asc >= 0 && p.y_ + des <= bv_->workHeight())
+		if (p.y_ - asc >= 0 && p.y_ + des < bv_->workHeight())
 			return false;
 	}
 	bv_->center();
@@ -599,7 +609,8 @@ void BufferView::Pimpl::update(bool fitc
 		buffer_->buildMacros();
 		// first drawing step
 
-		CoordCache backup = theCoords;
+		CoordCache backup;
+		std::swap(theCoords, backup);
 		//
 		ViewMetricsInfo vi = metrics();
 
@@ -611,7 +622,7 @@ void BufferView::Pimpl::update(bool fitc
 			// second drawing step
 			screen().redraw(*bv_, vi);
 		} else
-			theCoords = backup;
+			std::swap(theCoords, backup);
 		
 	} else
 		screen().greyOut();
@@ -877,6 +888,7 @@ bool BufferView::Pimpl::workAreaDispatch
 	// surrounding LyXText will handle this event.
 
 	// Build temporary cursor.
+	cmd.y = min(max(cmd.y,-1), bv_->workHeight());
 	InsetBase * inset = bv_->text()->editXY(cur, cmd.x, cmd.y);
 	lyxerr << " * hit inset at tip: " << inset << endl;
 	lyxerr << " * created temp cursor:" << cur << endl;
@@ -1157,10 +1169,11 @@ ViewMetricsInfo BufferView::Pimpl::metri
 		y1 -= text->getPar(pit1).descent();
 	}
 
+	
 	// take care of ascent of first line
 	y1 -= text->getPar(pit1).ascent();
 
-	//normalize anchor
+	//normalize anchor for next time
 	anchor_ref_ = pit1;
 	offset_ref_ = -y1;
 
@@ -1183,7 +1196,7 @@ ViewMetricsInfo BufferView::Pimpl::metri
 	// take care of descent of last line 
 	y2 += text->getPar(pit2).descent();
 
-	// the coordinates of all these paragraphs are correct
+	// the coordinates of all these paragraphs are correct, cache them
 	int y = y1;
 	for (lyx::pit_type pit = pit1; pit <= pit2; ++pit) {
 		y += text->getPar(pit).ascent();
Index: BufferView_pimpl.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView_pimpl.h,v
retrieving revision 1.124.2.3
diff -u -p -u -r1.124.2.3 BufferView_pimpl.h
--- BufferView_pimpl.h	7 Nov 2004 20:55:14 -0000	1.124.2.3
+++ BufferView_pimpl.h	14 Nov 2004 14:34:47 -0000
@@ -185,7 +185,7 @@ private:
 	int offset_ref_;
 	///
 	ViewMetricsInfo metrics();
-	
-	
+
+
 };
 #endif // BUFFERVIEW_PIMPL_H
Index: lyxtext.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyxtext.h,v
retrieving revision 1.312.2.2
diff -u -p -u -r1.312.2.2 lyxtext.h
--- lyxtext.h	14 Nov 2004 13:31:48 -0000	1.312.2.2
+++ lyxtext.h	14 Nov 2004 14:34:47 -0000
@@ -349,9 +349,6 @@ public:
 	///
 	ParagraphList pars_;
 
-	/// absolute document pixel coordinates of this LyXText
-	mutable int xo_;
-
 	/// our 'outermost' Font
 	LyXFont font_;
 
Index: rowpainter.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/rowpainter.C,v
retrieving revision 1.135.2.9
diff -u -p -u -r1.135.2.9 rowpainter.C
--- rowpainter.C	14 Nov 2004 13:31:48 -0000	1.135.2.9
+++ rowpainter.C	14 Nov 2004 14:34:48 -0000
@@ -736,11 +736,10 @@ void paintPar
 {
 //	lyxerr << "  paintPar: pit: " << pit << " at y: " << y << endl;
 	Paragraph & par = text.paragraphs()[pit];
-	//par.dump();
 
 	RowList::iterator const rb = par.rows().begin();
 	RowList::iterator const re = par.rows().end();
-	theCoords.pars_[&text][pit] = Point(0, y);
+	theCoords.pars_[&text][pit] = Point(x, y);
 
 	y -= rb->ascent();
 	for (RowList::iterator rit = rb; rit != re; ++rit) {
@@ -761,14 +760,6 @@ void paintPar
 } // namespace anon
 
 
-//void refreshPar(BufferView const & bv, LyXText const & text, pit_type pit)
-void foo()
-{
-	// removing this leads to linker errors ?!
-	static NullPainter nop;
-}
-
-
 void paintText(BufferView const & bv, ViewMetricsInfo const & vi)
 {
 	Painter & pain = bv.painter();
@@ -780,6 +771,7 @@ void paintText(BufferView const & bv, Vi
 
 	// draw selection
 	PainterInfo pi(const_cast<BufferView *>(&bv), pain);
+
 	text->drawSelection(pi, 0, 0);
 
 	int yy = vi.y1;
@@ -790,6 +782,22 @@ void paintText(BufferView const & bv, Vi
 		yy += text->getPar(pit).descent();
 	}
 	
+
+	static NullPainter nop;
+	PainterInfo nullpi(const_cast<BufferView *>(&bv), nop);
+	// nullpaint one paragraph above and one below
+	if (vi.p1 > 0) {
+		text->redoParagraph(vi.p1 - 1);
+		paintPar(nullpi, *bv.text(), vi.p1 - 1, 0,
+			 vi.y1 -  text->getPar(vi.p1 - 1).descent());
+	}
+
+	if (vi.p2 < text->paragraphs().size() - 1) {
+		text->redoParagraph(vi.p2 + 1);
+		paintPar(nullpi, *bv.text(), vi.p2 + 1, 0,
+			 vi.y2 + text->getPar(vi.p2 + 1).ascent());
+	}
+
 	// and grey out above (should not happen later)
 	lyxerr << "par ascent: " << text->getPar(vi.p1).ascent() << endl;
 	if (vi.y1 > 0)
Index: text.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/text.C,v
retrieving revision 1.584.2.13
diff -u -p -u -r1.584.2.13 text.C
--- text.C	14 Nov 2004 13:31:48 -0000	1.584.2.13
+++ text.C	14 Nov 2004 14:34:48 -0000
@@ -1713,8 +1713,6 @@ void LyXText::metrics(MetricsInfo & mi, 
 // only used for inset right now. should also be used for main text
 void LyXText::draw(PainterInfo & pi, int x, int y) const
 {
-	xo_ = x;
-//	drawSelection(pi, x, y);
 	paintTextInset(*this, pi, x, y);
 }
 
@@ -1791,10 +1789,8 @@ void LyXText::drawSelection(PainterInfo 
 */
 
 
-void LyXText::drawSelection(PainterInfo & pi, int, int) const
+void LyXText::drawSelection(PainterInfo & pi, int x, int) const
 {
-	int x = xo_;
-	
 	LCursor & cur = pi.base.bv->cursor();
 	if (!cur.selection())
 		return;
@@ -2238,7 +2234,7 @@ void LyXText::setCursorFromCoordinates(L
 	pit_type pit = getPitNearY(y);
 	BOOST_ASSERT(theCoords.pars_.find(this) != theCoords.pars_.end());
 	BOOST_ASSERT(theCoords.pars_[this].find(pit) != theCoords.pars_[this].end());
-	int yy = theCoords.pars_[this][pit].y_ - pars_[pit].ascent();
+	int yy = theCoords.get(this, pit).y_ - pars_[pit].ascent();
 	lyxerr << "setCursorFromCoordinates: x: " << x << " y: " << y 
 		<< " pit: " << pit << " yy: " << yy << endl;
 
@@ -2254,7 +2250,8 @@ void LyXText::setCursorFromCoordinates(L
 
 	Row const & row = par.rows()[r];
  
-	lyxerr << "setCursorFromCoordinates:  row " << r << " from pos: " << row.pos() << endl;
+	lyxerr << "setCursorFromCoordinates:  row " << r
+	       << " from pos: " << row.pos() << endl;
 	
 	bool bound = false;
 	int xx = x;
Index: text2.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/text2.C,v
retrieving revision 1.587.2.7
diff -u -p -u -r1.587.2.7 text2.C
--- text2.C	14 Nov 2004 11:27:07 -0000	1.587.2.7
+++ text2.C	14 Nov 2004 14:34:49 -0000
@@ -74,7 +74,7 @@ using std::string;
 LyXText::LyXText(BufferView * bv)
 	: maxwidth_(bv ? bv->workWidth() : 100),
 	  background_color_(LColor::background),
-	  bv_owner(bv), xo_(0)
+	  bv_owner(bv)
 {}
 
 
@@ -1029,7 +1029,8 @@ void LyXText::setCurrentFont(LCursor & c
 pos_type LyXText::getColumnNearX(pit_type const pit,
 	Row const & row, int & x, bool & boundary) const
 {
-	x -= xo_;
+	int const xo = theCoords.get(this, pit).x_;
+	x -= xo;
 	RowMetrics const r = computeRowMetrics(pit, row);
 	Paragraph const & par = pars_[pit];
 
@@ -1051,7 +1052,7 @@ pos_type LyXText::getColumnNearX(pit_typ
 
 	// check for empty row
 	if (vc == end) {
-		x = int(tmpx) + xo_;
+		x = int(tmpx) + xo;
 		return 0;
 	}
 
@@ -1121,7 +1122,7 @@ pos_type LyXText::getColumnNearX(pit_typ
 		c = end - 1;
 	}
 
-	x = int(tmpx) + xo_;
+	x = int(tmpx) + xo;
 	return c - row.pos();
 }
 
@@ -1157,7 +1158,7 @@ pit_type LyXText::getPitNearY(int y) con
 Row const & LyXText::getRowNearY(int y, pit_type pit) const
 {
 	Paragraph const & par = pars_[pit];
-	int yy = theCoords.pars_[this][pit].y_ - pars_[pit].ascent();
+	int yy = theCoords.get(this, pit).y_ - pars_[pit].ascent();
 	BOOST_ASSERT(!par.rows().empty());
 	RowList::const_iterator rit = par.rows().begin();
 	RowList::const_iterator const rlast = boost::prior(par.rows().end());
Index: text3.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/text3.C,v
retrieving revision 1.268.2.5
diff -u -p -u -r1.268.2.5 text3.C
--- text3.C	10 Nov 2004 09:16:15 -0000	1.268.2.5
+++ text3.C	14 Nov 2004 14:34:49 -0000
@@ -1159,6 +1159,7 @@ void LyXText::dispatch(LCursor & cur, Fu
 			int const y = std::max(0, std::min(bv->workHeight() - 1, cmd.y));
 					  
 			setCursorFromCoordinates(cur, cmd.x, y);
+			cur.x_target() = cmd.x;
 			if (cmd.y >= bv->workHeight())
 				cursorDown(cur);
 			else if (cmd.y < 0)

Reply via email to