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::clearDaughterParams()
54 // A functor for use with std::sort, leading to case insensitive sorting
55 struct compareNoCase: public std::binary_function<string, string, bool>
57 bool operator()(string const & s1, string const & s2) const {
58 return compare_no_case(s1, s2) < 0;
63 vector<string> const ControlCitation::getBibkeys()
65 vector<string> bibkeys;
68 vector<pair<string,string> > blist = lv_.buffer()->getBibkeyList();
70 for (vector<pair<string,string> >::size_type i=0; i<blist.size(); ++i) {
71 bibkeys.push_back(blist[i].first);
72 bibkeysInfo_.insert(InfoMapValue(blist[i].first,
76 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
81 string const ControlCitation::getBibkeyInfo(string const & key)
85 if (bibkeysInfo_.empty()) getBibkeys();
87 InfoMap::const_iterator it = bibkeysInfo_.find(key);
88 if (it != bibkeysInfo_.end()) {
89 // Search for all possible "required" keys
90 string author = parseBibTeX(it->second, "author");
92 author = parseBibTeX(it->second, "editor");
94 string year = parseBibTeX(it->second, "year");
95 string title = parseBibTeX(it->second, "title");
96 string booktitle = parseBibTeX(it->second, "booktitle");
97 string chapter = parseBibTeX(it->second, "chapter");
98 string pages = parseBibTeX(it->second, "pages");
100 string media = parseBibTeX(it->second, "journal");
102 media = parseBibTeX(it->second, "publisher");
104 media = parseBibTeX(it->second, "school");
106 media = parseBibTeX(it->second, "institution");
110 result += ", " + year;
112 result += ", " + title;
113 if (!booktitle.empty())
114 result += ", in " + booktitle;
115 if (!chapter.empty())
116 result += ", Ch. " + chapter;
118 result += ", " + media;
120 result += ", pp. " + pages;
122 if (result.empty()) // not a BibTeX record
130 vector<string>::const_iterator
131 searchKeys(ControlCitation const & controller,
132 vector<string> const & keys,
134 vector<string>::const_iterator start,
135 ControlCitation::Search type,
136 ControlCitation::Direction dir,
139 // Preliminary checks
140 if(start < keys.begin() || start >= keys.end())
143 string search_expr = frontStrip(strip(expr));
144 if (search_expr.empty())
147 if (type == ControlCitation::SIMPLE)
148 return simpleSearch(controller, keys, search_expr, start, dir,
151 return regexSearch(controller, keys, search_expr, start, dir);
155 vector<string>::const_iterator
156 simpleSearch(ControlCitation const & controller,
157 vector<string> const & keys,
159 vector<string>::const_iterator start,
160 ControlCitation::Direction dir,
163 vector<string> searchwords = getVectorFromString(expr, " ");
165 // Loop over all keys from start...
166 for (vector<string>::const_iterator it = start;
167 // End condition is direction-dependent.
168 (dir == ControlCitation::FORWARD) ?
169 (it<keys.end()) : (it>=keys.begin());
170 // increment is direction-dependent.
171 (dir == ControlCitation::FORWARD) ?
175 ControlCitation::InfoMap::const_iterator info =
176 controller.bibkeysInfo().find(*it);
177 if (info != controller.bibkeysInfo().end())
178 data += " " + info->second;
180 data = lowercase(data);
184 // Loop over all search words...
186 for (vector<string>::const_iterator sit=
188 sit<searchwords.end(); ++sit) {
189 if (data.find(*sit) == string::npos) {
195 for (vector<string>::const_iterator sit=
197 sit<searchwords.end(); ++sit) {
198 if (data.find(lowercase(*sit)) ==
206 if (found) return it;
213 vector<string>::const_iterator
214 regexSearch(ControlCitation const & controller,
215 vector<string> const & keys,
217 vector<string>::const_iterator start,
218 ControlCitation::Direction dir)
222 for (vector<string>::const_iterator it = start;
223 // End condition is direction-dependent.
224 (dir == ControlCitation::FORWARD) ?
225 (it<keys.end()) : (it>=keys.begin());
226 // increment is direction-dependent.
227 (dir == ControlCitation::FORWARD) ?
231 ControlCitation::InfoMap::const_iterator info =
232 controller.bibkeysInfo().find(*it);
233 if (info != controller.bibkeysInfo().end())
234 data += " " + info->second;
236 if (reg.exec(data).size() > 0)
243 string const parseBibTeX(string data, string const & findkey)
247 for (string::iterator it=data.begin(); it<data.end(); ++it) {
248 if ((*it) == '\n' || (*it) == '\t')
252 data = frontStrip(data);
253 while (!data.empty() && data[0] != '=' &&
254 (data.find(' ') != string::npos || data.find('=') != string::npos)) {
256 string::size_type keypos = min(data.find(' '), data.find('='));
257 string key = lowercase(data.substr(0, keypos));
259 data = data.substr(keypos, data.length()-1);
260 data = frontStrip(strip(data));
261 if (data.length() > 1 && data[0]=='=') {
262 data = frontStrip(data.substr(1, data.length()-1));
270 } else if (data[0]=='"') {
278 data.find(enclosing)!=string::npos &&
280 string tmp = data.substr(keypos,
282 while (tmp.find('{') != string::npos &&
283 tmp.find('}') != string::npos &&
284 tmp.find('{') < tmp.find('}') &&
285 tmp.find('{') < tmp.find(enclosing)) {
287 keypos += tmp.find('{')+1;
288 tmp = data.substr(keypos,
290 keypos += tmp.find('}')+1;
291 tmp = data.substr(keypos,
295 if (tmp.find(enclosing)==string::npos)
298 keypos += tmp.find(enclosing);
299 tmp = data.substr(keypos,
303 value = data.substr(1, keypos-1);
305 if (keypos+1<data.length()-1)
306 data = frontStrip(data.substr(keypos+1, data.length()-1));
310 } else if (!keypos &&
313 keypos = data.length()-1;
314 if (data.find(' ') != string::npos)
315 keypos = data.find(' ');
316 if (data.find(',') != string::npos &&
317 keypos > data.find(','))
318 keypos = data.find(',');
320 value = data.substr(0, keypos);
322 if (keypos+1<data.length()-1)
323 data = frontStrip(data.substr(keypos+1, data.length()-1));
330 if (findkey == key) {
335 data = frontStrip(frontStrip(data,','));
338 else return keyvalue;