+string const familyName(string const & name)
+{
+ // Very simple parser
+ string fname = name;
+
+ string::size_type idx = fname.rfind(".");
+ if (idx != string::npos)
+ fname = frontStrip(fname.substr(idx+1));
+
+ return fname;
+}
+
+
+string const getAbbreviatedAuthor(InfoMap const & map, string const & key)
+{
+ lyx::Assert(!map.empty());
+
+ InfoMap::const_iterator it = map.find(key);
+
+ string author;
+ if (it != map.end()) {
+ author = parseBibTeX(it->second, "author");
+ if (author.empty())
+ author = parseBibTeX(it->second, "editor");
+
+ vector<string> authors = getVectorFromString(author, "and");
+
+ if (!authors.empty()) {
+ author.erase();
+
+ for (vector<string>::iterator it = authors.begin();
+ it != authors.end(); ++it) {
+ *it = familyName(strip(*it));
+ }
+
+ author = authors[0];
+ if (authors.size() == 2)
+ author += _(" and ") + authors[1];
+ else if (authors.size() > 2)
+ author += _(" et al.");
+ }
+ }
+
+ if (author.empty())
+ author = _("Caesar et al.");
+
+ return author;
+}
+
+
+string const getYear(InfoMap const & map, string const & key)
+{
+ lyx::Assert(!map.empty());
+
+ InfoMap::const_iterator it = map.find(key);
+
+ string year;
+
+ if (it != map.end())
+ year = parseBibTeX(it->second, "year");
+
+ if (year.empty())
+ year = "50BC";
+
+ return year;
+}
+
+} // namespace anon
+
+
+
+
+
+
+
+// A functor for use with std::sort, leading to case insensitive sorting
+struct compareNoCase: public std::binary_function<string, string, bool>
+{
+ bool operator()(string const & s1, string const & s2) const {
+ return compare_no_case(s1, s2) < 0;
+ }
+};
+
+vector<string> const getKeys(InfoMap const & map)
+{
+ vector<string> bibkeys;
+
+ for (InfoMap::const_iterator it = map.begin(); it != map.end(); ++it) {
+ bibkeys.push_back(it->first);
+ }
+
+ sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
+ return bibkeys;
+}
+
+
+string const getInfo(InfoMap const & map, string const & key)
+{
+ lyx::Assert(!map.empty());
+
+ InfoMap::const_iterator it = map.find(key);
+ if (it == map.end()) return string();
+
+ // Search for all possible "required" keys
+ string author = parseBibTeX(it->second, "author");
+ if (author.empty())
+ author = parseBibTeX(it->second, "editor");
+
+ string year = parseBibTeX(it->second, "year");
+ string title = parseBibTeX(it->second, "title");
+ string booktitle = parseBibTeX(it->second, "booktitle");
+ string chapter = parseBibTeX(it->second, "chapter");
+ string number = parseBibTeX(it->second, "number");
+ string volume = parseBibTeX(it->second, "volume");
+ string pages = parseBibTeX(it->second, "pages");
+
+ string media = parseBibTeX(it->second, "journal");
+ if (media.empty())
+ media = parseBibTeX(it->second, "publisher");
+ if (media.empty())
+ media = parseBibTeX(it->second, "school");
+ if (media.empty())
+ media = parseBibTeX(it->second, "institution");
+
+ ostringstream result;
+ 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 (result.str().empty()) // not a BibTeX record
+ result << it->second;
+
+ return result.str().c_str();
+}
+
+
+vector<string>::const_iterator
+searchKeys(InfoMap const & theMap,
+ vector<string> const & keys,
+ string const & expr,
+ vector<string>::const_iterator start,
+ Search type,
+ Direction dir,
+ bool caseSensitive)
+{
+ // Preliminary checks
+ if(start < keys.begin() || start >= keys.end())
+ return keys.end();
+
+ string search_expr = frontStrip(strip(expr));
+ if (search_expr.empty())
+ return keys.end();
+
+ if (type == SIMPLE)
+ return simpleSearch(theMap, keys, search_expr, start, dir,
+ caseSensitive);
+
+ return regexSearch(theMap, keys, search_expr, start, dir);
+}
+
+