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;
58 typedef std::map<string, string>::value_type InfoMapValue;
60 for (InfoMap::const_iterator it = map.begin(); it != map.end(); ++it) {
61 bibkeys.push_back(it->first);
64 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
69 string const getInfo(InfoMap const & map, string const & key)
75 InfoMap::const_iterator it = map.find(key);
76 if (it != map.end()) {
77 // Search for all possible "required" keys
78 string author = parseBibTeX(it->second, "author");
80 author = parseBibTeX(it->second, "editor");
82 string year = parseBibTeX(it->second, "year");
83 string title = parseBibTeX(it->second, "title");
84 string booktitle = parseBibTeX(it->second, "booktitle");
85 string chapter = parseBibTeX(it->second, "chapter");
86 string pages = parseBibTeX(it->second, "pages");
88 string media = parseBibTeX(it->second, "journal");
90 media = parseBibTeX(it->second, "publisher");
92 media = parseBibTeX(it->second, "school");
94 media = parseBibTeX(it->second, "institution");
98 result += ", " + year;
100 result += ", " + title;
101 if (!booktitle.empty())
102 result += ", in " + booktitle;
103 if (!chapter.empty())
104 result += ", Ch. " + chapter;
106 result += ", " + media;
108 result += ", pp. " + pages;
110 if (result.empty()) // not a BibTeX record
118 vector<string>::const_iterator
119 searchKeys(InfoMap const & theMap,
120 vector<string> const & keys,
122 vector<string>::const_iterator start,
127 // Preliminary checks
128 if(start < keys.begin() || start >= keys.end())
131 string search_expr = frontStrip(strip(expr));
132 if (search_expr.empty())
136 return simpleSearch(theMap, keys, search_expr, start, dir,
139 return regexSearch(theMap, keys, search_expr, start, dir);
143 vector<string>::const_iterator
144 simpleSearch(InfoMap const & theMap,
145 vector<string> const & keys,
147 vector<string>::const_iterator start,
151 vector<string> searchwords = getVectorFromString(expr, " ");
153 // Loop over all keys from start...
154 for (vector<string>::const_iterator it = start;
155 // End condition is direction-dependent.
156 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
157 // increment is direction-dependent.
158 (dir == FORWARD) ? (++it) : (--it)) {
161 biblio::InfoMap::const_iterator info = theMap.find(*it);
162 if (info != theMap.end())
163 data += " " + info->second;
165 data = lowercase(data);
169 // Loop over all search words...
171 for (vector<string>::const_iterator sit=
173 sit<searchwords.end(); ++sit) {
174 if (data.find(*sit) == string::npos) {
180 for (vector<string>::const_iterator sit=
182 sit<searchwords.end(); ++sit) {
183 if (data.find(lowercase(*sit)) ==
191 if (found) return it;
198 vector<string>::const_iterator
199 regexSearch(InfoMap const & theMap,
200 vector<string> const & keys,
202 vector<string>::const_iterator start,
207 for (vector<string>::const_iterator it = start;
208 // End condition is direction-dependent.
209 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
210 // increment is direction-dependent.
211 (dir == FORWARD) ? (++it) : (--it)) {
214 biblio::InfoMap::const_iterator info = theMap.find(*it);
215 if (info != theMap.end())
216 data += " " + info->second;
218 if (reg.exec(data).size() > 0)
225 string const parseBibTeX(string data, string const & findkey)
229 for (string::iterator it=data.begin(); it<data.end(); ++it) {
230 if ((*it) == '\n' || (*it) == '\t')
234 data = frontStrip(data);
235 while (!data.empty() && data[0] != '=' &&
236 (data.find(' ') != string::npos || data.find('=') != string::npos)) {
238 string::size_type keypos = min(data.find(' '), data.find('='));
239 string key = lowercase(data.substr(0, keypos));
241 data = data.substr(keypos, data.length()-1);
242 data = frontStrip(strip(data));
243 if (data.length() > 1 && data[0]=='=') {
244 data = frontStrip(data.substr(1, data.length()-1));
252 } else if (data[0]=='"') {
260 data.find(enclosing)!=string::npos &&
262 string tmp = data.substr(keypos,
264 while (tmp.find('{') != string::npos &&
265 tmp.find('}') != string::npos &&
266 tmp.find('{') < tmp.find('}') &&
267 tmp.find('{') < tmp.find(enclosing)) {
269 keypos += tmp.find('{')+1;
270 tmp = data.substr(keypos,
272 keypos += tmp.find('}')+1;
273 tmp = data.substr(keypos,
277 if (tmp.find(enclosing)==string::npos)
280 keypos += tmp.find(enclosing);
281 tmp = data.substr(keypos,
285 value = data.substr(1, keypos-1);
287 if (keypos+1<data.length()-1)
288 data = frontStrip(data.substr(keypos+1, data.length()-1));
292 } else if (!keypos &&
295 keypos = data.length()-1;
296 if (data.find(' ') != string::npos)
297 keypos = data.find(' ');
298 if (data.find(',') != string::npos &&
299 keypos > data.find(','))
300 keypos = data.find(',');
302 value = data.substr(0, keypos);
304 if (keypos+1<data.length()-1)
305 data = frontStrip(data.substr(keypos+1, data.length()-1));
312 if (findkey == key) {
317 data = frontStrip(frontStrip(data,','));
320 else return keyvalue;
326 } // namespace biblio