Ok this is my fix to the fitCursor problem in CoordBranch.

I'm posting it here because it changes quite a few things, and I want this
to get accepted. I'll commit after I receive some comment.

1) It separates the first and second drawing steps, i.e. takes the metrics
step out of update to BufferView::Pimpl. To do so I created a
ViewMetricsInfo struct that holds the needed info to pass between both
steps: the first and last paragraphs to be painted with their absolute
positions.

2) it introduces two new bool parameters to update: fitcursor and
forceupdate with defaults of true and true respectively.
fitcursor=true means to fit the cursor and to force an update if position
changes, forceupdate means to force an update irrespectively. It's not very
elegant, because the combination false,false doesn't do anything but we can
change this later.

3) It moves the decision to greyOut from LyXScreen to BufferView (where it
belongs IMO)

Comments?

With this, cursor movement becomes useable, at least in text. 


PS: CoordBranch seems now less crashy than HEAD (which doesn't mean much,
but...)

Alfredo
Index: BufferView.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView.C,v
retrieving revision 1.254.2.3
diff -u -p -u -r1.254.2.3 BufferView.C
--- BufferView.C	6 Nov 2004 22:09:47 -0000	1.254.2.3
+++ BufferView.C	7 Nov 2004 10:51:19 -0000
@@ -85,19 +85,6 @@ Buffer * BufferView::buffer() const
 }
 
 
-bool BufferView::fitCursor()
-{
-	int x, y;
-	if (bv_funcs::status(this, cursor()) == bv_funcs::CUR_INSIDE) {
-		Point p = bv_funcs::getPos(cursor());
-		if (p.y_ >= 0 && p.y_ <= workHeight())
-			return false;
-	}
-	center();
-	return true;
-}
-
-
 LyXScreen & BufferView::screen() const
 {
 	return pimpl_->screen();
@@ -149,9 +136,9 @@ void BufferView::resize()
 }
 
 
-void BufferView::update()
+void BufferView::update(bool fitcursor, bool forceupdate)
 {
-	pimpl_->update();
+	pimpl_->update(fitcursor, forceupdate);
 }
 
 
Index: BufferView.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView.h,v
retrieving revision 1.179.2.3
diff -u -p -u -r1.179.2.3 BufferView.h
--- BufferView.h	6 Nov 2004 22:09:48 -0000	1.179.2.3
+++ BufferView.h	7 Nov 2004 10:51:19 -0000
@@ -78,7 +78,7 @@ public:
 	bool loadLyXFile(std::string const & name, bool tolastfiles = true);
 
 	/// perform pending painting updates
-	void update();
+	void update(bool fitcursor = true, bool forceupdate = true);
 	/// reset the scrollbar to reflect current view position
 	void updateScrollbar();
 
@@ -169,8 +169,6 @@ public:
 	void putSelectionAt(DocIterator const & cur,
 		int length, bool backwards);
 
-	// 
-	bool fitCursor();
 
 private:
 	///
Index: BufferView_pimpl.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView_pimpl.C,v
retrieving revision 1.558.2.5
diff -u -p -u -r1.558.2.5 BufferView_pimpl.C
--- BufferView_pimpl.C	7 Nov 2004 07:32:16 -0000	1.558.2.5
+++ BufferView_pimpl.C	7 Nov 2004 10:51:19 -0000
@@ -41,6 +41,7 @@
 #include "lyxtext.h"
 #include "lyxrc.h"
 #include "lastfiles.h"
+#include "metricsinfo.h"
 #include "paragraph.h"
 #include "paragraph_funcs.h"
 #include "ParagraphParameters.h"
@@ -555,32 +556,46 @@ void BufferView::Pimpl::workAreaResize()
 }
 
 
