2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 2000 The LyX Team.
9 * ======================================================
11 * \file ControlCitation.C
12 * \author Angus Leeming <a.leeming@ic.ac.uk>
18 #pragma implementation
23 #include "ControlCitation.h"
25 #include "ButtonController.h"
29 #include "support/lstrings.h"
30 #include "support/LRegex.h"
39 ControlCitation::ControlCitation(LyXView & lv, Dialogs & d)
40 : ControlCommand(lv, d, LFUN_CITATION_INSERT)
42 // These are permanent connections so we won't bother
43 // storing a copy because we won't be disconnecting.
44 d_.showCitation.connect(slot(this, &ControlCitation::showInset));
45 d_.createCitation.connect(slot(this, &ControlCitation::createInset));
49 void ControlCitation::hide()
52 ControlCommand::hide();
56 // A functor for use with std::sort, leading to case insensitive sorting
57 struct compareNoCase: public std::binary_function<string, string, bool>
59 bool operator()(string const & s1, string const & s2) const {
60 return compare_no_case(s1, s2) < 0;
65 vector<string> const ControlCitation::getBibkeys()
67 vector<string> bibkeys;
70 vector<pair<string,string> > blist = lv_.buffer()->getBibkeyList();
72 for (vector<pair<string,string> >::size_type i=0; i<blist.size(); ++i) {
73 bibkeys.push_back(blist[i].first);
74 bibkeysInfo_.insert(InfoMapValue(blist[i].first,
78 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
83 string const ControlCitation::getBibkeyInfo(string const & key)
87 if (bibkeysInfo_.empty()) getBibkeys();
89 InfoMap::const_iterator it = bibkeysInfo_.find(key);
90 if (it != bibkeysInfo_.end()) {
91 // Search for all possible "required" keys
92 string author = parseBibTeX((*it).second, "author");
94 author = parseBibTeX((*it).second, "editor");
96 string year = parseBibTeX((*it).second, "year");
97 string title = parseBibTeX((*it).second, "title");
98 string booktitle = parseBibTeX((*it).second, "booktitle");
99 string chapter = parseBibTeX((*it).second, "chapter");
100 string pages = parseBibTeX((*it).second, "pages");
102 string media = parseBibTeX((*it).second, "journal");
104 media = parseBibTeX((*it).second, "publisher");
106 media = parseBibTeX((*it).second, "school");
108 media = parseBibTeX((*it).second, "institution");
112 result += ", " + year;
114 result += ", " + title;
115 if (!booktitle.empty())
116 result += ", in " + booktitle;
117 if (!chapter.empty())
118 result += ", Ch. " + chapter;
120 result += ", " + media;
122 result += ", pp. " + pages;
129 string const getStringFromVector(vector<string> const & vec, char delim)
132 for (vector<string>::size_type i=0; i<vec.size(); ++i) {
133 if (i > 0) str += tostr(delim);
139 vector<string> const getVectorFromString(string const & str, char delim)
144 keys = frontStrip(split(keys, tmp, delim));
145 while (!tmp.empty()) {
147 keys = frontStrip(split(keys, tmp, delim));
152 vector<string>::const_iterator
153 searchKeys(ControlCitation const & controller,
154 vector<string> const & keys,
156 vector<string>::const_iterator start,
157 ControlCitation::Search type,
158 ControlCitation::Direction dir,
161 // Preliminary checks
162 if(start < keys.begin() || start >= keys.end())
165 string search_expr = frontStrip(strip(expr));
166 if (search_expr.empty())
169 if (type == ControlCitation::SIMPLE)
170 return simpleSearch(controller, keys, search_expr, start, dir,
173 return regexSearch(controller, keys, search_expr, start, dir);
177 vector<string>::const_iterator
178 simpleSearch(ControlCitation const & controller,
179 vector<string> const & keys,
181 vector<string>::const_iterator start,
182 ControlCitation::Direction dir,
185 vector<string> searchwords = getVectorFromString(expr, ' ');
187 // Loop over all keys from start...
188 for (vector<string>::const_iterator it = start;
189 // End condition is direction-dependent.
190 (dir == ControlCitation::FORWARD) ?
191 (it<keys.end()) : (it>=keys.begin());
192 // increment is direction-dependent.
193 (dir == ControlCitation::FORWARD) ?
197 ControlCitation::InfoMap::const_iterator info =
198 controller.bibkeysInfo().find(*it);
199 if (info != controller.bibkeysInfo().end())
200 data += " " + info->second;
202 data = lowercase(data);
206 // Loop over all search words...
208 for (vector<string>::const_iterator sit=
210 sit<searchwords.end(); ++sit) {
211 if (data.find(*sit) == string::npos) {
217 for (vector<string>::const_iterator sit=
219 sit<searchwords.end(); ++sit) {
220 if (data.find(lowercase(*sit)) ==
228 if (found) return it;
235 vector<string>::const_iterator
236 regexSearch(ControlCitation const & controller,
237 vector<string> const & keys,
239 vector<string>::const_iterator start,
240 ControlCitation::Direction dir)
244 for (vector<string>::const_iterator it = start;
245 // End condition is direction-dependent.
246 (dir == ControlCitation::FORWARD) ?
247 (it<keys.end()) : (it>=keys.begin());
248 // increment is direction-dependent.
249 (dir == ControlCitation::FORWARD) ?
253 ControlCitation::InfoMap::const_iterator info =
254 controller.bibkeysInfo().find(*it);
255 if (info != controller.bibkeysInfo().end())
256 data += " " + info->second;
258 if (reg.exec(data).size() > 0)
265 string const parseBibTeX(string data, string const & findkey)
269 for (string::iterator it=data.begin(); it<data.end(); ++it) {
270 if ((*it) == '\n' || (*it) == '\t')
274 data = frontStrip(data);
275 while (!data.empty() && data[0] != '=' &&
276 (data.find(' ') != string::npos || data.find('=') != string::npos)) {
278 string::size_type keypos = min(data.find(' '), data.find('='));
279 string key = lowercase(data.substr(0, keypos));
281 data = data.substr(keypos, data.length()-1);
282 data = frontStrip(strip(data));
283 if (data.length() > 1 && data[0]=='=') {
284 data = frontStrip(data.substr(1, data.length()-1));
292 } else if (data[0]=='"') {
300 data.find(enclosing)!=string::npos &&
302 string tmp = data.substr(keypos,
304 while (tmp.find('{') != string::npos &&
305 tmp.find('}') != string::npos &&
306 tmp.find('{') < tmp.find('}') &&
307 tmp.find('{') < tmp.find(enclosing)) {
309 keypos += tmp.find('{')+1;
310 tmp = data.substr(keypos,
312 keypos += tmp.find('}')+1;
313 tmp = data.substr(keypos,
317 if (tmp.find(enclosing)==string::npos)
320 keypos += tmp.find(enclosing);
321 tmp = data.substr(keypos,
325 value = data.substr(1, keypos-1);
327 if (keypos+1<data.length()-1)
328 data = frontStrip(data.substr(keypos+1, data.length()-1));
332 } else if (!keypos &&
335 keypos = data.length()-1;
336 if (data.find(' ') != string::npos)
337 keypos = data.find(' ');
338 if (data.find(',') != string::npos &&
339 keypos > data.find(','))
340 keypos = data.find(',');
342 value = data.substr(0, keypos);
344 if (keypos+1<data.length()-1)
345 data = frontStrip(data.substr(keypos+1, data.length()-1));
352 if (findkey == key) {
357 data = frontStrip(frontStrip(data,','));
360 else return keyvalue;