]> git.lyx.org Git - lyx.git/blob - src/frontends/controllers/biblio.C
Two tiny clean-ups.
[lyx.git] / src / frontends / controllers / biblio.C
1 /* This file is part of
2  * ====================================================== 
3  *
4  *           LyX, The Document Processor
5  *
6  *           Copyright 2001 The LyX Team.
7  *
8  * ======================================================
9  *
10  * \file biblio.C
11  * \author Angus Leeming <a.leeming@ic.ac.uk>
12  */
13
14 #include <vector>
15 #include <algorithm>
16
17 #ifdef __GNUG__
18 #pragma implementation
19 #endif
20
21 #include <config.h>
22
23 /*
24 #include "buffer.h"
25 #include "Dialogs.h"
26 #include "LyXView.h"
27 */
28 #include "LString.h"
29 #include "biblio.h"
30 #include "helper_funcs.h"
31 #include "support/lstrings.h"
32 #include "support/LAssert.h"
33 #include "support/LRegex.h"
34
35 using std::find;
36 using std::min;
37 using std::pair;
38 using std::vector;
39 using std::sort;
40
41 namespace biblio 
42 {
43
44
45 // A functor for use with std::sort, leading to case insensitive sorting
46 struct compareNoCase: public std::binary_function<string, string, bool> 
47 {
48         bool operator()(string const & s1, string const & s2) const {
49                 return compare_no_case(s1, s2) < 0;
50         }
51 };
52
53 vector<string> const getKeys(InfoMap const & map)
54 {
55         vector<string> bibkeys;
56
57         for (InfoMap::const_iterator it = map.begin(); it != map.end(); ++it) {
58                 bibkeys.push_back(it->first);
59         }
60
61         sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
62         return bibkeys;
63 }
64
65
66 string const getInfo(InfoMap const & map, string const & key)
67 {
68         lyx::Assert(!map.empty());
69
70         string result;
71
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");
76                 if (author.empty())
77                         author = parseBibTeX(it->second, "editor");
78
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");
84
85                 string media      = parseBibTeX(it->second, "journal");
86                 if (media.empty())
87                         media = parseBibTeX(it->second, "publisher");
88                 if (media.empty())
89                         media = parseBibTeX(it->second, "school");
90                 if (media.empty())
91                         media = parseBibTeX(it->second, "institution");
92
93                 result = author;
94                 if (!year.empty())
95                         result += ", " + year;
96                 if (!title.empty())
97                         result += ", " + title;
98                 if (!booktitle.empty())
99                         result += ", in " + booktitle;
100                 if (!chapter.empty())
101                         result += ", Ch. " + chapter;
102                 if (!media.empty())
103                         result += ", " + media;
104                 if (!pages.empty())
105                         result += ", pp. " + pages;
106
107                 if (result.empty()) // not a BibTeX record
108                         result = it->second;
109         }
110
111         return result;
112 }
113  
114
115 vector<string>::const_iterator
116 searchKeys(InfoMap const & theMap,
117            vector<string> const & keys,
118            string const & expr,
119            vector<string>::const_iterator start,
120            Search type,
121            Direction dir,
122            bool caseSensitive)
123 {
124         // Preliminary checks
125         if(start < keys.begin() || start >= keys.end())
126                 return keys.end();
127         
128         string search_expr = frontStrip(strip(expr));
129         if (search_expr.empty())
130                 return keys.end();
131
132         if (type == SIMPLE)
133                 return simpleSearch(theMap, keys, search_expr, start, dir,
134                                     caseSensitive);
135
136         return regexSearch(theMap, keys, search_expr, start, dir);
137 }
138
139
140 vector<string>::const_iterator
141 simpleSearch(InfoMap const & theMap,
142              vector<string> const & keys,
143              string const & expr,
144              vector<string>::const_iterator start,
145              Direction dir,
146              bool caseSensitive)
147 {
148         string tmp = expr;
149         if (!caseSensitive)
150                 tmp = lowercase(tmp);
151
152         vector<string> searchwords = getVectorFromString(tmp, " ");
153
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)) {
160
161                 string data = (*it);
162                 biblio::InfoMap::const_iterator info = theMap.find(*it);
163                 if (info != theMap.end())
164                         data += " " + info->second;
165                 if (!caseSensitive)
166                         data = lowercase(data);
167
168                 bool found = true;
169
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) {
174                                 found = false;
175                                 break;
176                         }
177                 }
178                 
179                 if (found) return it;
180         }
181
182         return keys.end();
183 }
184
185
186 vector<string>::const_iterator
187 regexSearch(InfoMap const & theMap,
188             vector<string> const & keys,
189             string const & expr,
190             vector<string>::const_iterator start,
191             Direction dir)
192 {
193         LRegex reg(expr);
194
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)) {
200
201                 string data = (*it);
202                 biblio::InfoMap::const_iterator info = theMap.find(*it);
203                 if (info != theMap.end())
204                         data += " " + info->second;
205
206                 if (reg.exec(data).size() > 0)
207                         return it;
208         }
209
210         return keys.end();
211 }
212
213 string const parseBibTeX(string data, string const & findkey)
214 {
215         string keyvalue;
216         
217         for (string::iterator it=data.begin(); it<data.end(); ++it) {
218                 if ((*it) == '\n' || (*it) == '\t')
219                         (*it)= ' ';
220         }
221         
222         data = frontStrip(data);
223         while (!data.empty() && data[0] != '=' && 
224                (data.find(' ') != string::npos || data.find('=') != string::npos)) {
225
226                 string::size_type keypos = min(data.find(' '), data.find('='));
227                 string key = lowercase(data.substr(0, keypos));
228       
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));
233                         if (!data.empty()) {
234                                 keypos = 1;
235                                 string value;
236                                 char enclosing;
237
238                                 if (data[0]=='{') {
239                                         enclosing = '}';
240                                 } else if (data[0]=='"') {
241                                         enclosing = '"';
242                                 } else {
243                                         keypos=0;
244                                         enclosing=' ';
245                                 }
246
247                                 if (keypos &&
248                                     data.find(enclosing)!=string::npos &&
249                                     data.length()>1) {
250                                         string tmp = data.substr(keypos,
251                                                                  data.length()-1);
252                                         while (tmp.find('{') != string::npos &&
253                                                tmp.find('}') != string::npos &&
254                                                tmp.find('{') < tmp.find('}') &&
255                                                tmp.find('{') < tmp.find(enclosing)) {
256
257                                                 keypos += tmp.find('{')+1;
258                                                 tmp = data.substr(keypos,
259                                                                   data.length()-1);
260                                                 keypos += tmp.find('}')+1;
261                                                 tmp = data.substr(keypos,
262                                                                   data.length()-1);
263                                         }
264
265                                         if (tmp.find(enclosing)==string::npos)
266                                                 return keyvalue;
267                                         else {
268                                                 keypos += tmp.find(enclosing);
269                                                 tmp = data.substr(keypos,
270                                                                   data.length()-1);
271                                         }
272
273                                         value = data.substr(1, keypos-1);
274
275                                         if (keypos+1<data.length()-1)
276                                                 data = frontStrip(data.substr(keypos+1, data.length()-1));
277                                         else
278                                                 data = "";
279
280                                 } else if (!keypos &&
281                                            (data.find(' ') ||
282                                             data.find(','))) {
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(',');
289
290                                         value = data.substr(0, keypos);
291                   
292                                         if (keypos+1<data.length()-1)
293                                                 data = frontStrip(data.substr(keypos+1, data.length()-1));
294                                         else
295                                                 data = "";
296                                 }
297                                 else
298                                         return keyvalue;
299
300                                 if (findkey == key) {
301                                         keyvalue = value;
302                                         return keyvalue;
303                                 } 
304
305                                 data = frontStrip(frontStrip(data,','));
306                         }
307                 }
308                 else return keyvalue;
309         }
310         return keyvalue;
311 }
312
313
314 } // namespace biblio 
315