-void BufferView::Pimpl::update()
+bool BufferView::Pimpl::fitCursor()
+{
+	if (bv_funcs::status(bv_, bv_->cursor()) == bv_funcs::CUR_INSIDE) {
+		Point p = bv_funcs::getPos(bv_->cursor());
+		if (p.y_ >= 0 && p.y_ <= bv_->workHeight())
+			return false;
+	}
+	bv_->center();
+	return true;
+}
+
+
+void BufferView::Pimpl::update(bool fitcursor, bool forceupdate)
 {
 	lyxerr << "BufferView::Pimpl::update(), buffer: " << buffer_ << endl;
 	// fix cursor coordinate cache in case something went wrong
 
+	
 	// check needed to survive LyX startup
 	if (buffer_) {
 		// update macro store
 		buffer_->buildMacros();
-
-//		// update all 'visible' paragraphs
-//		lyx::pit_type beg, end;
-//		getParsInRange(buffer_->paragraphs(),
-//			       top_y(), top_y() + workarea().workHeight(),
-//			       beg, end);
-//		bv_->text()->redoParagraphs(beg, end);
-
 		// and the scrollbar
 		updateScrollbar();
-	}
-
-	// remove old position cache
-	theCoords.clear();
-
-	// The real, big redraw.
-	screen().redraw(*bv_);
+		// remove old position cache
+		theCoords.clear();
+		// first drawing step
+		ViewMetricsInfo vi = metrics();
+
+		if (fitcursor && fitCursor()) {
+			forceupdate = true;
+			vi = metrics();
+		}
+		if (forceupdate) {
+			// second drawing step
+			screen().redraw(*bv_, vi);
+		}
+		
+	} else
+		screen().greyOut();
 
 	bv_->owner()->view_state_changed();
 }
@@ -859,8 +874,7 @@ bool BufferView::Pimpl::workAreaDispatch
 
 	if (cur.result().dispatched()) {
 		// Redraw if requested or necessary.
-		if (bv_->fitCursor() || cur.result().update())
-			update();
+		update(true, cur.result().update());
 	}
 
 	// see workAreaKeyPress
@@ -1104,4 +1118,56 @@ bool BufferView::Pimpl::dispatch(FuncReq
 	}
 
 	return true;
+}
+
+
+ViewMetricsInfo BufferView::Pimpl::metrics()
+{
+	BufferView & bv = *bv_;
+	LyXText * const text = bv.text();
+	lyx::pit_type const pit = min(bv.anchor_ref(), int(text->paragraphs().size()));
+	int const off = bv.offset_ref();
+
+	int pit1 = pit;
+	int pit2 = pit;
+	size_t npit = text->paragraphs().size();
+	lyxerr << "npit: " << npit << " pit1: " << pit1 
+		<< " pit2: " << pit2 << endl;
+
+	//
+	// rebreak cursor par	
+	//
+	text->redoParagraph(pit);
+	int y0 = text->getPar(pit1).ascent() - off;
+	theCoords.pars_[text][pit1] = Point(0, y0);
+	
+
+	// redo paragraphs above cursor if necessary
+	int y1 = y0;
+	while (y1 > 0 && pit1 > 0) {
+		y1 -= text->getPar(pit1).ascent();
+		--pit1;
+		text->redoParagraph(pit1);
+		y1 -= text->getPar(pit1).descent();
+		theCoords.pars_[text][pit1] = Point(0, y1);
+	}
+
+	// redo paragraphs below cursor if necessary
+	int y2 = y0;
+	//-text->getPar(pit2).descent() - off;
+	while (y2 < bv.workHeight() && pit2 < int(npit) - 1) {
+		y2 += text->getPar(pit2).descent();
+		++pit2;
+		text->redoParagraph(pit2);
+		y2 += text->getPar(pit2).ascent();
+		theCoords.pars_[text][pit2] = Point(0, y2);
+	}
+
+	// take care of ascent of first and descent of last line
+	int yy = y1;
+	y1 -= text->getPar(pit1).ascent();
+	y2 += text->getPar(pit2).descent();
+
+	lyxerr << "paintText: yy: " << yy << " y1: " << y1 << " y2: " << y2 << endl;
+	return ViewMetricsInfo(pit1, pit2, y1, y2);
 }
Index: BufferView_pimpl.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView_pimpl.h,v
retrieving revision 1.124.2.2
diff -u -p -u -r1.124.2.2 BufferView_pimpl.h
--- BufferView_pimpl.h	4 Nov 2004 11:15:52 -0000	1.124.2.2
+++ BufferView_pimpl.h	7 Nov 2004 10:51:19 -0000
@@ -41,6 +41,7 @@ class WorkArea;
 class LyXScreen;
 class FuncRequest;
 class FuncStatus;
