With the patch this time.

Attached is the latest patch addressing this bug. I'm seeking agreement
to commit it to trunk, for testing, prior to committing to branch,
hopefully for 1.5.2. This has been discussed with Jurgen already. JMarc,
or someone else: Does this seem OK?

If this does go in, I'll shortly start looking into re-working the
citation dialog so we can search on specified fields and not just on
everything at once. That shouldn't be at all difficult now.

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.h
===================================================================
--- src/Buffer.h	(revision 19264)
+++ src/Buffer.h	(working copy)
@@ -13,7 +13,11 @@
 #define BUFFER_H
 
 #include "DocIterator.h"
+#include "ErrorList.h"
+#include "InsetList.h"
 
+#include "frontends/controllers/frontend_helpers.h"
+
 #include "support/FileName.h"
 #include "support/limited_stack.h"
 #include "support/types.h"
@@ -283,7 +287,7 @@
 	void validate(LaTeXFeatures &) const;
 
 	/// return all bibkeys from buffer and its childs
-	void fillWithBibKeys(std::vector<std::pair<std::string, docstring> > & keys) const;
+	void fillWithBibKeys(biblio::BibKeyList & keys) const;
 	/// Update the cache with all bibfiles in use (including bibfiles
 	/// of loaded child documents).
 	void updateBibfilesCache();
Index: src/Buffer.cpp
===================================================================
--- src/Buffer.cpp	(revision 19264)
+++ src/Buffer.cpp	(working copy)
@@ -1333,7 +1333,7 @@
 
 
 // This is also a buffer property (ale)
-void Buffer::fillWithBibKeys(vector<pair<string, docstring> > & keys)
+void Buffer::fillWithBibKeys(biblio::BibKeyList & keys)
 	const
 {
 	/// if this is a child document and the parent is already loaded
@@ -1359,11 +1359,12 @@
 				static_cast<InsetBibitem const &>(*it);
 			// FIXME UNICODE
 			string const key = to_utf8(inset.getParam("key"));
-			docstring const label = inset.getParam("label");
+			biblio::KeyValMap keyvalmap;
+			keyvalmap[from_ascii("label")] = inset.getParam("label");
 			DocIterator doc_it(it); doc_it.forwardPos();
-			docstring const ref = doc_it.paragraph().asString(*this, false);
-			docstring const info = label + "TheBibliographyRef" + ref;
-			keys.push_back(pair<string, docstring>(key, info));
+			keyvalmap [from_ascii("ref")] = doc_it.paragraph().asString(*this, false);
+			keyvalmap[biblio::TheBibliographyRef] = biblio::TheBibliographyRef;
+			keys[key] = keyvalmap;
 		}
 	}
 }
