The attached patch builds on Abdel's earlier work and, I think, solves the remaining problems. Whether this is the best way to do it, I'm not sure. Abdel was talking about a more major re-organization of the code, but maybe that could wait.

What I've done is add an optional argument to LFUN_BUFFER_CHILD_OPEN indicating whether the file is being auto-loaded. (Contrary to what I said before, this is ok, since we're expecting a valid LyX filename, and one isn't going to end with "|true".) There are also corresponding booleans in LyXView::loadLyXFile and BufferView::loadLyXFile.

Abdel, I'll leave it up to you to decide what's best here. But either way, please see the long FIXME at the end of LyXView::loadLyXFile(). It looks to me as if we're doing a lot of things twice.

Richard

--
==================================================================
Richard G Heck, Jr
Professor of Philosophy
Brown University
http://frege.brown.edu/heck/
==================================================================
Get my public key from http://sks.keyserver.penguin.de
Hash: 0x1DE91F1E66FFBDEC
Learn how to sign your email using Thunderbird and GnuPG at:
http://dudu.dyn.2-h.org/nist/gpg-enigmail-howto

Index: src/Buffer.cpp
===================================================================
--- src/Buffer.cpp	(revision 18803)
+++ src/Buffer.cpp	(working copy)
@@ -1616,7 +1616,11 @@
 
 void Buffer::setParentName(string const & name)
 {
-	params().parentname = name;
+	if (name == pimpl_->filename.absFilename())
+		// Avoids recursive include.
+		params().parentname.clear();
+	else
+		params().parentname = name;
 }
 
 
Index: src/BufferView.cpp
===================================================================
--- src/BufferView.cpp	(revision 18803)
+++ src/BufferView.cpp	(working copy)
@@ -233,8 +233,8 @@
 		graphics::Previews::get().generateBufferPreviews(*buffer_);
 }
 
-
-bool BufferView::loadLyXFile(FileName const & filename, bool tolastfiles)
+// FIXME: all of this should go in a helper file in buffer_func.
+Buffer * BufferView::loadLyXFile(FileName const & filename, bool auto_open)
 {
 	// File already open?
 	if (theBufferList().exists(filename.absFilename())) {
@@ -246,12 +246,13 @@
 			text, 0, 1,  _("&Revert"), _("&Switch to document"));
 
 		if (ret != 0) {
-			setBuffer(theBufferList().getBuffer(filename.absFilename()));
-			return true;
+      Buffer * buf = theBufferList().getBuffer(filename.absFilename());
+			setBuffer(buf);
+			return buf;
 		}
 		// FIXME: should be LFUN_REVERT
 		if (!theBufferList().close(theBufferList().getBuffer(filename.absFilename()), false))
-			return false;
+			return 0;
 		// Fall through to new load. (Asger)
 		buffer_ = 0;
 	}