+class ViewMetricsInfo;
 
 
 ///
@@ -55,8 +56,10 @@ struct BufferView::Pimpl : public boost:
 	void setBuffer(Buffer * buf);
 	///
 	void resizeCurrentBuffer();
+	// 
+	bool fitCursor();
 	///
-	void update();
+	void update(bool fitcursor = false, bool forceupdate = true);
 	///
 	void newFile(std::string const &, std::string const &, bool);
 	///
@@ -180,6 +183,9 @@ private:
 	lyx::pit_type anchor_ref_;
 	///
 	int offset_ref_;
+	///
+	ViewMetricsInfo metrics();
+	
 	
 };
 #endif // BUFFERVIEW_PIMPL_H
Index: bufferview_funcs.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/bufferview_funcs.C,v
retrieving revision 1.142.2.1
diff -u -p -u -r1.142.2.1 bufferview_funcs.C
--- bufferview_funcs.C	6 Nov 2004 22:09:48 -0000	1.142.2.1
+++ bufferview_funcs.C	7 Nov 2004 10:51:19 -0000
@@ -174,6 +174,7 @@ Point coordOffset(DocIterator const & di
 	for (size_t rit = 0, rend = par.pos2row(sl.pos()); rit != rend; ++rit)
 		y += par.rows()[rit].height();
 	y += par.rows()[par.pos2row(sl.pos())].ascent();
+	x += dit.bottom().text()->cursorX(dit.bottom());
 	return Point(x,y);
 }
  
@@ -192,7 +193,6 @@ Point getPos(DocIterator const & dit)
 		return Point(-1,-1);
 	}
 	Point p = coordOffset(dit); // offset from outer paragraph
-	p.x_ += bot.text()->cursorX(bot);
 	p.y_ += cache[bot.pit()].y_;
 	return p;
 }
Index: lyxfunc.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyxfunc.C,v
retrieving revision 1.627.2.2
diff -u -p -u -r1.627.2.2 lyxfunc.C
--- lyxfunc.C	6 Nov 2004 22:09:48 -0000	1.627.2.2
+++ lyxfunc.C	7 Nov 2004 10:51:20 -0000
@@ -1438,8 +1438,6 @@ void LyXFunc::dispatch(FuncRequest const
 				update |= view()->cursor().result().update();
 			else
 				update |= view()->dispatch(cmd);
-			update |= view()->fitCursor();
-
 			break;
 		}
 		}
