The attached patch backports r27635, r28193, r28194, r28220, r29094, and r29095. The point of these, taken together, is to improve the display of information in InsetCitation and GuiCitation, by gathering missing data from the crossref, if one is defined, basically as BibTeX does.

OK?

rh

Index: src/BiblioInfo.h
===================================================================
--- src/BiblioInfo.h	(revision 29157)
+++ src/BiblioInfo.h	(working copy)
@@ -38,8 +38,9 @@
 
 /// Class to represent information about a BibTeX or
 /// bibliography entry.
-/// The keys are BibTeX fields (e.g., author, title, etc), 
-/// and the values are the associated field values.
+/// This class basically wraps a std::map, and many of its
+/// methods simply delegate to the corresponding methods of
+/// std::map.
 class BibTeXInfo {
 public:
 	///
@@ -51,36 +52,43 @@
 	BibTeXInfo(bool ib) : is_bibtex_(ib) {}
 	/// constructor that sets the entryType
 	BibTeXInfo(docstring const & key, docstring const & type);
-	/// Search for the given field and return the associated info.
-	/// The point of this is that BibTeXInfo::operator[] has no const
-	/// form.
-	docstring const & getValueForField(docstring const & field) const;
 	///
-	docstring const & getValueForField(std::string const & field) const;
-	///
 	bool hasField(docstring const & field) const;
 	/// return the short form of an authorlist
 	docstring const getAbbreviatedAuthor() const;
 	/// 
 	docstring const getYear() const;
-	/// Returns formatted BibTeX data suitable for framing.
-	docstring const getInfo() const;
 	///
+	docstring const getXRef() const;
+	/// \return formatted BibTeX data suitable for framing.
+	/// \param pointer to crossref information
+	docstring const & getInfo(BibTeXInfo const * const xref = 0) const;
+	///
 	int count(docstring const & f) const { return bimap_.count(f); }
 	///
 	const_iterator find(docstring const & f) const { return bimap_.find(f); }
 	///
 	const_iterator end() const { return bimap_.end(); }
-	///
+	/// \return value for field f
+	/// note that this will create an empty field if it does not exist
 	docstring & operator[](docstring const & f) 
 		{ return bimap_[f]; }
+	/// \return value for field f
+	/// this one, since it is const, will simply return docstring() if
+	/// we don't have the field and will NOT create an empty field
+	docstring const & operator[](docstring const & field) const;
 	///
+	docstring const & operator[](std::string const & field) const;
+	///
 	docstring const & allData() const { return all_data_; }
 	///
 	void setAllData(docstring const & d) { all_data_ = d; }
 	///
 	docstring entryType() const { return entry_type_; }
 private:
+	/// like operator[], except it will also check the given xref
+	docstring getValueForKey(std::string const & key, 
+			BibTeXInfo const * const xref = 0) const;
 	/// true if from BibTeX; false if from bibliography environment
 	bool is_bibtex_;
 	/// the BibTeX key for this entry
@@ -111,9 +119,12 @@
 	/// return the short form of an authorlist
 	docstring const getAbbreviatedAuthor(docstring const & key) const;
 	/// return the year from the bibtex data record
+	/// Note that this will get the year from the crossref if it's
+	/// not present in the record itself
 	docstring const getYear(docstring const & key) const;
 	/// Returns formatted BibTeX data associated with a given key.
 	/// Empty if no info exists. 
+	/// Note that this will retrieve data from the crossref as needed.
 	docstring const getInfo(docstring const & key) const;
 	
 	/**
Index: src/frontends/qt4/GuiCitation.cpp
===================================================================
--- src/frontends/qt4/GuiCitation.cpp	(revision 29157)
+++ src/frontends/qt4/GuiCitation.cpp	(working copy)
@@ -702,7 +702,7 @@
 		else if (field.empty())
 			data = to_utf8(*it) + ' ' + to_utf8(kvm.allData());
 		else if (kvm.hasField(field))
-			data = to_utf8(kvm.getValueForField(field));
+			data = to_utf8(kvm[field]);
 		
 		if (data.empty())
 			continue;
Index: src/BiblioInfo.cpp
===================================================================
--- src/BiblioInfo.cpp	(revision 29157)
+++ src/BiblioInfo.cpp	(working copy)
@@ -39,39 +39,9 @@
 
 namespace lyx {
 
-//////////////////////////////////////////////////////////////////////
-//
-// BibTeXInfo
-//
-//////////////////////////////////////////////////////////////////////
+namespace {
 
-BibTeXInfo::BibTeXInfo(docstring const & key, docstring const & type)
-	: is_bibtex_(true), bib_key_(key), entry_type_(type), info_()
-{}
-
-
-bool BibTeXInfo::hasField(docstring const & field) const
-{
-	return count(field) == 1;
-}
-
-
-docstring const & BibTeXInfo::getValueForField(docstring const & field) const
-{
-	BibTeXInfo::const_iterator it = find(field);
-	if (it != end())
-		return it->second;
-	static docstring const empty_value = docstring();
-	return empty_value;
-}
-	
-	
-docstring const & BibTeXInfo::getValueForField(string const & field) const
-{
-	return getValueForField(from_ascii(field));
-}
-
-
+// gets the "family name" from an author-type string
 docstring familyName(docstring const & name)
 {
 	if (name.empty())
@@ -118,65 +88,10 @@
 	return retval;
 }
 
-docstring const BibTeXInfo::getAbbreviatedAuthor() const
-{
-	if (!is_bibtex_) {
-		docstring const opt = trim(getValueForField("label"));
-		if (opt.empty())
-			return docstring();
 
-		docstring authors;
-		split(opt, authors, '(');
-		return authors;
-	}
-
-	docstring author = getValueForField("author");
-	if (author.empty()) {
-		author = getValueForField("editor");
-		if (author.empty())
-			return bib_key_;
-	}
-
-	// OK, we've got some names. Let's format them.
-	// Try to split the author list on " and "
-	vector<docstring> const authors =
-		getVectorFromString(author, from_ascii(" and "));
-
-	if (authors.size() == 2)
-		return bformat(_("%1$s and %2$s"),
-			familyName(authors[0]), familyName(authors[1]));
-
-	if (authors.size() > 2)
-		return bformat(_("%1$s et al."), familyName(authors[0]));
-
-	return familyName(authors[0]);
-}
-
-
-docstring const BibTeXInfo::getYear() const
-{
-	if (!is_bibtex_) {
-		docstring const opt = trim(getValueForField("label"));
-		if (opt.empty())
-			return docstring();
-
-		docstring authors;
-		docstring const tmp = split(opt, authors, '(');
-		docstring year;
-		split(tmp, year, ')');
-		return year;
-	}
-
-	docstring year = getValueForField("year");
-	if (year.empty())
-		year = _("No year");
-	return year;
-}
-
-
-namespace {
-
-	docstring convertLaTeXCommands(docstring const & str)
+// converts a string containing LaTeX commands into unicode
+// for display.
+docstring convertLaTeXCommands(docstring const & str)
 	{
 		docstring val = str;
 		docstring ret;
@@ -274,8 +189,85 @@
 } // anon namespace
 
 
-docstring const BibTeXInfo::getInfo() const
+//////////////////////////////////////////////////////////////////////
+//
+// BibTeXInfo
+//
+//////////////////////////////////////////////////////////////////////
+
+BibTeXInfo::BibTeXInfo(docstring const & key, docstring const & type)
+	: is_bibtex_(true), bib_key_(key), entry_type_(type), info_()
+{}
+
+
+bool BibTeXInfo::hasField(docstring const & field) const
 {
+	return count(field) == 1;
+}
+
+
+docstring const BibTeXInfo::getAbbreviatedAuthor() const
+{
+	if (!is_bibtex_) {
+		docstring const opt = trim(operator[]("label"));
+		if (opt.empty())
+			return docstring();
+
+		docstring authors;
+		split(opt, authors, '(');
+		return authors;
+	}
+
+	docstring author = operator[]("author");
+	if (author.empty()) {
+		author = operator[]("editor");
+		if (author.empty())
+			return bib_key_;
+	}
+
+	// OK, we've got some names. Let's format them.
+	// Try to split the author list on " and "
+	vector<docstring> const authors =
+		getVectorFromString(author, from_ascii(" and "));
+
+	if (authors.size() == 2)
+		return bformat(_("%1$s and %2$s"),
+			familyName(authors[0]), familyName(authors[1]));
+
+	if (authors.size() > 2)
+		return bformat(_("%1$s et al."), familyName(authors[0]));
+
+	return familyName(authors[0]);
+}
+
+
+docstring const BibTeXInfo::getYear() const
+{
+	if (is_bibtex_) 
+		return operator[]("year");
+
+	docstring const opt = trim(operator[]("label"));
+	if (opt.empty())
+		return docstring();
+
+	docstring authors;
+	docstring const tmp = split(opt, authors, '(');
+	docstring year;
+	split(tmp, year, ')');
+	return year;
+}
+
+
+docstring const BibTeXInfo::getXRef() const
+{
+	if (!is_bibtex_)
+		return docstring();
+	return operator[]("crossref");
+}
+
+
+docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref) const
+{
 	if (!info_.empty())
 		return info_;
 
@@ -286,35 +278,35 @@
 	}
  
 	// FIXME
-	// This could be made a lot better using the entryType
+	// This could be made a lot better using the entry_type_
 	// field to customize the output based upon entry type.
 	
 	// Search for all possible "required" fields
-	docstring author = getValueForField("author");
+	docstring author = getValueForKey("author", xref);
 	if (author.empty())
-		author = getValueForField("editor");
+		author = getValueForKey("editor", xref);
  
-	docstring year      = getValueForField("year");
-	docstring title     = getValueForField("title");
-	docstring docLoc    = getValueForField("pages");
+	docstring year   = getValueForKey("year", xref);
+	docstring title  = getValueForKey("title", xref);
+	docstring docLoc = getValueForKey("pages", xref);
 	if (docLoc.empty()) {
-		docLoc = getValueForField("chapter");
+		docLoc = getValueForKey("chapter", xref);
 		if (!docLoc.empty())
 			docLoc = _("Ch. ") + docLoc;
 	}	else {
 		docLoc = _("pp. ") + docLoc;
 	}
 
-	docstring media = getValueForField("journal");
+	docstring media = getValueForKey("journal", xref);
 	if (media.empty()) {
-		media = getValueForField("publisher");
+		media = getValueForKey("publisher", xref);
 		if (media.empty()) {
-			media = getValueForField("school");
+			media = getValueForKey("school", xref);
 			if (media.empty())
-				media = getValueForField("institution");
+				media = getValueForKey("institution");
 		}
 	}
-	docstring volume = getValueForField("volume");
+	docstring volume = getValueForKey("volume", xref);
 
 	odocstringstream result;
 	if (!author.empty())
@@ -324,7 +316,7 @@
 	if (!media.empty())
 		result << ", " << media;
 	if (!year.empty())
-		result << ", " << year;
+		result << " (" << year << ")";
 	if (!docLoc.empty())
 		result << ", " << docLoc;
 
@@ -335,10 +327,37 @@
 	}
 
 	// This should never happen (or at least be very unusual!)
-	return docstring();
+	static docstring e = docstring();
+	return e;
 }
 
 
+docstring const & BibTeXInfo::operator[](docstring const & field) const
+{
+	BibTeXInfo::const_iterator it = find(field);
+	if (it != end())
+		return it->second;
+	static docstring const empty_value = docstring();
+	return empty_value;
+}
+	
+	
+docstring const & BibTeXInfo::operator[](string const & field) const
+{
+	return operator[](from_ascii(field));
+}
+
+
+docstring BibTeXInfo::getValueForKey(string const & key, 
+		BibTeXInfo const * const xref) const
+{
+	docstring const ret = operator[](key);
+	if (!ret.empty() or !xref)
+		return ret;
+	return (*xref)[key];
+}
+
+
 //////////////////////////////////////////////////////////////////////
 //
 // BiblioInfo
@@ -408,6 +427,18 @@
 	if (it == end())
 		return docstring();
 	BibTeXInfo const & data = it->second;
+	docstring year = data.getYear();
+	if (!year.empty())
+		return year;
+	// let's try the crossref
+	docstring const xref = data.getXRef();
+	if (xref.empty())
+		return _("No year"); // no luck
+	BiblioInfo::const_iterator const xrefit = find(xref);
+	if (xrefit == end())
+		return _("No year"); // no luck again
+	BibTeXInfo const & xref_data = xrefit->second;
+	return xref_data.getYear();
 	return data.getYear();
 }
 
@@ -418,7 +449,14 @@
 	if (it == end())
 		return docstring();
 	BibTeXInfo const & data = it->second;
-	return data.getInfo();
+	BibTeXInfo const * xrefptr = 0;
+	docstring const xref = data.getXRef();
+	if (!xref.empty()) {
+		BiblioInfo::const_iterator const xrefit = find(xref);
+		if (xrefit != end())
+			xrefptr = &(xrefit->second);
+	}
+	return data.getInfo(xrefptr);
 }
 
 

Reply via email to