1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 2001 The LyX Team.
8 * ======================================================
11 * \author Angus Leeming <a.leeming@ic.ac.uk>
18 #pragma implementation
30 #include "helper_funcs.h"
31 #include "support/lstrings.h"
32 #include "support/LAssert.h"
33 #include "support/LRegex.h"
45 // A functor for use with std::sort, leading to case insensitive sorting
46 struct compareNoCase: public std::binary_function<string, string, bool>
48 bool operator()(string const & s1, string const & s2) const {
49 return compare_no_case(s1, s2) < 0;
53 vector<string> const getKeys(InfoMap const & map)
55 vector<string> bibkeys;
57 typedef std::map<string, string>::value_type InfoMapValue;
59 for (InfoMap::const_iterator it = map.begin(); it != map.end(); ++it) {
60 bibkeys.push_back(it->first);
63 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
68 string const getInfo(InfoMap const & map, string const & key)
74 InfoMap::const_iterator it = map.find(key);
75 if (it != map.end()) {
76 // Search for all possible "required" keys
77 string author = parseBibTeX(it->second, "author");
79 author = parseBibTeX(it->second, "editor");
81 string year = parseBibTeX(it->second, "year");
82 string title = parseBibTeX(it->second, "title");
83 string booktitle = parseBibTeX(it->second, "booktitle");
84 string chapter = parseBibTeX(it->second, "chapter");
85 string pages = parseBibTeX(it->second, "pages");
87 string media = parseBibTeX(it->second, "journal");
89 media = parseBibTeX(it->second, "publisher");
91 media = parseBibTeX(it->second, "school");
93 media = parseBibTeX(it->second, "institution");
97 result += ", " + year;
99 result += ", " + title;
100 if (!booktitle.empty())
101 result += ", in " + booktitle;
102 if (!chapter.empty())
103 result += ", Ch. " + chapter;
105 result += ", " + media;
107 result += ", pp. " + pages;
109 if (result.empty()) // not a BibTeX record
117 vector<string>::const_iterator
118 searchKeys(InfoMap const & theMap,
119 vector<string> const & keys,
121 vector<string>::const_iterator start,
126 // Preliminary checks
127 if(start < keys.begin() || start >= keys.end())
130 string search_expr = frontStrip(strip(expr));
131 if (search_expr.empty())
135 return simpleSearch(theMap, keys, search_expr, start, dir,
138 return regexSearch(theMap, keys, search_expr, start, dir);
142 vector<string>::const_iterator
143 simpleSearch(InfoMap const & theMap,
144 vector<string> const & keys,
146 vector<string>::const_iterator start,
150 vector<string> searchwords = getVectorFromString(expr, " ");
152 // Loop over all keys from start...
153 for (vector<string>::const_iterator it = start;
154 // End condition is direction-dependent.
155 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
156 // increment is direction-dependent.
157 (dir == FORWARD) ? (++it) : (--it)) {
160 biblio::InfoMap::const_iterator info = theMap.find(*it);
161 if (info != theMap.end())
162 data += " " + info->second;
164 data = lowercase(data);
168 // Loop over all search words...
170 for (vector<string>::const_iterator sit=
172 sit<searchwords.end(); ++sit) {
173 if (data.find(*sit) == string::npos) {
179 for (vector<string>::const_iterator sit=
181 sit<searchwords.end(); ++sit) {
182 if (data.find(lowercase(*sit)) ==
190 if (found) return it;
197 vector<string>::const_iterator
198 regexSearch(InfoMap const & theMap,
199 vector<string> const & keys,
201 vector<string>::const_iterator start,
206 for (vector<string>::const_iterator it = start;
207 // End condition is direction-dependent.
208 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
209 // increment is direction-dependent.
210 (dir == FORWARD) ? (++it) : (--it)) {
213 biblio::InfoMap::const_iterator info = theMap.find(*it);
214 if (info != theMap.end())
215 data += " " + info->second;
217 if (reg.exec(data).size() > 0)
224 string const parseBibTeX(string data, string const & findkey)
228 for (string::iterator it=data.begin(); it<data.end(); ++it) {
229 if ((*it) == '\n' || (*it) == '\t')
233 data = frontStrip(data);
234 while (!data.empty() && data[0] != '=' &&
235 (data.find(' ') != string::npos || data.find('=') != string::npos)) {
237 string::size_type keypos = min(data.find(' '), data.find('='));
238 string key = lowercase(data.substr(0, keypos));
240 data = data.substr(keypos, data.length()-1);
241 data = frontStrip(strip(data));
242 if (data.length() > 1 && data[0]=='=') {
243 data = frontStrip(data.substr(1, data.length()-1));
251 } else if (data[0]=='"') {
259 data.find(enclosing)!=string::npos &&
261 string tmp = data.substr(keypos,
263 while (tmp.find('{') != string::npos &&
264 tmp.find('}') != string::npos &&
265 tmp.find('{') < tmp.find('}') &&
266 tmp.find('{') < tmp.find(enclosing)) {
268 keypos += tmp.find('{')+1;
269 tmp = data.substr(keypos,
271 keypos += tmp.find('}')+1;
272 tmp = data.substr(keypos,
276 if (tmp.find(enclosing)==string::npos)
279 keypos += tmp.find(enclosing);
280 tmp = data.substr(keypos,
284 value = data.substr(1, keypos-1);
286 if (keypos+1<data.length()-1)
287 data = frontStrip(data.substr(keypos+1, data.length()-1));
291 } else if (!keypos &&
294 keypos = data.length()-1;
295 if (data.find(' ') != string::npos)
296 keypos = data.find(' ');
297 if (data.find(',') != string::npos &&
298 keypos > data.find(','))
299 keypos = data.find(',');
301 value = data.substr(0, keypos);
303 if (keypos+1<data.length()-1)
304 data = frontStrip(data.substr(keypos+1, data.length()-1));
311 if (findkey == key) {
316 data = frontStrip(frontStrip(data,','));
319 else return keyvalue;
325 } // namespace biblio