@@ -1448,8 +1446,7 @@ void LyXFunc::dispatch(FuncRequest const
 			// Redraw screen unless explicitly told otherwise.
 			// This also initializes the position cache for all insets
 			// in (at least partially) visible top-level paragraphs.
-			if (update)
-				view()->update();
+			view()->update(true, update);
 
 			// if we executed a mutating lfun, mark the buffer as dirty
 			if (getStatus(cmd).enabled()
Index: metricsinfo.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/metricsinfo.h,v
retrieving revision 1.13
diff -u -p -u -r1.13 metricsinfo.h
--- metricsinfo.h	14 Aug 2004 23:57:29 -0000	1.13
+++ metricsinfo.h	7 Nov 2004 10:51:20 -0000
@@ -13,6 +13,7 @@
 #define METRICSINFO_H
 
 #include "lyxfont.h"
+#include "support/types.h"
 
 #include <string>
 
@@ -88,8 +89,18 @@ struct PainterInfo {
 	bool ltr_pos;
 };
 
-
 struct TextMetricsInfo {};
+
+
+struct ViewMetricsInfo
+{
+	ViewMetricsInfo(lyx::pit_type p1, lyx::pit_type p2,
+			int y1, int y2) : p1(p1), p2(p2), y1(y1), y2(y2) {}
+	lyx::pit_type p1;
+	lyx::pit_type p2;
+	int y1;
+	int y2;
+};
 
 
 // Generic base for temporarily changing things.
Index: rowpainter.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/rowpainter.C,v
retrieving revision 1.135.2.4
diff -u -p -u -r1.135.2.4 rowpainter.C
--- rowpainter.C	6 Nov 2004 20:56:35 -0000	1.135.2.4
+++ rowpainter.C	7 Nov 2004 10:51:20 -0000
@@ -771,81 +771,38 @@ void foo()
 }
 
 
-void paintText(BufferView const & bv)
+void paintText(BufferView const & bv, ViewMetricsInfo const & vi)
 {
-	LyXText * const text = bv.text();
-	pit_type const pit = min(bv.anchor_ref(), int(text->paragraphs().size()));
-	int const off = bv.offset_ref();
 	Painter & pain = bv.painter();
-
-	int pit1 = pit;
-	int pit2 = pit;
-	size_t npit = text->paragraphs().size();
-	lyxerr << "npit: " << npit << " pit1: " << pit1 
-		<< " pit2: " << pit2 << endl;
-
-	//
-	// rebreak cursor par	
-	//
-	text->redoParagraph(pit);
-	int y0 = text->getPar(pit1).ascent() - off;
-	theCoords.pars_[text][pit1] = Point(0, y0);
-	
-
-	// redo paragraphs above cursor if necessary
-	int y1 = y0;
-	while (y1 > 0 && pit1 > 0) {
-		y1 -= text->getPar(pit1).ascent();
-		--pit1;
-		text->redoParagraph(pit1);
-		y1 -= text->getPar(pit1).descent();
-		theCoords.pars_[text][pit1] = Point(0, y1);
-	}
-
-	// redo paragraphs below cursor if necessary
-	int y2 = y0;
-	//-text->getPar(pit2).descent() - off;
-	while (y2 < bv.workHeight() && pit2 < int(npit) - 1) {
-		y2 += text->getPar(pit2).descent();
-		++pit2;
-		text->redoParagraph(pit2);
-		y2 += text->getPar(pit2).ascent();
-		theCoords.pars_[text][pit2] = Point(0, y2);
-	}
-
-	// take care of ascent of first and descent of last line
-	int yy = y1;
-	y1 -= text->getPar(pit1).ascent();
-	y2 += text->getPar(pit2).descent();
-
-	lyxerr << "paintText: yy: " << yy << " y1: " << y1 << " y2: " << y2 << endl;
+	LyXText * const text = bv.text();
 
 	// clear background
-	pain.fillRectangle(0, y1, bv.workWidth(), y2 - y1, LColor::background);
+	pain.fillRectangle(0, vi.y1, bv.workWidth(), vi.y2 - vi.y1,
+			   LColor::background);
 
 	// draw selection
 	PainterInfo pi(const_cast<BufferView *>(&bv), pain);
-	text->drawSelection(pi, 0, yy);
+	text->drawSelection(pi, 0, 0);
 
+	int yy = vi.y1 + text->getPar(vi.p1).ascent();
 	// draw contents
-	for (pit_type pit = pit1; pit <= pit2; ) {
+	for (pit_type pit = vi.p1; pit <= vi.p2; ) {
 		paintPar(pi, *bv.text(), pit, 0, yy);
 		yy += text->getPar(pit).descent();
 		++pit;
-		if (pit <= pit2) 
+		if (pit <= vi.p2) 
 			yy += text->getPar(pit).ascent();
 	}
-
+	
 	// and grey out above (should not happen later)
-	lyxerr << "par ascent: " << text->getPar(pit1).ascent() << endl;
-	if (y1 > 0)
-		pain.fillRectangle(0, 0, bv.workWidth(), y1, LColor::bottomarea);
+	lyxerr << "par ascent: " << text->getPar(vi.p1).ascent() << endl;
+	if (vi.y1 > 0)
+		pain.fillRectangle(0, 0, bv.workWidth(), vi.y1, LColor::bottomarea);
 
 	// and possibly grey out below
-	lyxerr << "par descent: " << text->getPar(pit1).ascent() << endl;
-	if (y2 < bv.workHeight())
-		pain.fillRectangle(0, y2, bv.workWidth(), bv.workHeight() - y2,
-			LColor::bottomarea);
+	lyxerr << "par descent: " << text->getPar(vi.p1).ascent() << endl;
+	if (vi.y2 < bv.workHeight())
+		pain.fillRectangle(0, vi.y2, bv.workWidth(), bv.workHeight() - vi.y2, LColor::bottomarea);
 }
 
 
Index: rowpainter.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/rowpainter.h,v
retrieving revision 1.20.2.1
diff -u -p -u -r1.20.2.1 rowpainter.h
--- rowpainter.h	3 Nov 2004 22:34:02 -0000	1.20.2.1
+++ rowpainter.h	7 Nov 2004 10:51:20 -0000
@@ -19,9 +19,11 @@
 class LyXText;
 class BufferView;
 class PainterInfo;
+class ViewMetricsInfo;
+
 
 /// paint visible paragraph of main text
-void paintText(BufferView const & bv);
+void paintText(BufferView const & bv, ViewMetricsInfo const & vi);
 
 /// paint the rows of a text inset
 void paintTextInset(LyXText const & text, PainterInfo & pi, int x, int y);
Index: frontends/screen.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/screen.C,v
retrieving revision 1.96.2.1
diff -u -p -u -r1.96.2.1 screen.C
--- frontends/screen.C	3 Nov 2004 22:34:07 -0000	1.96.2.1
+++ frontends/screen.C	7 Nov 2004 10:51:20 -0000
@@ -121,7 +121,7 @@ SplashScreen::SplashScreen()
 
 
 LyXScreen::LyXScreen()
-	: cursor_visible_(false), greyed_out_(true)
+	: cursor_visible_(false)
 {
 	// Start loading the pixmap as soon as possible
 	if (lyxrc.show_banner) {
@@ -204,29 +204,20 @@ void LyXScreen::toggleCursor(BufferView 
 }
 
 
-void LyXScreen::redraw(BufferView & bv)
+void LyXScreen::redraw(BufferView & bv, ViewMetricsInfo const & vi)
 {
-	greyed_out_ = !bv.text();
-
-	if (greyed_out_) {
-		greyOut();
-	} else {
-		workarea().getPainter().start();
-		hideCursor();
-		paintText(bv);
-		lyxerr[Debug::DEBUG] << "Redraw screen" << endl;
-		expose(0, 0, workarea().workWidth(), workarea().workHeight());
-		workarea().getPainter().end();
-		showCursor(bv);
-	}
+	workarea().getPainter().start();
+	hideCursor();
+	paintText(bv, vi);
+	lyxerr[Debug::DEBUG] << "Redraw screen" << endl;
+	expose(0, 0, workarea().workWidth(), workarea().workHeight());
+	workarea().getPainter().end();
+	showCursor(bv);
 }
 
 
 void LyXScreen::greyOut()
 {
-	if (!greyed_out_)
-		return;
-
 	workarea().getPainter().start();
 
 	workarea().getPainter().fillRectangle(0, 0,
Index: frontends/screen.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/screen.h,v
retrieving revision 1.29.2.1
diff -u -p -u -r1.29.2.1 screen.h
--- frontends/screen.h	3 Nov 2004 22:34:07 -0000	1.29.2.1
+++ frontends/screen.h	7 Nov 2004 10:51:20 -0000
@@ -13,10 +13,15 @@
 #ifndef SCREEN_H
 #define SCREEN_H
 
+#include <support/types.h>
+
+
 class LyXText;
 class CursorSlice;
 class WorkArea;
 class BufferView;
+class ViewMetricsInfo;
+
 
 /**
  * LyXScreen - document rendering management
@@ -37,7 +42,10 @@ public:
 	virtual ~LyXScreen();
 
 	/// redraw the screen, without using existing pixmap
-	virtual void redraw(BufferView & bv);
+	virtual void redraw(BufferView & bv, ViewMetricsInfo const & vi);
+
+	/// grey out (no buffer)
+	void greyOut();
 
 	/// hide the visible cursor, if it is visible
 	void hideCursor();
@@ -72,14 +80,9 @@ protected:
 	virtual void removeCursor() = 0;
 
 private:
-	/// grey out (no buffer)
-	void greyOut();
 
 	/// is the cursor currently displayed
 	bool cursor_visible_;
-
-	/// is the screen displaying text or the splash screen?
-	bool greyed_out_;
 };
 
 #endif // SCREEN_H

Reply via email to