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"
38 ControlCitation::ControlCitation(LyXView & lv, Dialogs & d)
39 : ControlCommand(lv, d, LFUN_CITATION_INSERT)
41 // These are permanent connections so we won't bother
42 // storing a copy because we won't be disconnecting.
43 d_.showCitation.connect(slot(this, &ControlCitation::showInset));
44 d_.createCitation.connect(slot(this, &ControlCitation::createInset));
48 void ControlCitation::hide()
51 ControlCommand::hide();
55 // A functor for use with std::sort, leading to case insensitive sorting
56 struct compareNoCase: public std::binary_function<string, string, bool>
58 bool operator()(string const & s1, string const & s2) const {
59 return compare_no_case(s1, s2) < 0;
64 vector<string> const ControlCitation::getBibkeys()
66 vector<string> bibkeys;
69 vector<pair<string,string> > blist = lv_.buffer()->getBibkeyList();
71 for (vector<pair<string,string> >::size_type i=0; i<blist.size(); ++i) {
72 bibkeys.push_back(blist[i].first);
73 bibkeysInfo_.insert(InfoMapValue(blist[i].first,
77 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
82 string const ControlCitation::getBibkeyInfo(string const & key)
86 if (bibkeysInfo_.empty()) getBibkeys();
88 InfoMap::const_iterator it = bibkeysInfo_.find(key);
89 if (it != bibkeysInfo_.end()) {
90 // Search for all possible "required" keys
91 string author = parseBibTeX((*it).second, "author");
93 author = parseBibTeX((*it).second, "editor");
95 string year = parseBibTeX((*it).second, "year");
96 string title = parseBibTeX((*it).second, "title");
97 string booktitle = parseBibTeX((*it).second, "booktitle");
98 string chapter = parseBibTeX((*it).second, "chapter");
99 string pages = parseBibTeX((*it).second, "pages");
101 string media = parseBibTeX((*it).second, "journal");
103 media = parseBibTeX((*it).second, "publisher");
105 media = parseBibTeX((*it).second, "school");
107 media = parseBibTeX((*it).second, "institution");
111 result += ", " + year;
113 result += ", " + title;
114 if (!booktitle.empty())
115 result += ", in " + booktitle;
116 if (!chapter.empty())
117 result += ", Ch. " + chapter;
119 result += ", " + media;
121 result += ", pp. " + pages;
128 vector<string>::const_iterator
129 searchKeys(ControlCitation const & controller,
130 vector<string> const & keys,
132 vector<string>::const_iterator start,
133 ControlCitation::Search type,
134 ControlCitation::Direction dir,
137 // Preliminary checks
138 if(start < keys.begin() || start >= keys.end())
141 string search_expr = frontStrip(strip(expr));
142 if (search_expr.empty())
145 if (type == ControlCitation::SIMPLE)
146 return simpleSearch(controller, keys, search_expr, start, dir,
149 return regexSearch(controller, keys, search_expr, start, dir);
153 vector<string>::const_iterator
154 simpleSearch(ControlCitation const & controller,
155 vector<string> const & keys,
157 vector<string>::const_iterator start,
158 ControlCitation::Direction dir,
161 vector<string> searchwords = getVectorFromString(expr, ' ');
163 // Loop over all keys from start...
164 for (vector<string>::const_iterator it = start;
165 // End condition is direction-dependent.
166 (dir == ControlCitation::FORWARD) ?
167 (it<keys.end()) : (it>=keys.begin());
168 // increment is direction-dependent.
169 (dir == ControlCitation::FORWARD) ?
173 ControlCitation::InfoMap::const_iterator info =
174 controller.bibkeysInfo().find(*it);
175 if (info != controller.bibkeysInfo().end())
176 data += " " + info->second;
178 data = lowercase(data);
182 // Loop over all search words...
184 for (vector<string>::const_iterator sit=
186 sit<searchwords.end(); ++sit) {
187 if (data.find(*sit) == string::npos) {
193 for (vector<string>::const_iterator sit=
195 sit<searchwords.end(); ++sit) {
196 if (data.find(lowercase(*sit)) ==
204 if (found) return it;
211 vector<string>::const_iterator
212 regexSearch(ControlCitation const & controller,
213 vector<string> const & keys,
215 vector<string>::const_iterator start,
216 ControlCitation::Direction dir)
220 for (vector<string>::const_iterator it = start;
221 // End condition is direction-dependent.
222 (dir == ControlCitation::FORWARD) ?
223 (it<keys.end()) : (it>=keys.begin());
224 // increment is direction-dependent.
225 (dir == ControlCitation::FORWARD) ?
229 ControlCitation::InfoMap::const_iterator info =
230 controller.bibkeysInfo().find(*it);
231 if (info != controller.bibkeysInfo().end())
232 data += " " + info->second;
234 if (reg.exec(data).size() > 0)
241 string const getStringFromVector(vector<string> const & vec, char delim)
244 for (vector<string>::size_type i=0; i<vec.size(); ++i) {
245 if (i > 0) str += tostr(delim) + " ";
251 vector<string> const getVectorFromString(string const & str, char delim)
256 keys = frontStrip(split(keys, tmp, delim));
257 while (!tmp.empty()) {
259 keys = frontStrip(split(keys, tmp, delim));
264 string const parseBibTeX(string data, string const & findkey)
268 for (string::iterator it=data.begin(); it<data.end(); ++it) {
269 if ((*it) == '\n' || (*it) == '\t')
273 data = frontStrip(data);
274 while (!data.empty() && data[0] != '=' &&
275 (data.find(' ') != string::npos || data.find('=') != string::npos)) {
277 string::size_type keypos = min(data.find(' '), data.find('='));
278 string key = lowercase(data.substr(0, keypos));
280 data = data.substr(keypos, data.length()-1);
281 data = frontStrip(strip(data));
282 if (data.length() > 1 && data[0]=='=') {
283 data = frontStrip(data.substr(1, data.length()-1));
291 } else if (data[0]=='"') {
299 data.find(enclosing)!=string::npos &&
301 string tmp = data.substr(keypos,
303 while (tmp.find('{') != string::npos &&
304 tmp.find('}') != string::npos &&
305 tmp.find('{') < tmp.find('}') &&
306 tmp.find('{') < tmp.find(enclosing)) {
308 keypos += tmp.find('{')+1;
309 tmp = data.substr(keypos,
311 keypos += tmp.find('}')+1;
312 tmp = data.substr(keypos,
316 if (tmp.find(enclosing)==string::npos)
319 keypos += tmp.find(enclosing);
320 tmp = data.substr(keypos,
324 value = data.substr(1, keypos-1);
326 if (keypos+1<data.length()-1)
327 data = frontStrip(data.substr(keypos+1, data.length()-1));
331 } else if (!keypos &&
334 keypos = data.length()-1;
335 if (data.find(' ') != string::npos)
336 keypos = data.find(' ');
337 if (data.find(',') != string::npos &&
338 keypos > data.find(','))
339 keypos = data.find(',');
341 value = data.substr(0, keypos);
343 if (keypos+1<data.length()-1)
344 data = frontStrip(data.substr(keypos+1, data.length()-1));
351 if (findkey == key) {
356 data = frontStrip(frontStrip(data,','));
359 else return keyvalue;