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 for (InfoMap::const_iterator it = map.begin(); it != map.end(); ++it) {
58 bibkeys.push_back(it->first);
61 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
66 string const getInfo(InfoMap const & map, string const & key)
68 lyx::Assert(!map.empty());
72 InfoMap::const_iterator it = map.find(key);
73 if (it != map.end()) {
74 // Search for all possible "required" keys
75 string author = parseBibTeX(it->second, "author");
77 author = parseBibTeX(it->second, "editor");
79 string year = parseBibTeX(it->second, "year");
80 string title = parseBibTeX(it->second, "title");
81 string booktitle = parseBibTeX(it->second, "booktitle");
82 string chapter = parseBibTeX(it->second, "chapter");
83 string pages = parseBibTeX(it->second, "pages");
85 string media = parseBibTeX(it->second, "journal");
87 media = parseBibTeX(it->second, "publisher");
89 media = parseBibTeX(it->second, "school");
91 media = parseBibTeX(it->second, "institution");
95 result += ", " + year;
97 result += ", " + title;
98 if (!booktitle.empty())
99 result += ", in " + booktitle;
100 if (!chapter.empty())
101 result += ", Ch. " + chapter;
103 result += ", " + media;
105 result += ", pp. " + pages;
107 if (result.empty()) // not a BibTeX record
115 vector<string>::const_iterator
116 searchKeys(InfoMap const & theMap,
117 vector<string> const & keys,
119 vector<string>::const_iterator start,
124 // Preliminary checks
125 if(start < keys.begin() || start >= keys.end())
128 string search_expr = frontStrip(strip(expr));
129 if (search_expr.empty())
133 return simpleSearch(theMap, keys, search_expr, start, dir,
136 return regexSearch(theMap, keys, search_expr, start, dir);
140 vector<string>::const_iterator
141 simpleSearch(InfoMap const & theMap,
142 vector<string> const & keys,
144 vector<string>::const_iterator start,
150 tmp = lowercase(tmp);
152 vector<string> searchwords = getVectorFromString(tmp, " ");
154 // Loop over all keys from start...
155 for (vector<string>::const_iterator it = start;
156 // End condition is direction-dependent.
157 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
158 // increment is direction-dependent.
159 (dir == FORWARD) ? (++it) : (--it)) {
162 biblio::InfoMap::const_iterator info = theMap.find(*it);
163 if (info != theMap.end())
164 data += " " + info->second;
166 data = lowercase(data);
170 // Loop over all search words...
171 for (vector<string>::const_iterator sit = searchwords.begin();
172 sit != searchwords.end(); ++sit) {
173 if (data.find(*sit) == string::npos) {
179 if (found) return it;
186 vector<string>::const_iterator
187 regexSearch(InfoMap const & theMap,
188 vector<string> const & keys,
190 vector<string>::const_iterator start,
195 for (vector<string>::const_iterator it = start;
196 // End condition is direction-dependent.
197 (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
198 // increment is direction-dependent.
199 (dir == FORWARD) ? (++it) : (--it)) {
202 biblio::InfoMap::const_iterator info = theMap.find(*it);
203 if (info != theMap.end())
204 data += " " + info->second;
206 if (reg.exec(data).size() > 0)
213 string const parseBibTeX(string data, string const & findkey)
217 for (string::iterator it=data.begin(); it<data.end(); ++it) {
218 if ((*it) == '\n' || (*it) == '\t')
222 data = frontStrip(data);
223 while (!data.empty() && data[0] != '=' &&
224 (data.find(' ') != string::npos || data.find('=') != string::npos)) {
226 string::size_type keypos = min(data.find(' '), data.find('='));
227 string key = lowercase(data.substr(0, keypos));
229 data = data.substr(keypos, data.length()-1);
230 data = frontStrip(strip(data));
231 if (data.length() > 1 && data[0]=='=') {
232 data = frontStrip(data.substr(1, data.length()-1));
240 } else if (data[0]=='"') {
248 data.find(enclosing)!=string::npos &&
250 string tmp = data.substr(keypos,
252 while (tmp.find('{') != string::npos &&
253 tmp.find('}') != string::npos &&
254 tmp.find('{') < tmp.find('}') &&
255 tmp.find('{') < tmp.find(enclosing)) {
257 keypos += tmp.find('{')+1;
258 tmp = data.substr(keypos,
260 keypos += tmp.find('}')+1;
261 tmp = data.substr(keypos,
265 if (tmp.find(enclosing)==string::npos)
268 keypos += tmp.find(enclosing);
269 tmp = data.substr(keypos,
273 value = data.substr(1, keypos-1);
275 if (keypos+1<data.length()-1)
276 data = frontStrip(data.substr(keypos+1, data.length()-1));
280 } else if (!keypos &&
283 keypos = data.length()-1;
284 if (data.find(' ') != string::npos)
285 keypos = data.find(' ');
286 if (data.find(',') != string::npos &&
287 keypos > data.find(','))
288 keypos = data.find(',');
290 value = data.substr(0, keypos);
292 if (keypos+1<data.length()-1)
293 data = frontStrip(data.substr(keypos+1, data.length()-1));
300 if (findkey == key) {
305 data = frontStrip(frontStrip(data,','));
308 else return keyvalue;
314 } // namespace biblio