@@ -262,7 +263,7 @@
 		b = theBufferList().newBuffer(filename.absFilename());
 		if (!lyx::loadLyXFile(b, filename)) {
 			theBufferList().release(b);
-			return false;
+			return 0;
 		}
 	} else {
 		docstring text = bformat(_("The document %1$s does not yet "
@@ -274,34 +275,15 @@
 		if (ret == 0) {
 			b = newFile(filename.absFilename(), string(), true);
 			if (!b)
-				return false;
+				return 0;
 		} else
-			return false;
+			return 0;
 	}
 
-	setBuffer(b);
-	// Send the "errors" signal in case of parsing errors
-	b->errors("Parse");
+  if (!auto_open)
+  	setBuffer(b);
 
-	// Update the labels and section numbering.
-	updateLabels(*buffer_);
-	// scroll to the position when the file was last closed
-	if (lyxrc.use_lastfilepos) {
-		pit_type pit;
-		pos_type pos;
-		boost::tie(pit, pos) = LyX::ref().session().lastFilePos().load(filename);
-		// if successfully move to pit (returned par_id is not zero), update metrics and reset font
-		if (moveToPosition(pit, pos, 0, 0).get<1>()) {
-			if (fitCursor())
-				updateMetrics(false);
-			buffer_->text().setCurrentFont(cursor_);
-		}
-	}
-
-	if (tolastfiles)
-		LyX::ref().session().lastFiles().add(FileName(b->fileName()));
-
-	return true;
+	return b;
 }
 
 
Index: src/BufferView.h
===================================================================
--- src/BufferView.h	(revision 18803)
+++ src/BufferView.h	(working copy)
@@ -94,7 +94,8 @@
 	void resize();
 
 	/// load a buffer into the view.
-	bool loadLyXFile(support::FileName const & name, bool tolastfiles = true);
+  /// returns the buffer or 0 if not loaded
+	Buffer * loadLyXFile(support::FileName const & name, bool auto_open = false);
 
 	/// perform pending metrics updates.
 	/** \c Update::FitCursor means first to do a FitCursor, and to
Index: src/LyX.cpp
===================================================================
--- src/LyX.cpp	(revision 18803)
+++ src/LyX.cpp	(working copy)
@@ -613,7 +613,7 @@
 	if (!pimpl_->files_to_load_.empty()) {
 		for_each(pimpl_->files_to_load_.begin(),
 			pimpl_->files_to_load_.end(),
-			bind(&LyXView::loadLyXFile, view, _1, true));
+			bind(&LyXView::loadLyXFile, view, _1, true, false, false));
 		// clear this list to save a few bytes of RAM
 		pimpl_->files_to_load_.clear();
 		pimpl_->session_->lastOpened().clear();
@@ -628,7 +628,7 @@
 	// last session, and should be already there (regular files), or should
 	// not be added at all (help files).
 	for_each(lastopened.begin(), lastopened.end(),
-		bind(&LyXView::loadLyXFile, view, _1, false));
+		bind(&LyXView::loadLyXFile, view, _1, false, false, false));
 
 	// clear this list to save a few bytes of RAM
 	pimpl_->session_->lastOpened().clear();
Index: src/LyXFunc.cpp
===================================================================
--- src/LyXFunc.cpp	(revision 18803)
+++ src/LyXFunc.cpp	(working copy)
@@ -1410,24 +1410,35 @@
 		}
 
 		case LFUN_BUFFER_CHILD_OPEN: {
+      // takes an optional argument, "|bool", at the end
+      // indicating whether this file is being opened automatically
+      // by LyX itself, in which case we will not want to switch
+      // buffers after opening. The default is false, so in practice
+      // it is used only when true.
 			BOOST_ASSERT(lyx_view_);
-			FileName const filename =
-				makeAbsPath(argument, lyx_view_->buffer()->filePath());
+      int const arglength = argument.length();
+			FileName filename;
+      bool autoOpen = false;
+      if (argument.substr(arglength - 5, 5) == "|true") {
+        autoOpen = true;
+        filename = makeAbsPath(argument.substr(0, arglength - 5), 
+                               lyx_view_->buffer()->filePath());
+      } else if (argument.substr(arglength - 6, 6) == "|false") {
+        filename = makeAbsPath(argument.substr(0, arglength - 6), 
+                               lyx_view_->buffer()->filePath());
+      } else filename = 
+        makeAbsPath(argument, lyx_view_->buffer()->filePath());
 			view()->saveBookmark(false);
-			string const parentfilename = lyx_view_->buffer()->fileName();
-			if (theBufferList().exists(filename.absFilename()))
-				lyx_view_->setBuffer(theBufferList().getBuffer(filename.absFilename()));
-			else
-				if (lyx_view_->loadLyXFile(filename)) {
-					// Set the parent name of the child document.
-					// This makes insertion of citations and references in the child work,
-					// when the target is in the parent or another child document.
-					lyx_view_->buffer()->setParentName(parentfilename);
-					setMessage(bformat(_("Opening child document %1$s..."),
-						 makeDisplayPath(filename.absFilename())));
-				} else
-					setMessage(_("Document not loaded."));
-			break;
+			if (theBufferList().exists(filename.absFilename())) {
+        Buffer * buf = theBufferList().getBuffer(filename.absFilename());
+        if (!autoOpen)
+				  lyx_view_->setBuffer(buf, true);
+        else
+          buf->setParentName(lyx_view_->buffer()->fileName());
+			} else
+        lyx_view_->loadLyXFile(filename, true, true, autoOpen);
+			
+      break;
 		}
 
 		case LFUN_TOGGLE_CURSOR_FOLLOWS_SCROLLBAR:
Index: src/frontends/LyXView.cpp
===================================================================
--- src/frontends/LyXView.cpp	(revision 18803)
+++ src/frontends/LyXView.cpp	(working copy)
@@ -20,6 +20,7 @@
 #include "Gui.h"
 
 #include "Buffer.h"
+#include "buffer_funcs.h"
 #include "BufferList.h"
 #include "BufferParams.h"
 #include "BufferView.h"
@@ -31,6 +32,7 @@
 #include "gettext.h"
 #include "Intl.h"
 #include "callback.h"
+#include "LyX.h"
 #include "LyXFunc.h"
 #include "LyXRC.h"
 #include "Text.h"
@@ -122,27 +124,44 @@
 }
 
 
-void LyXView::setBuffer(Buffer * b)
+void LyXView::setBuffer(Buffer * b, bool child_document)
 {
 	busy(true);
 
 	BOOST_ASSERT(work_area_);
-	if (work_area_->bufferView().buffer())
+	Buffer * oldBuffer = work_area_->bufferView().buffer();
+	// parentfilename will be used in case when we switch to a child
+	// document (hence when child_document is true)
+	string parentfilename;
+	if (oldBuffer) {
+		parentfilename = oldBuffer->fileName();
 		disconnectBuffer();
+	}
 
 	if (!b && theBufferList().empty())
 		getDialogs().hideBufferDependent();
 
 	work_area_->bufferView().setBuffer(b);
-	// Make sure the TOC is updated before anything else.
-	updateToc();
 
-	if (work_area_->bufferView().buffer()) {
+	Buffer * newBuffer = work_area_->bufferView().buffer();
+	if (newBuffer) {
+		if (child_document && newBuffer != oldBuffer) {
+			// Set the parent name of the child document.
+			// This makes insertion of citations and references in the child work,
+			// when the target is in the parent or another child document.
+			newBuffer->setParentName(parentfilename);
+			// updateLabels() will emit Buffer::structureChanged() so better
+			// connect it before.
+			connectBuffer(*newBuffer);
+			// Update the labels and section numbering.
+			updateLabels(*newBuffer->getMasterBuffer());
+		} else
+			connectBuffer(*newBuffer);
+
 		// Buffer-dependent dialogs should be updated or
 		// hidden. This should go here because some dialogs (eg ToC)
 		// require bv_->text.
 		getDialogs().updateBufferDependent(true);
-		connectBuffer(*work_area_->bufferView().buffer());
 	}
 
 	if (quitting)
@@ -159,34 +178,82 @@
 }
 
 
-bool LyXView::loadLyXFile(FileName const & filename, bool tolastfiles)
+bool LyXView::loadLyXFile(FileName const & filename, bool tolastfiles,
+		bool child_document, bool auto_open)
 {
 	busy(true);
 
 	BOOST_ASSERT(work_area_);
-	bool const hadBuffer = work_area_->bufferView().buffer();
-	if (hadBuffer)
-		disconnectBuffer();
+	string parentfilename;
+	Buffer * oldBuffer = work_area_->bufferView().buffer();
+	if (oldBuffer)
+		parentfilename = oldBuffer->fileName();
 
-	bool const loaded =
-		work_area_->bufferView().loadLyXFile(filename, tolastfiles);
+	Buffer * newBuffer =
+		work_area_->bufferView().loadLyXFile(filename, auto_open);
 
-	updateToc();
+  if (!newBuffer) {
+		message(_("Document not loaded."));
+    updateStatusBar();
+    busy(false);
+    work_area_->redraw();
+    return false;
+  }
+  
+  if (!auto_open) {
+    disconnectBuffer();
+    connectBuffer(*newBuffer);
+  }
+
+  showErrorList("Parse");
+
+  if (child_document && newBuffer != oldBuffer) {
+    // Set the parent name of the child document.
+    // This makes insertion of citations and references in the child work,
+    // when the target is in the parent or another child document.
+    newBuffer->setParentName(parentfilename);
+    message(bformat(_("Opening child document %1$s..."),
+      makeDisplayPath(filename.absFilename())));
+  }
+  
+  // Update the labels and section numbering.
+  updateLabels(*newBuffer->getMasterBuffer());
+
+  // scroll to the position when the file was last closed
+  if (!auto_open && lyxrc.use_lastfilepos) {
+    pit_type pit;
+    pos_type pos;
+    boost::tie(pit, pos) = LyX::ref().session().lastFilePos().load(filename);
+    // if successfully move to pit (returned par_id is not zero),
+    // update metrics and reset font
+    if (work_area_->bufferView().moveToPosition(pit, pos, 0, 0).get<1>()) {
+      if (work_area_->bufferView().fitCursor())
+        work_area_->bufferView().updateMetrics(false);
+      newBuffer->text().setCurrentFont(work_area_->bufferView().cursor());
+    }
+  }
+
+  if (tolastfiles)
+    LyX::ref().session().lastFiles().add(filename);
+
+  // FIXME We definitely don't have to do all of this if auto_open...
+  // The question is: What do we have to do here if we've loaded a new
+  // file but haven't switched buffers? I'm guessing we can skip the
+  // layout big and the title.
+  // and if we have already switched buffers...won't all of this have been
+  // done already in setBuffer()? So why does it also need doing here?
+  // In fact, won't a lot of what's above already have been done?  E.g.,
+  // the connecting and disconnecting of buffers will have been done
+  // already in setBuffer().
 	updateMenubar();
 	updateToolbars();
 	updateLayoutChoice();
 	updateWindowTitle();
 	updateTab();
-	if (loaded) {
-		connectBuffer(*work_area_->bufferView().buffer());
-		showErrorList("Parse");
-	} else if (hadBuffer)
-		//Need to reconnect the buffer if the load failed
-		connectBuffer(*work_area_->bufferView().buffer());
 	updateStatusBar();
 	busy(false);
 	work_area_->redraw();
-	return loaded;
+	return true;
 }
 
 
@@ -230,7 +297,7 @@
 
 	closingConnection_ =
 		buf.closing.connect(
-			boost::bind(&LyXView::setBuffer, this, (Buffer *)0));
+			boost::bind(&LyXView::setBuffer, this, (Buffer *)0, false));
 }
 
 
Index: src/frontends/LyXView.h
===================================================================
--- src/frontends/LyXView.h	(revision 18803)
+++ src/frontends/LyXView.h	(working copy)
@@ -142,11 +142,15 @@
 
 	//@}
 
-	/// load a buffer into the current workarea
-	bool loadLyXFile(support::FileName const &  name, bool tolastfiles = true);
+	/// load a buffer into the current workarea.
+	bool loadLyXFile(support::FileName const &  name, ///< File to load.
+		bool tolastfiles = true,  ///< append to the "Open recent" menu?
+		bool child_document = false, ///< Is this a child document?
+    bool auto_open = false); ///< Is this being opened by LyX itself?
 
-	/// set a buffer to the current workarea
-	void setBuffer(Buffer * b);
+	/// set a buffer to the current workarea.
+	void setBuffer(Buffer * b, ///< \c Buffer to set.
+		bool child_document = false);  ///< Is this a child document?
 
 	/// updates the possible layouts selectable
 	void updateLayoutChoice();
Index: src/insets/InsetInclude.cpp
===================================================================
--- src/insets/InsetInclude.cpp	(revision 18803)
+++ src/insets/InsetInclude.cpp	(working copy)
@@ -52,6 +52,9 @@
 
 
 namespace lyx {
+  
+// Implementation is in LyX.cpp
+extern void dispatch(FuncRequest const & action);
 
 using support::addName;
 using support::absolutePath;
@@ -400,12 +403,10 @@
 		// the readonly flag can/will be wrong, not anymore I think.
 		if (!fs::exists(included_file.toFilesystemEncoding()))
 			return false;
-		buf = theBufferList().newBuffer(included_file.absFilename());
-		if (!loadLyXFile(buf, included_file)) {
-			//close the buffer we just opened
-			theBufferList().close(buf, false);
-			return false;
-		}
+		lyx::dispatch(FuncRequest(LFUN_BUFFER_CHILD_OPEN,
+			included_file.absFilename() + "|true"));
+		buf = theBufferList().getBuffer(included_file.absFilename());
+		return buf;
 	}
 	buf->setParentName(parentFilename(buffer));
 	return true;

Reply via email to