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,
152 tmp = lowercase(tmp);
154 vector<string> searchwords = getVectorFromString(tmp, " ");
156 // Loop over all keys from start...
157 for (vector<string>::const_iterator it = start;
158 // End condition is direction-dependent.
159 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
160 // increment is direction-dependent.
161 (dir == FORWARD) ? (++it) : (--it)) {
164 biblio::InfoMap::const_iterator info = theMap.find(*it);
165 if (info != theMap.end())
166 data += " " + info->second;
168 data = lowercase(data);
172 // Loop over all search words...
173 for (vector<string>::const_iterator sit = searchwords.begin();
174 sit != searchwords.end(); ++sit) {
175 if (data.find(*sit) == string::npos) {
181 if (found) return it;
188 vector<string>::const_iterator
189 regexSearch(InfoMap const & theMap,
190 vector<string> const & keys,
192 vector<string>::const_iterator start,
197 for (vector<string>::const_iterator it = start;
198 // End condition is direction-dependent.
199 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
200 // increment is direction-dependent.
201 (dir == FORWARD) ? (++it) : (--it)) {
204 biblio::InfoMap::const_iterator info = theMap.find(*it);
205 if (info != theMap.end())
206 data += " " + info->second;
208 if (reg.exec(data).size() > 0)
215 string const parseBibTeX(string data, string const & findkey)
219 for (string::iterator it=data.begin(); it<data.end(); ++it) {
220 if ((*it) == '\n' || (*it) == '\t')
224 data = frontStrip(data);
225 while (!data.empty() && data[0] != '=' &&
226 (data.find(' ') != string::npos || data.find('=') != string::npos)) {
228 string::size_type keypos = min(data.find(' '), data.find('='));
229 string key = lowercase(data.substr(0, keypos));
231 data = data.substr(keypos, data.length()-1);
232 data = frontStrip(strip(data));
233 if (data.length() > 1 && data[0]=='=') {
234 data = frontStrip(data.substr(1, data.length()-1));
242 } else if (data[0]=='"') {
250 data.find(enclosing)!=string::npos &&
252 string tmp = data.substr(keypos,
254 while (tmp.find('{') != string::npos &&
255 tmp.find('}') != string::npos &&
256 tmp.find('{') < tmp.find('}') &&
257 tmp.find('{') < tmp.find(enclosing)) {
259 keypos += tmp.find('{')+1;
260 tmp = data.substr(keypos,
262 keypos += tmp.find('}')+1;
263 tmp = data.substr(keypos,
267 if (tmp.find(enclosing)==string::npos)
270 keypos += tmp.find(enclosing);
271 tmp = data.substr(keypos,
275 value = data.substr(1, keypos-1);
277 if (keypos+1<data.length()-1)
278 data = frontStrip(data.substr(keypos+1, data.length()-1));
282 } else if (!keypos &&
285 keypos = data.length()-1;
286 if (data.find(' ') != string::npos)
287 keypos = data.find(' ');
288 if (data.find(',') != string::npos &&
289 keypos > data.find(','))
290 keypos = data.find(',');
292 value = data.substr(0, keypos);
294 if (keypos+1<data.length()-1)
295 data = frontStrip(data.substr(keypos+1, data.length()-1));
302 if (findkey == key) {
307 data = frontStrip(frontStrip(data,','));
310 else return keyvalue;
316 } // namespace biblio