@@ -1725,10 +1726,10 @@
 	vector<docstring> labels;
 
 	if (code == Inset::CITE_CODE) {
-		vector<pair<string, docstring> > keys;
+		biblio::BibKeyList keys;
 		fillWithBibKeys(keys);
-		vector<pair<string, docstring> >::const_iterator bit  = keys.begin();
-		vector<pair<string, docstring> >::const_iterator bend = keys.end();
+		biblio::BibKeyList::const_iterator bit  = keys.begin();
+		biblio::BibKeyList::const_iterator bend = keys.end();
 
 		for (; bit != bend; ++bit)
 			// FIXME UNICODE
Index: src/frontends/controllers/frontend_helpers.h
===================================================================
--- src/frontends/controllers/frontend_helpers.h	(revision 19264)
+++ src/frontends/controllers/frontend_helpers.h	(working copy)
@@ -28,8 +28,18 @@
 
 /** Functions of use to citation and bibtex GUI controllers and views */
 namespace lyx {
+	
 namespace biblio {
+	
+/// First entry is field, second is value
+typedef std::map<docstring, docstring> KeyValMap;
+/// First entry is the bibliography key, second the data
+typedef std::map<std::string, std::map<docstring, docstring> > BibKeyList;
 
+static const docstring TheBibliographyRef(from_ascii("@LyXInfo"));
+static const docstring TheDataString(from_ascii("@BibTeXData"));
+static const docstring TheEntryType(from_ascii("@BibTeXEntryType"));
+
 enum CiteEngine {
 	ENGINE_BASIC,
 	ENGINE_NATBIB_AUTHORYEAR,
@@ -69,34 +79,31 @@
 std::string const asValidLatexCommand(std::string const & input,
 				      CiteEngine const engine);
 
-/// First entry is the bibliography key, second the data
-typedef std::map<std::string, docstring> InfoMap;
-
 /// Returns a vector of bibliography keys
-std::vector<std::string> const getKeys(InfoMap const &);
+std::vector<std::string> const getKeys(BibKeyList const &);
 
 /** Returns the BibTeX data associated with a given key.
-    Empty if no info exists. */
-docstring const getInfo(InfoMap const &, std::string const & key);
+    Empty if the key was not defined in the BibTeX record. */
+docstring const getInfo(BibKeyList const &, std::string const & key);
 
 /// return the year from the bibtex data record
-docstring const getYear(InfoMap const & map, std::string const & key);
+docstring const getYear(BibKeyList const & map, std::string const & key);
 
 /// return the short form of an authorlist
-docstring const getAbbreviatedAuthor(InfoMap const & map, std::string const & key);
+docstring const getAbbreviatedAuthor(BibKeyList const & map, std::string const & key);
 
 // return only the family name
 docstring const familyName(docstring const & name);
 
 /** Search a BibTeX info field for the given key and return the
     associated field. */
-docstring const parseBibTeX(docstring data, std::string const & findkey);
+docstring const getValueForKey(KeyValMap data, std::string const & findkey);
 
 /** Returns an iterator to the first key that meets the search
     criterion, or end() if unsuccessful.
 
     User supplies :
-    the InfoMap of bibkeys info,
+    the BibKeyList of bibkeys info,
     the vector of keys to be searched,
     the search criterion,
     an iterator defining the starting point of the search,
@@ -105,7 +112,7 @@
 */
 
 std::vector<std::string>::const_iterator
-searchKeys(InfoMap const & map,
+searchKeys(BibKeyList const & map,
 	   std::vector<std::string> const & keys_to_search,
 	   docstring const & search_expression,
 	   std::vector<std::string>::const_iterator start,
@@ -145,12 +152,12 @@
 
    User supplies :
    the key,
-   the InfoMap of bibkeys info,
+   the BibKeyList of bibkeys info,
    the available citation styles
 */
 std::vector<docstring> const
 getNumericalStrings(std::string const & key,
-		    InfoMap const & map,
+		    BibKeyList const & map,
 		    std::vector<CiteStyle> const & styles);
 
 /**
@@ -162,12 +169,12 @@
 
    User supplies :
    the key,
-   the InfoMap of bibkeys info,
+   the BibKeyList of bibkeys info,
    the available citation styles
 */
 std::vector<docstring> const
 getAuthorYearStrings(std::string const & key,
-		     InfoMap const & map,
+		     BibKeyList const & map,
 		     std::vector<CiteStyle> const & styles);
 
 } // namespace biblio
Index: src/frontends/controllers/frontend_helpers.cpp
===================================================================
--- src/frontends/controllers/frontend_helpers.cpp	(revision 19264)
+++ src/frontends/controllers/frontend_helpers.cpp	(working copy)
@@ -26,9 +26,6 @@
 
 #include "support/filetools.h"
 #include "support/lstrings.h"
-#include "support/Package.h"
-#include "support/filetools.h"
-#include "support/lstrings.h"
 #include "support/lyxalgo.h"
 #include "support/os.h"
 #include "support/Package.h"
@@ -123,9 +120,6 @@
 	return str;
 }
 
-
-static const docstring TheBibliographyRef(from_ascii("TheBibliographyRef"));
-
 } // namespace anon
 
 
@@ -200,38 +194,29 @@
 }
 
 
-docstring const getAbbreviatedAuthor(InfoMap const & map, string const & key)
+docstring const getAbbreviatedAuthor(BibKeyList const & map, string const & key)
 {
 	BOOST_ASSERT(!map.empty());
 
-	InfoMap::const_iterator it = map.find(key);
+	BibKeyList::const_iterator it = map.find(key);
 	if (it == map.end())
 		return docstring();
-	docstring const & data = it->second;
+	KeyValMap const & data = it->second;
 
 	// Is the entry a BibTeX one or one from lyx-layout "bibliography"?
-	docstring::size_type const pos = data.find(TheBibliographyRef);
-	if (pos != docstring::npos) {
-		if (pos <= 2) {
-			return docstring();
-		}
+	KeyValMap::const_iterator it2 = data.find(TheBibliographyRef);
+	if (it2 != data.end()) 
+		// We don't have any way to tell how the author names might have
+		// been formatted.
+		return docstring();
 
-		docstring const opt = trim(data.substr(0, pos - 1));
-		if (opt.empty())
-			return docstring();
+	docstring author = getValueForKey(data, "author");
 
-		docstring authors;
-		split(opt, authors, '(');
-		return authors;
-	}
-
-	docstring author = parseBibTeX(data, "author");
-
 	if (author.empty())
-		author = parseBibTeX(data, "editor");
+		author = getValueForKey(data, "editor");
 
 	if (author.empty()) {
-		author = parseBibTeX(data, "key");
+		author = getValueForKey(data, "key");
 		if (author.empty())
 			// FIXME UNICODE
 			return from_utf8(key);
@@ -253,36 +238,23 @@
 }
 
 
-docstring const getYear(InfoMap const & map, string const & key)
+docstring const getYear(BibKeyList const & map, string const & key)
 {
 	BOOST_ASSERT(!map.empty());
 
-	InfoMap::const_iterator it = map.find(key);
+	BibKeyList::const_iterator it = map.find(key);
 	if (it == map.end())
 		return docstring();
-	docstring const & data = it->second;
+	KeyValMap const & data = it->second;
 
 	// Is the entry a BibTeX one or one from lyx-layout "bibliography"?
-	docstring::size_type const pos = data.find(TheBibliographyRef);
-	if (pos != docstring::npos) {
-		if (pos <= 2) {
-			return docstring();
-		}
+	KeyValMap::const_iterator it2 = data.find(TheBibliographyRef);
+	if (it2 != data.end()) 
+		// We don't have any way to tell how the entry might have
+		// been formatted.
+		return docstring();
 
-		docstring const opt =
-			trim(data.substr(0, pos - 1));
-		if (opt.empty())
-			return docstring();
-
-		docstring authors;
-		docstring const tmp = split(opt, authors, '(');
-		docstring year;
-		split(tmp, year, ')');
-		return year;
-
-	}
-
-	docstring year = parseBibTeX(data, "year");
+	docstring year = getValueForKey(data, "year");
 	if (year.empty())
 		year = _("No year");
 
@@ -304,11 +276,11 @@
 } // namespace anon
 
 
-vector<string> const getKeys(InfoMap const & map)
+vector<string> const getKeys(BibKeyList const & map)
 {
 	vector<string> bibkeys;
-	InfoMap::const_iterator it  = map.begin();
-	InfoMap::const_iterator end = map.end();
+	BibKeyList::const_iterator it  = map.begin();
+	BibKeyList::const_iterator end = map.end();
 	for (; it != end; ++it) {
 		bibkeys.push_back(it->first);
 	}
@@ -318,72 +290,69 @@
 }
 
 
-docstring const getInfo(InfoMap const & map, string const & key)
+docstring const getInfo(BibKeyList const & map, string const & key)
 {
 	BOOST_ASSERT(!map.empty());
 
-	InfoMap::const_iterator it = map.find(key);
+	BibKeyList::const_iterator it = map.find(key);
 	if (it == map.end())
 		return docstring();
-	docstring const & data = it->second;
+	KeyValMap const & data = it->second;
 
-	// is the entry a BibTeX one or one from lyx-layout "bibliography"?
-	docstring::size_type const pos = data.find(TheBibliographyRef);
-	if (pos != docstring::npos) {
-		docstring::size_type const pos2 = pos + TheBibliographyRef.size();
-		docstring const info = trim(data.substr(pos2));
-		return info;
+	// Is the entry a BibTeX one or one from lyx-layout "bibliography"?
+	KeyValMap::const_iterator it2 = data.find(TheBibliographyRef);
+	if (it2 != data.end()) {
+		KeyValMap::const_iterator it3 = data.find(from_ascii("ref"));
+		return it3->second;
 	}
 
-	// Search for all possible "required" keys
-	docstring author = parseBibTeX(data, "author");
+	//FIXME FIXME FIXME
+	//This could be made alot better using the biblio::TheEntryType
+	//field to customize the output based upon entry type.
+	
+	//Search for all possible "required" fields
+	docstring author = getValueForKey(data, "author");
 	if (author.empty())
-		author = parseBibTeX(data, "editor");
+		author = getValueForKey(data, "editor");
 
-	docstring year      = parseBibTeX(data, "year");
-	docstring title     = parseBibTeX(data, "title");
-	docstring booktitle = parseBibTeX(data, "booktitle");
-	docstring chapter   = parseBibTeX(data, "chapter");
-	docstring number    = parseBibTeX(data, "number");
-	docstring volume    = parseBibTeX(data, "volume");
-	docstring pages     = parseBibTeX(data, "pages");
-	docstring annote    = parseBibTeX(data, "annote");
-	docstring media     = parseBibTeX(data, "journal");
-	if (media.empty())
-		media = parseBibTeX(data, "publisher");
-	if (media.empty())
-		media = parseBibTeX(data, "school");
-	if (media.empty())
-		media = parseBibTeX(data, "institution");
+	docstring year      = getValueForKey(data, "year");
+	docstring title     = getValueForKey(data, "title");
+	docstring docLoc    = getValueForKey(data, "pages");
+	if (docLoc.empty()) {
+		docLoc = getValueForKey(data, "chapter");
+		if (!docLoc.empty())
+			docLoc = from_ascii("Ch. ") + docLoc;
+	}	else 
+		docLoc = from_ascii("pp. ") + docLoc;
+	docstring media     = getValueForKey(data, "journal");
+	if (media.empty()) {
+		media = getValueForKey(data, "publisher");
+		if (media.empty()) {
+			media = getValueForKey(data, "school");
+			if (media.empty())
+				media = getValueForKey(data, "institution");
+		}
+	}
+	docstring volume = getValueForKey(data, "volume");
 
 	odocstringstream result;
 	if (!author.empty())
 		result << author << ", ";
 	if (!title.empty())
 		result << title;
-	if (!booktitle.empty())
-		result << ", in " << booktitle;
-	if (!chapter.empty())
-		result << ", Ch. " << chapter;
 	if (!media.empty())
 		result << ", " << media;
-	if (!volume.empty())
-		result << ", vol. " << volume;
-	if (!number.empty())
-		result << ", no. " << number;
-	if (!pages.empty())
-		result << ", pp. " << pages;
 	if (!year.empty())
 		result << ", " << year;
-	if (!annote.empty())
-		result << "\n\n" << annote;
+	if (!docLoc.empty())
+		result << ", " << docLoc;
 
 	docstring const result_str = rtrim(result.str());
 	if (!result_str.empty())
 		return result_str;
 
 	// This should never happen (or at least be very unusual!)
-	return data;
+	return docstring();
 }
 
 
@@ -420,24 +389,28 @@
 public:
 	// re and icase are used to construct an instance of boost::RegEx.
 	// if icase is true, then matching is insensitive to case
-	RegexMatch(InfoMap const & m, string const & re, bool icase)
+	RegexMatch(BibKeyList const & m, string const & re, bool icase)
 		: map_(m), regex_(re, icase) {}
 
+	//FIXME This should probably be restored to its earlier behavior
 	bool operator()(string const & key) const {
-		// the data searched is the key + its associated BibTeX/biblio
-		// fields
-		string data = key;
-		InfoMap::const_iterator info = map_.find(key);
-		if (info != map_.end())
+		BibKeyList::const_iterator info = map_.find(key);
+ 		if (info == map_.end())
+ 			return false;
+ 
+ 		string data = key;
+		//The machinations here are required because map::operator[] 
+		//has no const version.
+		KeyValMap const kvm = info->second;
+		KeyValMap::const_iterator it = kvm.find(TheDataString);
+		if (it != kvm.end())
 			// FIXME UNICODE
-			data += ' ' + to_utf8(info->second);
-
-		// Attempts to find a match for the current RE
-		// somewhere in data.
+			data += ' ' + to_utf8(it->second);
+ 
 		return boost::regex_search(data, regex_);
 	}
 private:
-	InfoMap const map_;
+	BibKeyList const map_;
 	mutable boost::regex regex_;
 };
 
@@ -445,7 +418,7 @@
 
 
 vector<string>::const_iterator
-searchKeys(InfoMap const & theMap,
+searchKeys(BibKeyList const & theMap,
 	   vector<string> const & keys,
 	   string const & search_expr,
 	   vector<string>::const_iterator start,
@@ -492,142 +465,13 @@
 }
 
 
-docstring const parseBibTeX(docstring data, string const & findkey)
+docstring const getValueForKey(KeyValMap data, string const & findkey)
 {
-	// at first we delete all characters right of '%' and
-	// replace tabs through a space and remove leading spaces
-	// we read the data line by line so that the \n are
-	// ignored, too.
-	docstring data_;
-	int Entries = 0;
-	docstring dummy = token(data,'\n', Entries);
-	while (!dummy.empty()) {
-		// no tabs
-		dummy = subst(dummy, '\t', ' ');
-		// no leading spaces
-		dummy = ltrim(dummy);
-		// ignore lines with a beginning '%' or ignore all right of %
-		docstring::size_type const idx =
-			dummy.empty() ? docstring::npos : dummy.find('%');
-		if (idx != docstring::npos)
-			// Check if this is really a comment or just "\%"
-			if (idx == 0 || dummy[idx - 1] != '\\')
-				dummy.erase(idx, docstring::npos);
-			else
-				//  This is "\%", so just erase the '\'
-				dummy.erase(idx - 1, 1);
-		// do we have a new token or a new line of
-		// the same one? In the first case we ignore
-		// the \n and in the second we replace it
-		// with a space
-		if (!dummy.empty()) {
-			if (!contains(dummy, '='))
-				data_ += ' ' + dummy;
-			else
-				data_ += dummy;
-		}
-		dummy = token(data, '\n', ++Entries);
-	}
-
-	// replace double commas with "" for easy scanning
-	data = subst(data_, from_ascii(",,"), from_ascii("\"\""));
-
-	// unlikely!
-	if (data.empty())
+	docstring key = from_ascii(findkey);
+	KeyValMap::const_iterator it = data.find(key);
+	if (it == data.end())
 		return docstring();
-
-	// now get only the important line of the bibtex entry.
-	// all entries are devided by ',' except the last one.
-	data += ',';
-	// now we have same behaviour for all entries because the last one
-	// is "blah ... }"
-	Entries = 0;
-	bool found = false;
-	// parsing of title and booktitle is different from the
-	// others, because booktitle contains title
-	do {
-		dummy = token(data, ',', Entries++);
-		if (!dummy.empty()) {
-			found = contains(ascii_lowercase(dummy), from_ascii(findkey));
-			if (findkey == "title" &&
-			    contains(ascii_lowercase(dummy), from_ascii("booktitle")))
-				found = false;
-		}
-	} while (!found && !dummy.empty());
-	if (dummy.empty())
-		// no such keyword
-		return docstring();
-
-	// we are not sure, if we get all, because "key= "blah, blah" is
-	// allowed.
-	// Therefore we read all until the next "=" character, which follows a
-	// new keyword
-	docstring keyvalue = dummy;
-	dummy = token(data, ',', Entries++);
-	while (!contains(dummy, '=') && !dummy.empty()) {
-		keyvalue += ',' + dummy;
-		dummy = token(data, ',', Entries++);
-	}
-
-	// replace double "" with originals ,, (two commas)
-	// leaving us with the all-important line
-	data = subst(keyvalue, from_ascii("\"\""), from_ascii(",,"));
-
-	// Clean-up.
-	// 1. Spaces
-	data = rtrim(data);
-	// 2. if there is no opening '{' then a closing '{' is probably cruft.
-	if (!contains(data, '{'))
-		data = rtrim(data, "}");
-	// happens, when last keyword
-	docstring::size_type const idx =
-		!data.empty() ? data.find('=') : docstring::npos;
-
-	if (idx == docstring::npos)
-		return docstring();
-
-	data = trim(data.substr(idx));
-
-	// a valid entry?
-	if (data.length() < 2 || data[0] != '=')
-		return docstring();
-	else {
-		// delete '=' and the following spaces
-		data = ltrim(data, " =");
-		if (data.length() < 2) {
-			// not long enough to find delimiters
-			return data;
-		} else {
-			docstring::size_type keypos = 1;
-			char_type enclosing;
-			if (data[0] == '{') {
-				enclosing = '}';
-			} else if (data[0] == '"') {
-				enclosing = '"';
-			} else {
-				// no {} and no "", pure data but with a
-				// possible ',' at the end
-				return rtrim(data, ",");
-			}
-			docstring tmp = data.substr(keypos);
-			while (tmp.find('{') != docstring::npos &&
-			       tmp.find('}') != docstring::npos &&
-			       tmp.find('{') < tmp.find('}') &&
-			       tmp.find('{') < tmp.find(enclosing)) {
-
-				keypos += tmp.find('{') + 1;
-				tmp = data.substr(keypos);
-				keypos += tmp.find('}') + 1;
-				tmp = data.substr(keypos);
-			}
-			if (tmp.find(enclosing) == docstring::npos)
-				return data;
-			else {
-				keypos += tmp.find(enclosing);
-				return data.substr(1, keypos - 1);
-			}
-		}
-	}
+	return data[key];
 }
 
 
@@ -745,7 +589,7 @@
 
 vector<docstring> const
 getNumericalStrings(string const & key,
-		    InfoMap const & map, vector<CiteStyle> const & styles)
+		    BibKeyList const & map, vector<CiteStyle> const & styles)
 {
 	if (map.empty())
 		return vector<docstring>();
@@ -799,7 +643,7 @@
 
 vector<docstring> const
 getAuthorYearStrings(string const & key,
-		    InfoMap const & map, vector<CiteStyle> const & styles)
+		    BibKeyList const & map, vector<CiteStyle> const & styles)
 {
 	if (map.empty())
 		return vector<docstring>();
Index: src/frontends/controllers/ControlCitation.h
===================================================================
--- src/frontends/controllers/ControlCitation.h	(revision 19264)
+++ src/frontends/controllers/ControlCitation.h	(working copy)
@@ -63,7 +63,7 @@
 	}
 private:
 	/// The info associated with each key
-	biblio::InfoMap bibkeysInfo_;
+	biblio::BibKeyList bibkeysInfo_;
 
 	///
 	static std::vector<biblio::CiteStyle> citeStyles_;
Index: src/frontends/controllers/ControlCitation.cpp
===================================================================
--- src/frontends/controllers/ControlCitation.cpp	(revision 19264)
+++ src/frontends/controllers/ControlCitation.cpp	(working copy)
@@ -12,6 +12,7 @@
 #include <config.h>
 
 #include "ControlCitation.h"
+#include "frontend_helpers.h"
 
 #include "Buffer.h"
 #include "BufferParams.h"
@@ -48,12 +49,8 @@
 
 	bool use_styles = engine != biblio::ENGINE_BASIC;
 
-	vector<pair<string, docstring> > blist;
-	kernel().buffer().fillWithBibKeys(blist);
-	bibkeysInfo_.clear();
-	for (size_t i = 0; i < blist.size(); ++i)
-		bibkeysInfo_[blist[i].first] = blist[i].second;
-
+	kernel().buffer().fillWithBibKeys(bibkeysInfo_);
+	
 	if (citeStyles_.empty())
 		citeStyles_ = biblio::getCiteStyles(engine);
 	else {
@@ -137,23 +134,21 @@
 		// it is treated as a simple string by boost::regex.
 		expr = escape_special_chars(expr);
 
-	boost::regex reg_exp(to_utf8(expr), case_sensitive?
+	boost::regex reg_exp(to_utf8(expr), case_sensitive ?
 		boost::regex_constants::normal : boost::regex_constants::icase);
 
 	vector<string>::const_iterator it = keys_to_search.begin();
 	vector<string>::const_iterator end = keys_to_search.end();
 	for (; it != end; ++it ) {
-		biblio::InfoMap::const_iterator info = bibkeysInfo_.find(*it);
+		biblio::BibKeyList::iterator info = bibkeysInfo_.find(*it);
 		if (info == bibkeysInfo_.end())
 			continue;
 
 		string data = *it;
 		// FIXME UNICODE
-		data += ' ' + to_utf8(info->second);
+		data += ' ' + to_utf8((info->second)[biblio::TheDataString]);
 
 		try {
-			// Attempts to find a match for the current RE
-			// somewhere in data.
 			if (boost::regex_search(data, reg_exp))
 				foundKeys.push_back(*it);
 		}
Index: src/insets/InsetBibtex.h
===================================================================
--- src/insets/InsetBibtex.h	(revision 19264)
+++ src/insets/InsetBibtex.h	(working copy)
@@ -13,8 +13,9 @@
 #define INSET_BIBTEX_H
 
 
-#include <vector>
+#include <map>
 #include "InsetCommand.h"
+#include "frontends/controllers/frontend_helpers.h"
 
 #include "support/FileName.h"
 
@@ -38,8 +39,7 @@
 	///
 	int latex(Buffer const &, odocstream &, OutputParams const &) const;
 	///
-	void fillWithBibKeys(Buffer const & buffer,
-		std::vector<std::pair<std::string, docstring> > & keys) const;
+	void fillWithBibKeys(Buffer const & buffer, biblio::BibKeyList & keys) const;
 	///
 	std::vector<support::FileName> const getFiles(Buffer const &) const;
 	///
Index: src/insets/InsetBibtex.cpp
===================================================================
--- src/insets/InsetBibtex.cpp	(revision 19264)
+++ src/insets/InsetBibtex.cpp	(working copy)
@@ -34,7 +34,6 @@
 
 #include <boost/tokenizer.hpp>
 
-
 namespace lyx {
 
 using support::absolutePath;
@@ -415,13 +414,13 @@
 		bool legalChar = true;
 		while (ifs && !isSpace(ch) && 
 			   delimChars.find(ch) == docstring::npos &&
-			   (legalChar = illegalChars.find(ch) == docstring::npos)
-			   ) {
-			if (chCase == makeLowerCase) {
+			   (legalChar = (illegalChars.find(ch) == docstring::npos))
+			   ) 
+		{
+			if (chCase == makeLowerCase)
 				val += lowercase(ch);
-			} else {
+			else
 				val += ch;
-			}
 			ifs.get(ch);
 		}
 		
@@ -478,19 +477,41 @@
 					return false;
 
 			} else if (ch == '"' || ch == '{') {
+				// set end delimiter
+				char_type delim = ch == '"' ? '"': '}';
 
-				// read delimited text - set end delimiter
-				char_type delim = ch == '"'? '"': '}';
-
+				//Skip whitespace
+				do {
+					ifs.get(ch);
+				} while (ifs && isSpace(ch));
+				
+				if (!ifs)
+					return false;
+				
+				//We now have the first non-whitespace character
+				//We'll collapse adjacent whitespace.
+				bool lastWasWhiteSpace = false;
+				
 				// inside this delimited text braces must match.
 				// Thus we can have a closing delimiter only
 				// when nestLevel == 0
 				int nestLevel = 0;
 
-				ifs.get(ch);
 				while (ifs && (nestLevel > 0 || ch != delim)) {
+					if (isSpace(ch)) {
+						lastWasWhiteSpace = true;
+						ifs.get(ch);
+						continue;
+					} 
+					//We output the space only after we stop getting 
+					//whitespace so as not to output any whitespace
+					//at the end of the value.
+					if (lastWasWhiteSpace) {
+						lastWasWhiteSpace = false;
+						val += ' ';
+					}
+					
 					val += ch;
-
 					// update nesting level
 					switch (ch) {
 						case '{':
@@ -503,7 +524,7 @@
 					}
 
 					ifs.get(ch);
-				}
+				} //end while loop
 
 				if (!ifs)
 					return false;
@@ -554,9 +575,9 @@
 }
 
 
-// This method returns a comma separated list of Bibtex entries
+// This method returns a map of Bibtex entries
 void InsetBibtex::fillWithBibKeys(Buffer const & buffer,
-		std::vector<std::pair<string, docstring> > & keys) const
+		biblio::BibKeyList & keys) const
 {
 	vector<FileName> const files = getFiles(buffer);
 	for (vector<FileName>::const_iterator it = files.begin();
@@ -571,15 +592,6 @@
 		//   field values.
 		// - it accepts more characters in keys or value names than
 		//   bibtex does.
-		//
-		// TODOS:
-		// - the entries are split into name = value pairs by the
-		//   parser. These have to be merged again because of the
-		//   way lyx treats the entries ( pair<...>(...) ). The citation
-		//   mechanism in lyx should be changed such that it can use
-		//   the split entries.
-		// - messages on parsing errors can be generated.
-		//
 
 		// Officially bibtex does only support ASCII, but in practice
 		// you can use the encoding of the main document as long as
@@ -588,6 +600,7 @@
 		// We don't restrict keys to ASCII in LyX, since our own
 		// InsetBibitem can generate non-ASCII keys, and nonstandard
 		// 8bit clean bibtex forks exist.
+		
 		idocfstream ifs(it->toFilesystemEncoding().c_str(),
 				std::ios_base::in,
 				buffer.params().encoding().iconvName());
@@ -658,24 +671,29 @@
 					continue;
 
 			} else {
-
-				// Citation entry. Read the key and all name = value pairs
+				// Citation entry. Try to read the key.
 				docstring key;
-				docstring fields;
-				docstring name;
-				docstring value;
-				docstring commaNewline;
 
 				if (!readTypeOrKey(key, ifs, from_ascii(","), 
 				                   from_ascii("}"), keepCase) || !ifs)
 					continue;
 
-				// now we have a key, so we will add an entry
+				/////////////////////////////////////////////
+				// now we have a key, so we will add an entry 
 				// (even if it's empty, as bibtex does)
 				//
+				// we now read the field = value pairs.
 				// all items must be separated by a comma. If
 				// it is missing the scanning of this entry is
 				// stopped and the next is searched.
+				docstring fields;
+				docstring name;
+				docstring value;
+				docstring commaNewline;
+				docstring data;
+				biblio::KeyValMap keyvalmap;
+				keyvalmap[biblio::TheEntryType] = entryType;
+				
 				bool readNext = removeWSAndComma(ifs);
 
 				while (ifs && readNext) {
@@ -698,23 +716,15 @@
 					if (!readValue(value, ifs, strings))
 						break;
 
-					// append field to the total entry string.
-					//
-					// TODO: Here is where the fields can be put in
-					//       a more intelligent structure that preserves
-					//	     the already known parts.
-					fields += commaNewline;
-					fields += name + from_ascii(" = {") + value + '}';
-
-					if (!commaNewline.length())
-						commaNewline = from_ascii(",\n");
-
+					keyvalmap[name] = value;
+					data += "\n\n" + value;
+					
 					readNext = removeWSAndComma(ifs);
 				}
 
 				// add the new entry
-				keys.push_back(pair<string, docstring>(
-				to_utf8(key), fields));
+				keyvalmap[biblio::TheDataString] = data;
+				keys[to_utf8(key)] = keyvalmap;
 			}
 
 		} //< searching '@'
Index: src/insets/InsetCitation.cpp
===================================================================
--- src/insets/InsetCitation.cpp	(revision 19264)
+++ src/insets/InsetCitation.cpp	(working copy)
@@ -65,13 +65,13 @@
 		return docstring();
 
 	// Cache the labels
-	typedef std::map<Buffer const *, biblio::InfoMap> CachedMap;
+	typedef std::map<Buffer const *, biblio::BibKeyList> CachedMap;
 	static CachedMap cached_keys;
 
 	// and cache the timestamp of the bibliography files.
 	static std::map<FileName, time_t> bibfileStatus;
 
-	biblio::InfoMap infomap;
+	biblio::BibKeyList infomap;
 
 	vector<FileName> const & bibfilesCache = buffer.getBibfilesCache();
 	// compare the cached timestamps with the actual ones.
@@ -97,16 +97,7 @@
 
 	// build the keylist only if the bibfiles have been changed
 	if (cached_keys[&buffer].empty() || bibfileStatus.empty() || changed) {
-		typedef vector<std::pair<string, docstring> > 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;
-
+		buffer.fillWithBibKeys(infomap);
 		cached_keys[&buffer] = infomap;
 	} else
 		// use the cached keys
Index: src/insets/InsetInclude.h
===================================================================
--- src/insets/InsetInclude.h	(revision 19264)
+++ src/insets/InsetInclude.h	(working copy)
@@ -57,10 +57,11 @@
 			  std::vector<docstring> & list) const;
 	/** Fills \c keys
 	 *  \param buffer the Buffer containing this inset.
-	 *  \param keys the list of bibkeys in the child buffer.
-	 */
+	 *  \param keys the map of bibkeys in the child buffer.
+	 */	
+
 	void fillWithBibKeys(Buffer const & buffer,
-		std::vector<std::pair<std::string, docstring> > & keys) const;
+		std::map<std::string, std::map<docstring, docstring> > & keys) const;
 	/** Update the cache with all bibfiles in use of the child buffer
 	 *  (including bibfiles of grandchild documents).
 	 *  Does nothing if the child document is not loaded to prevent
Index: src/insets/InsetInclude.cpp
===================================================================
--- src/insets/InsetInclude.cpp	(revision 19264)
+++ src/insets/InsetInclude.cpp	(working copy)
@@ -736,7 +736,7 @@
 
 
 void InsetInclude::fillWithBibKeys(Buffer const & buffer,
-		std::vector<std::pair<string, docstring> > & keys) const
+		std::map<std::string, std::map<docstring, docstring> > & keys) const
 {
 	if (loadIfNeeded(buffer, params_)) {
 		string const included_file = includedFilename(buffer, params_).absFilename();

Reply via email to