2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 2001 The LyX Team.
9 * ======================================================
12 * \author Angus Leeming <a.leeming@ic.ac.uk>
21 #pragma implementation
26 #include "helper_funcs.h"
27 #include "support/lstrings.h"
28 #include "support/LAssert.h"
29 #include "support/LRegex.h"
40 // A functor for use with std::sort, leading to case insensitive sorting
41 struct compareNoCase: public std::binary_function<string, string, bool>
43 bool operator()(string const & s1, string const & s2) const {
44 return compare_no_case(s1, s2) < 0;
48 vector<string> const getKeys(InfoMap const & map)
50 vector<string> bibkeys;
52 for (InfoMap::const_iterator it = map.begin(); it != map.end(); ++it) {
53 bibkeys.push_back(it->first);
56 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
61 string const getInfo(InfoMap const & map, string const & key)
63 lyx::Assert(!map.empty());
67 InfoMap::const_iterator it = map.find(key);
68 if (it != map.end()) {
69 // Search for all possible "required" keys
70 string author = parseBibTeX(it->second, "author");
72 author = parseBibTeX(it->second, "editor");
74 string year = parseBibTeX(it->second, "year");
75 string title = parseBibTeX(it->second, "title");
76 string booktitle = parseBibTeX(it->second, "booktitle");
77 string chapter = parseBibTeX(it->second, "chapter");
78 string pages = parseBibTeX(it->second, "pages");
80 string media = parseBibTeX(it->second, "journal");
82 media = parseBibTeX(it->second, "publisher");
84 media = parseBibTeX(it->second, "school");
86 media = parseBibTeX(it->second, "institution");
90 result += ", " + year;
92 result += ", " + title;
93 if (!booktitle.empty())
94 result += ", in " + booktitle;
96 result += ", Ch. " + chapter;
98 result += ", " + media;
100 result += ", pp. " + pages;
102 if (result.empty()) // not a BibTeX record
110 vector<string>::const_iterator
111 searchKeys(InfoMap const & theMap,
112 vector<string> const & keys,
114 vector<string>::const_iterator start,
119 // Preliminary checks
120 if(start < keys.begin() || start >= keys.end())
123 string search_expr = frontStrip(strip(expr));
124 if (search_expr.empty())
128 return simpleSearch(theMap, keys, search_expr, start, dir,
131 return regexSearch(theMap, keys, search_expr, start, dir);
135 vector<string>::const_iterator
136 simpleSearch(InfoMap const & theMap,
137 vector<string> const & keys,
139 vector<string>::const_iterator start,
145 tmp = lowercase(tmp);
147 vector<string> searchwords = getVectorFromString(tmp, " ");
149 // Loop over all keys from start...
150 for (vector<string>::const_iterator it = start;
151 // End condition is direction-dependent.
152 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
153 // increment is direction-dependent.
154 (dir == FORWARD) ? (++it) : (--it)) {
157 biblio::InfoMap::const_iterator info = theMap.find(*it);
158 if (info != theMap.end())
159 data += " " + info->second;
161 data = lowercase(data);
165 // Loop over all search words...
166 for (vector<string>::const_iterator sit = searchwords.begin();
167 sit != searchwords.end(); ++sit) {
168 if (data.find(*sit) == string::npos) {
174 if (found) return it;
181 vector<string>::const_iterator
182 regexSearch(InfoMap const & theMap,
183 vector<string> const & keys,
185 vector<string>::const_iterator start,
190 for (vector<string>::const_iterator it = start;
191 // End condition is direction-dependent.
192 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
193 // increment is direction-dependent.
194 (dir == FORWARD) ? (++it) : (--it)) {
197 biblio::InfoMap::const_iterator info = theMap.find(*it);
198 if (info != theMap.end())
199 data += " " + info->second;
201 if (reg.exec(data).size() > 0)
208 string const parseBibTeX(string data, string const & findkey)
212 for (string::iterator it=data.begin(); it<data.end(); ++it) {
213 if ((*it) == '\n' || (*it) == '\t')
217 data = frontStrip(data);
218 while (!data.empty() && data[0] != '=' &&
219 (data.find(' ') != string::npos || data.find('=') != string::npos)) {
221 string::size_type keypos = min(data.find(' '), data.find('='));
222 string key = lowercase(data.substr(0, keypos));
224 data = data.substr(keypos, data.length()-1);
225 data = frontStrip(strip(data));
226 if (data.length() > 1 && data[0]=='=') {
227 data = frontStrip(data.substr(1, data.length()-1));
235 } else if (data[0]=='"') {
243 data.find(enclosing)!=string::npos &&
245 string tmp = data.substr(keypos,
247 while (tmp.find('{') != string::npos &&
248 tmp.find('}') != string::npos &&
249 tmp.find('{') < tmp.find('}') &&
250 tmp.find('{') < tmp.find(enclosing)) {
252 keypos += tmp.find('{')+1;
253 tmp = data.substr(keypos,
255 keypos += tmp.find('}')+1;
256 tmp = data.substr(keypos,
260 if (tmp.find(enclosing)==string::npos)
263 keypos += tmp.find(enclosing);
264 tmp = data.substr(keypos,
268 value = data.substr(1, keypos-1);
270 if (keypos+1<data.length()-1)
271 data = frontStrip(data.substr(keypos+1, data.length()-1));
275 } else if (!keypos &&
278 keypos = data.length()-1;
279 if (data.find(' ') != string::npos)
280 keypos = data.find(' ');
281 if (data.find(',') != string::npos &&
282 keypos > data.find(','))
283 keypos = data.find(',');
285 value = data.substr(0, keypos);
287 if (keypos+1<data.length()-1)
288 data = frontStrip(data.substr(keypos+1, data.length()-1));
295 if (findkey == key) {
300 data = frontStrip(frontStrip(data,','));
303 else return keyvalue;
309 } // namespace biblio