Jean-Marc Lasgouttes wrote:
> Could you provide a 1.4 version so that I take a look?

attached.

Jürgen

> JMarc
Index: src/insets/insetbibtex.C
===================================================================
--- src/insets/insetbibtex.C	(Revision 13775)
+++ src/insets/insetbibtex.C	(Arbeitskopie)
@@ -85,9 +85,10 @@ void InsetBibtex::doDispatch(LCursor & c
 	case LFUN_INSET_MODIFY: {
 		InsetCommandParams p;
 		InsetCommandMailer::string2params("bibtex", cmd.argument, p);
-		if (!p.getCmdName().empty())
+		if (!p.getCmdName().empty()) {
 			setParams(p);
-		else
+			cur.buffer().updateBibfilesCache();
+		} else
 			cur.noUpdate();
 		break;
 	}
Index: src/insets/insetinclude.h
===================================================================
--- src/insets/insetinclude.h	(Revision 13775)
+++ src/insets/insetinclude.h	(Arbeitskopie)
@@ -52,9 +52,19 @@ public:
 	 *  \param buffer the Buffer containing this inset.
 	 *  \param keys the list of bibkeys in the child buffer.
 	 */
-	///
 	void fillWithBibKeys(Buffer const & buffer,
 		std::vector<std::pair<std::string,std::string> > & keys) const;
+	/** Update the cache with all bibfiles in use of the child buffer
+	 *  (including bibfiles of grandchild documents).
+	 *  \param buffer the Buffer containing this inset.
+	 */
+	void updateBibfilesCache(Buffer const & buffer);
+	/** Return the cache with all bibfiles in use of the child buffer
+	 *  (including bibfiles of grandchild documents).
+	 *  \param buffer the Buffer containing this inset.
+	 */
+	std::vector<std::string> const &
+	getBibfilesCache(Buffer const & buffer) const;
 	///
 	EDITABLE editable() const { return IS_EDITABLE; }
 	///
Index: src/insets/insetinclude.C
===================================================================
--- src/insets/insetinclude.C	(Revision 13775)
+++ src/insets/insetinclude.C	(Arbeitskopie)
@@ -128,9 +128,10 @@ void InsetInclude::doDispatch(LCursor & 
 	case LFUN_INSET_MODIFY: {
 		InsetCommandParams p;
 		InsetIncludeMailer::string2params(cmd.argument, p);
-		if (!p.getCmdName().empty())
+		if (!p.getCmdName().empty()) {
 			set(p, cur.buffer());
-		else
+			cur.buffer().updateBibfilesCache();
+		} else
 			cur.noUpdate();
 		break;
 	}
@@ -613,6 +614,34 @@ void InsetInclude::fillWithBibKeys(Buffe
 }
 
 
+void InsetInclude::updateBibfilesCache(Buffer const & buffer)
+{
+	if (loadIfNeeded(buffer, params_)) {
+		string const included_file = includedFilename(buffer, params_);
+		Buffer * tmp = bufferlist.getBuffer(included_file);
+		tmp->setParentName("");
+		tmp->updateBibfilesCache();
+		tmp->setParentName(parentFilename(buffer));
+	}
+}
+
+
+std::vector<string> const &
+InsetInclude::getBibfilesCache(Buffer const & buffer) const
+{
+	if (loadIfNeeded(buffer, params_)) {
+		string const included_file = includedFilename(buffer, params_);
+		Buffer * tmp = bufferlist.getBuffer(included_file);
+		tmp->setParentName("");
+		std::vector<string> const & cache = tmp->getBibfilesCache();
+		tmp->setParentName(parentFilename(buffer));
+		return cache;
+	}
+	static std::vector<string> const empty;
+	return empty;
+}
+
+
 void InsetInclude::metrics(MetricsInfo & mi, Dimension & dim) const
 {
 	BOOST_ASSERT(mi.base.bv && mi.base.bv->buffer());
Index: src/insets/insetcite.C
===================================================================
--- src/insets/insetcite.C	(Revision 13775)
+++ src/insets/insetcite.C	(Arbeitskopie)
@@ -24,6 +24,8 @@
 
 #include "support/lstrings.h"
 
+#include <boost/filesystem/operations.hpp>
+
 using lyx::support::ascii_lowercase;
 using lyx::support::contains;
 using lyx::support::getVectorFromString;
@@ -37,6 +39,7 @@ using std::vector;
 using std::map;
 
 namespace biblio = lyx::biblio;
+namespace fs = boost::filesystem;
 
 
 namespace {
@@ -50,26 +53,47 @@ string const getNatbibLabel(Buffer const
 	if (!buffer.fully_loaded())
 		return string();
 
+	// Cache the labels
 	typedef std::map<Buffer const *, biblio::InfoMap> CachedMap;
 	static CachedMap cached_keys;
 
-	// build the keylist
-	typedef vector<std::pair<string, string> > InfoType;
-	InfoType bibkeys;
-	buffer.fillWithBibKeys(bibkeys);
-
-	InfoType::const_iterator bit  = bibkeys.begin();
-	InfoType::const_iterator bend = bibkeys.end();
+	// and cache the timestamp of the bibliography files.
+	static std::map<string, time_t> bibfileStatus;
 
 	biblio::InfoMap infomap;
-	for (; bit != bend; ++bit) {
-		infomap[bit->first] = bit->second;
+
+	vector<string> const & bibfilesCache = buffer.getBibfilesCache();
+	// compare the cached timestamps with the actual ones.
+	bool changed = false;
+	for (vector<string>::const_iterator it = bibfilesCache.begin();
+			it != bibfilesCache.end(); ++ it) {
+		string const f = *it;
+		if (bibfileStatus[f] != fs::last_write_time(f)) {
+			changed = true;
+			bibfileStatus[f] = fs::last_write_time(f);
+		}
 	}
+
+	// build the keylist only if the bibfiles have been changed
+	if (cached_keys.empty() || bibfileStatus.empty() || changed) {
+		typedef vector<std::pair<string, string> > InfoType;
+		InfoType bibkeys;
+		buffer.fillWithBibKeys(bibkeys);
+
+		InfoType::const_iterator bit  = bibkeys.begin();
+		InfoType::const_iterator bend = bibkeys.end();
+
+		for (; bit != bend; ++bit)
+			infomap[bit->first] = bit->second;
+
+		cached_keys[&buffer] = infomap;
+	} else
+		// use the cached keys
+		infomap = cached_keys[&buffer];
+
 	if (infomap.empty())
 		return string();
 
-	cached_keys[&buffer] = infomap;
-
 	// the natbib citation-styles
 	// CITET:	author (year)
 	// CITEP:	(author,year)
Index: src/BufferView_pimpl.C
===================================================================
--- src/BufferView_pimpl.C	(Revision 13775)
+++ src/BufferView_pimpl.C	(Arbeitskopie)
@@ -1291,8 +1291,10 @@ bool BufferView::Pimpl::dispatch(FuncReq
 		bv_funcs::findInset(tmpcur, InsetBase::BIBTEX_CODE, false);
 		InsetBibtex * inset = getInsetByCode<InsetBibtex>(tmpcur,
 						InsetBase::BIBTEX_CODE);
-		if (inset)
-			inset->addDatabase(cmd.argument);
+		if (inset) {
+			if (inset->addDatabase(cmd.argument))
+				buffer_->updateBibfilesCache();
+		}
 		break;
 	}
 
@@ -1301,8 +1303,10 @@ bool BufferView::Pimpl::dispatch(FuncReq
 		bv_funcs::findInset(tmpcur, InsetBase::BIBTEX_CODE, false);
 		InsetBibtex * inset = getInsetByCode<InsetBibtex>(tmpcur,
 						InsetBase::BIBTEX_CODE);
-		if (inset)
-			inset->delDatabase(cmd.argument);
+		if (inset) {
+			if (inset->delDatabase(cmd.argument))
+				buffer_->updateBibfilesCache();
+		}
 		break;
 	}
 
Index: src/buffer.C
===================================================================
--- src/buffer.C	(Revision 13775)
+++ src/buffer.C	(Arbeitskopie)
@@ -487,6 +487,7 @@ bool Buffer::readDocument(LyXLex & lex)
 	for_each(text().paragraphs().begin(),
 		 text().paragraphs().end(),
 		 bind(&Paragraph::setInsetOwner, _1, &inset()));
+	updateBibfilesCache();
 	return res;
 }
 
@@ -1253,6 +1254,53 @@ void Buffer::fillWithBibKeys(vector<pair
 }
 
 
+void Buffer::updateBibfilesCache()
+{
+	// if this is a child document and the parent is already loaded
+	// update the parent's cache instead
+	Buffer * tmp = getMasterBuffer();
+	BOOST_ASSERT(tmp);
+	if (tmp != this) {
+		tmp->updateBibfilesCache();
+		return;
+	}
+
+	bibfilesCache_.clear();
+	for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
+		if (it->lyxCode() == InsetBase::BIBTEX_CODE) {
+			InsetBibtex const & inset =
+				dynamic_cast<InsetBibtex const &>(*it);
+			vector<string> const bibfiles = inset.getFiles(*this);
+			bibfilesCache_.insert(bibfilesCache_.end(),
+				bibfiles.begin(),
+				bibfiles.end());
+		} else if (it->lyxCode() == InsetBase::INCLUDE_CODE) {
+			InsetInclude & inset =
+				dynamic_cast<InsetInclude &>(*it);
+			inset.updateBibfilesCache(*this);
+			vector<string> const & bibfiles =
+					inset.getBibfilesCache(*this);
+			bibfilesCache_.insert(bibfilesCache_.end(),
+				bibfiles.begin(),
+				bibfiles.end());
+		}
+	}
+}
+
+
+vector<string> const & Buffer::getBibfilesCache() const
+{
+	// if this is a child document and the parent is already loaded
+	// use the parent's cache instead
+	Buffer const * tmp = getMasterBuffer();
+	BOOST_ASSERT(tmp);
+	if (tmp != this)
+		return tmp->getBibfilesCache();
+
+	return bibfilesCache_;
+}
+
+
 bool Buffer::isDepClean(string const & name) const
 {
 	DepClean::const_iterator const it = pimpl_->dep_clean.find(name);
@@ -1496,6 +1544,19 @@ Buffer const * Buffer::getMasterBuffer()
 }
 
 
+Buffer * Buffer::getMasterBuffer()
+{
+	if (!params().parentname.empty()
+	    && bufferlist.exists(params().parentname)) {
+		Buffer * buf = bufferlist.getBuffer(params().parentname);
+		if (buf)
+			return buf->getMasterBuffer();
+	}
+
+	return this;
+}
+
+
 MacroData const & Buffer::getMacro(std::string const & name) const
 {
 	return pimpl_->macros.get(name);
Index: src/buffer.h
===================================================================
--- src/buffer.h	(Revision 13775)
+++ src/buffer.h	(Arbeitskopie)
@@ -24,6 +24,7 @@
 #include <boost/signal.hpp>
 
 #include <iosfwd>
+#include <string>
 #include <map>
 #include <utility>
 #include <vector>
@@ -217,6 +218,10 @@ public:
 	    child document)
 	 */
 	Buffer const * getMasterBuffer() const;
+	/** Get the document's master (or \c this if this is not a
+	    child document)
+	 */
+	Buffer * getMasterBuffer();
 
 	/// Is buffer read-only?
 	bool isReadonly() const;
@@ -249,6 +254,12 @@ public:
 
 	/// return all bibkeys from buffer and its childs
 	void fillWithBibKeys(std::vector<std::pair<std::string, std::string> > & keys) const;
+	/// Update the cache with all bibfiles in use (including bibfiles
+	/// of child documents).
+	void updateBibfilesCache();
+	/// Return the cache with all bibfiles in use (including bibfiles
+	/// of child documents).
+	std::vector<std::string> const & getBibfilesCache() const;
 	///
 	void getLabelList(std::vector<std::string> &) const;
 
@@ -352,6 +363,9 @@ private:
 	/// it's BufferView, this should be FIXED in future.
 	StableDocIterator cursor_;
 	StableDocIterator anchor_;
+	/// A cache for the bibfiles (including bibfiles of child documents),
+	/// needed for appropriate update of natbib labels.
+	std::vector<std::string> bibfilesCache_;
 };
 
 #endif

Reply via email to