2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 2001 The LyX Team.
9 * ======================================================
11 * \file ControlCitation.C
12 * \author Angus Leeming <a.leeming@ic.ac.uk>
18 #pragma implementation
23 #include "ControlCitation.h"
27 #include "helper_funcs.h"
28 #include "support/lstrings.h"
29 #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;
123 if (result.empty()) // not a BibTeX record
131 vector<string>::const_iterator
132 searchKeys(ControlCitation const & controller,
133 vector<string> const & keys,
135 vector<string>::const_iterator start,
136 ControlCitation::Search type,
137 ControlCitation::Direction dir,
140 // Preliminary checks
141 if(start < keys.begin() || start >= keys.end())
144 string search_expr = frontStrip(strip(expr));
145 if (search_expr.empty())
148 if (type == ControlCitation::SIMPLE)
149 return simpleSearch(controller, keys, search_expr, start, dir,
152 return regexSearch(controller, keys, search_expr, start, dir);
156 vector<string>::const_iterator
157 simpleSearch(ControlCitation const & controller,
158 vector<string> const & keys,
160 vector<string>::const_iterator start,
161 ControlCitation::Direction dir,
164 vector<string> searchwords = getVectorFromString(expr, " ");
166 // Loop over all keys from start...
167 for (vector<string>::const_iterator it = start;
168 // End condition is direction-dependent.
169 (dir == ControlCitation::FORWARD) ?
170 (it<keys.end()) : (it>=keys.begin());
171 // increment is direction-dependent.
172 (dir == ControlCitation::FORWARD) ?
176 ControlCitation::InfoMap::const_iterator info =
177 controller.bibkeysInfo().find(*it);
178 if (info != controller.bibkeysInfo().end())
179 data += " " + info->second;
181 data = lowercase(data);
185 // Loop over all search words...
187 for (vector<string>::const_iterator sit=
189 sit<searchwords.end(); ++sit) {
190 if (data.find(*sit) == string::npos) {
196 for (vector<string>::const_iterator sit=
198 sit<searchwords.end(); ++sit) {
199 if (data.find(lowercase(*sit)) ==
207 if (found) return it;
214 vector<string>::const_iterator
215 regexSearch(ControlCitation const & controller,
216 vector<string> const & keys,
218 vector<string>::const_iterator start,
219 ControlCitation::Direction dir)
223 for (vector<string>::const_iterator it = start;
224 // End condition is direction-dependent.
225 (dir == ControlCitation::FORWARD) ?
226 (it<keys.end()) : (it>=keys.begin());
227 // increment is direction-dependent.
228 (dir == ControlCitation::FORWARD) ?
232 ControlCitation::InfoMap::const_iterator info =
233 controller.bibkeysInfo().find(*it);
234 if (info != controller.bibkeysInfo().end())
235 data += " " + info->second;
237 if (reg.exec(data).size() > 0)
244 string const parseBibTeX(string data, string const & findkey)
248 for (string::iterator it=data.begin(); it<data.end(); ++it) {
249 if ((*it) == '\n' || (*it) == '\t')
253 data = frontStrip(data);
254 while (!data.empty() && data[0] != '=' &&
255 (data.find(' ') != string::npos || data.find('=') != string::npos)) {
257 string::size_type keypos = min(data.find(' '), data.find('='));
258 string key = lowercase(data.substr(0, keypos));
260 data = data.substr(keypos, data.length()-1);
261 data = frontStrip(strip(data));
262 if (data.length() > 1 && data[0]=='=') {
263 data = frontStrip(data.substr(1, data.length()-1));
271 } else if (data[0]=='"') {
279 data.find(enclosing)!=string::npos &&
281 string tmp = data.substr(keypos,
283 while (tmp.find('{') != string::npos &&
284 tmp.find('}') != string::npos &&
285 tmp.find('{') < tmp.find('}') &&
286 tmp.find('{') < tmp.find(enclosing)) {
288 keypos += tmp.find('{')+1;
289 tmp = data.substr(keypos,
291 keypos += tmp.find('}')+1;
292 tmp = data.substr(keypos,
296 if (tmp.find(enclosing)==string::npos)
299 keypos += tmp.find(enclosing);
300 tmp = data.substr(keypos,
304 value = data.substr(1, keypos-1);
306 if (keypos+1<data.length()-1)
307 data = frontStrip(data.substr(keypos+1, data.length()-1));
311 } else if (!keypos &&
314 keypos = data.length()-1;
315 if (data.find(' ') != string::npos)
316 keypos = data.find(' ');
317 if (data.find(',') != string::npos &&
318 keypos > data.find(','))
319 keypos = data.find(',');
321 value = data.substr(0, keypos);
323 if (keypos+1<data.length()-1)
324 data = frontStrip(data.substr(keypos+1, data.length()-1));
331 if (findkey == key) {
336 data = frontStrip(frontStrip(data,','));
339 else return keyvalue;