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>
20 #pragma implementation
25 #include "helper_funcs.h"
26 #include "support/lstrings.h"
27 #include "support/LAssert.h"
28 #include "support/LRegex.h"
39 // A functor for use with std::sort, leading to case insensitive sorting
40 struct compareNoCase: public std::binary_function<string, string, bool>
42 bool operator()(string const & s1, string const & s2) const {
43 return compare_no_case(s1, s2) < 0;
47 vector<string> const getKeys(InfoMap const & map)
49 vector<string> bibkeys;
51 for (InfoMap::const_iterator it = map.begin(); it != map.end(); ++it) {
52 bibkeys.push_back(it->first);
55 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
60 string const getInfo(InfoMap const & map, string const & key)
62 lyx::Assert(!map.empty());
66 InfoMap::const_iterator it = map.find(key);
67 if (it != map.end()) {
68 // Search for all possible "required" keys
69 string author = parseBibTeX(it->second, "author");
71 author = parseBibTeX(it->second, "editor");
73 string year = parseBibTeX(it->second, "year");
74 string title = parseBibTeX(it->second, "title");
75 string booktitle = parseBibTeX(it->second, "booktitle");
76 string chapter = parseBibTeX(it->second, "chapter");
77 string pages = parseBibTeX(it->second, "pages");
79 string media = parseBibTeX(it->second, "journal");
81 media = parseBibTeX(it->second, "publisher");
83 media = parseBibTeX(it->second, "school");
85 media = parseBibTeX(it->second, "institution");
89 result += ", " + year;
91 result += ", " + title;
92 if (!booktitle.empty())
93 result += ", in " + booktitle;
95 result += ", Ch. " + chapter;
97 result += ", " + media;
99 result += ", pp. " + pages;
101 if (result.empty()) // not a BibTeX record
109 vector<string>::const_iterator
110 searchKeys(InfoMap const & theMap,
111 vector<string> const & keys,
113 vector<string>::const_iterator start,
118 // Preliminary checks
119 if(start < keys.begin() || start >= keys.end())
122 string search_expr = frontStrip(strip(expr));
123 if (search_expr.empty())
127 return simpleSearch(theMap, keys, search_expr, start, dir,
130 return regexSearch(theMap, keys, search_expr, start, dir);
134 vector<string>::const_iterator
135 simpleSearch(InfoMap const & theMap,
136 vector<string> const & keys,
138 vector<string>::const_iterator start,
144 tmp = lowercase(tmp);
146 vector<string> searchwords = getVectorFromString(tmp, " ");
148 // Loop over all keys from start...
149 for (vector<string>::const_iterator it = start;
150 // End condition is direction-dependent.
151 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
152 // increment is direction-dependent.
153 (dir == FORWARD) ? (++it) : (--it)) {
156 biblio::InfoMap::const_iterator info = theMap.find(*it);
157 if (info != theMap.end())
158 data += " " + info->second;
160 data = lowercase(data);
164 // Loop over all search words...
165 for (vector<string>::const_iterator sit = searchwords.begin();
166 sit != searchwords.end(); ++sit) {
167 if (data.find(*sit) == string::npos) {
173 if (found) return it;
180 vector<string>::const_iterator
181 regexSearch(InfoMap const & theMap,
182 vector<string> const & keys,
184 vector<string>::const_iterator start,
189 for (vector<string>::const_iterator it = start;
190 // End condition is direction-dependent.
191 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
192 // increment is direction-dependent.
193 (dir == FORWARD) ? (++it) : (--it)) {
196 biblio::InfoMap::const_iterator info = theMap.find(*it);
197 if (info != theMap.end())
198 data += " " + info->second;
200 if (reg.exec(data).size() > 0)
207 string const parseBibTeX(string data, string const & findkey)
211 for (string::iterator it=data.begin(); it<data.end(); ++it) {
212 if ((*it) == '\n' || (*it) == '\t')
216 data = frontStrip(data);
217 while (!data.empty() && data[0] != '=' &&
218 (data.find(' ') != string::npos || data.find('=') != string::npos)) {
220 string::size_type keypos = min(data.find(' '), data.find('='));
221 string key = lowercase(data.substr(0, keypos));
223 data = data.substr(keypos, data.length()-1);
224 data = frontStrip(strip(data));
225 if (data.length() > 1 && data[0]=='=') {
226 data = frontStrip(data.substr(1, data.length()-1));
234 } else if (data[0]=='"') {
242 data.find(enclosing)!=string::npos &&
244 string tmp = data.substr(keypos,
246 while (tmp.find('{') != string::npos &&
247 tmp.find('}') != string::npos &&
248 tmp.find('{') < tmp.find('}') &&
249 tmp.find('{') < tmp.find(enclosing)) {
251 keypos += tmp.find('{')+1;
252 tmp = data.substr(keypos,
254 keypos += tmp.find('}')+1;
255 tmp = data.substr(keypos,
259 if (tmp.find(enclosing)==string::npos)
262 keypos += tmp.find(enclosing);
263 tmp = data.substr(keypos,
267 value = data.substr(1, keypos-1);
269 if (keypos+1<data.length()-1)
270 data = frontStrip(data.substr(keypos+1, data.length()-1));
274 } else if (!keypos &&
277 keypos = data.length()-1;
278 if (data.find(' ') != string::npos)
279 keypos = data.find(' ');
280 if (data.find(',') != string::npos &&
281 keypos > data.find(','))
282 keypos = data.find(',');
284 value = data.substr(0, keypos);
286 if (keypos+1<data.length()-1)
287 data = frontStrip(data.substr(keypos+1, data.length()-1));
294 if (findkey == key) {
299 data = frontStrip(frontStrip(data,','));
302 else return keyvalue;
308 } // namespace biblio