]> git.lyx.org Git - lyx.git/blob - src/frontends/controllers/biblio.C
Controller-view split of Graphics and Index popups.
[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
58         typedef std::map<string, string>::value_type InfoMapValue;
59
60         for (InfoMap::const_iterator it = map.begin(); it != map.end(); ++it) {
61                 bibkeys.push_back(it->first);
62         }
63
64         sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
65         return bibkeys;
66 }
67
68
69 string const getInfo(InfoMap const & map, string const & key)
70 {
71         Assert(!map.empty());
72
73         string result;
74
75         InfoMap::const_iterator it = map.find(key);
76         if (it != map.end()) {
77                 // Search for all possible "required" keys
78                 string author = parseBibTeX(it->second, "author");
79                 if (author.empty())
80                         author = parseBibTeX(it->second, "editor");
81
82                 string year       = parseBibTeX(it->second, "year");
83                 string title      = parseBibTeX(it->second, "title");
84                 string booktitle  = parseBibTeX(it->second, "booktitle");
85                 string chapter    = parseBibTeX(it->second, "chapter");
86                 string pages      = parseBibTeX(it->second, "pages");
87
88                 string media      = parseBibTeX(it->second, "journal");
89                 if (media.empty())
90                         media = parseBibTeX(it->second, "publisher");
91                 if (media.empty())
92                         media = parseBibTeX(it->second, "school");
93                 if (media.empty())
94                         media = parseBibTeX(it->second, "institution");
95
96                 result = author;
97                 if (!year.empty())
98                         result += ", " + year;
99                 if (!title.empty())
100                         result += ", " + title;
101                 if (!booktitle.empty())
102                         result += ", in " + booktitle;
103                 if (!chapter.empty())
104                         result += ", Ch. " + chapter;
105                 if (!media.empty())
106                         result += ", " + media;
107                 if (!pages.empty())
108                         result += ", pp. " + pages;
109
110                 if (result.empty()) // not a BibTeX record
111                         result = it->second;
112         }
113
114         return result;
115 }
116  
117
118 vector<string>::const_iterator
119 searchKeys(InfoMap const & theMap,
120            vector<string> const & keys,
121            string const & expr,
122            vector<string>::const_iterator start,
123            Search type,
124            Direction dir,
125            bool caseSensitive)
126 {
127         // Preliminary checks
128         if(start < keys.begin() || start >= keys.end())
129                 return keys.end();
130         
131         string search_expr = frontStrip(strip(expr));
132         if (search_expr.empty())
133                 return start;
134
135         if (type == SIMPLE)
136                 return simpleSearch(theMap, keys, search_expr, start, dir,
137                                     caseSensitive);
138
139         return regexSearch(theMap, keys, search_expr, start, dir);
140 }
141
142
143 vector<string>::const_iterator
144 simpleSearch(InfoMap const & theMap,
145              vector<string> const & keys,
146              string const & expr,
147              vector<string>::const_iterator start,
148              Direction dir,
149              bool caseSensitive)
150 {
151         vector<string> searchwords = getVectorFromString(expr, " ");
152
153         // Loop over all keys from start...
154         for (vector<string>::const_iterator it = start;
155              // End condition is direction-dependent.
156              (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
157              // increment is direction-dependent.
158              (dir == FORWARD) ? (++it) : (--it)) {
159
160                 string data = (*it);
161                 biblio::InfoMap::const_iterator info = theMap.find(*it);
162                 if (info != theMap.end())
163                         data += " " + info->second;
164                 if (!caseSensitive)
165                         data = lowercase(data);
166
167                 bool found = true;
168
169                 // Loop over all search words...
170                 if (caseSensitive) {
171                         for (vector<string>::const_iterator sit=
172                                      searchwords.begin();
173                              sit<searchwords.end(); ++sit) {
174                                 if (data.find(*sit) == string::npos) {
175                                         found = false;
176                                         break;
177                                 }
178                         }
179                 } else {
180                         for (vector<string>::const_iterator sit=
181                                      searchwords.begin();
182                              sit<searchwords.end(); ++sit) {
183                                 if (data.find(lowercase(*sit)) ==
184                                     string::npos) {
185                                         found = false;
186                                         break;
187                                 }
188                         }
189                 }
190                 
191                 if (found) return it;
192         }
193
194         return keys.end();
195 }
196
197
198 vector<string>::const_iterator
199 regexSearch(InfoMap const & theMap,
200             vector<string> const & keys,
201             string const & expr,
202             vector<string>::const_iterator start,
203             Direction dir)
204 {
205         LRegex reg(expr);
206
207         for (vector<string>::const_iterator it = start;
208              // End condition is direction-dependent.
209              (dir == FORWARD) ? (it<keys.end()) : (it>=keys.begin());
210              // increment is direction-dependent.
211              (dir == FORWARD) ? (++it) : (--it)) {
212
213                 string data = (*it);
214                 biblio::InfoMap::const_iterator info = theMap.find(*it);
215                 if (info != theMap.end())
216                         data += " " + info->second;
217
218                 if (reg.exec(data).size() > 0)
219                         return it;
220         }
221
222         return keys.end();
223 }
224
225 string const parseBibTeX(string data, string const & findkey)
226 {
227         string keyvalue;
228         
229         for (string::iterator it=data.begin(); it<data.end(); ++it) {
230                 if ((*it) == '\n' || (*it) == '\t')
231                         (*it)= ' ';
232         }
233         
234         data = frontStrip(data);
235         while (!data.empty() && data[0] != '=' && 
236                (data.find(' ') != string::npos || data.find('=') != string::npos)) {
237
238                 string::size_type keypos = min(data.find(' '), data.find('='));
239                 string key = lowercase(data.substr(0, keypos));
240       
241                 data = data.substr(keypos, data.length()-1);
242                 data = frontStrip(strip(data));
243                 if (data.length() > 1 && data[0]=='=') {
244                         data = frontStrip(data.substr(1, data.length()-1));
245                         if (!data.empty()) {
246                                 keypos = 1;
247                                 string value;
248                                 char enclosing;
249
250                                 if (data[0]=='{') {
251                                         enclosing = '}';
252                                 } else if (data[0]=='"') {
253                                         enclosing = '"';
254                                 } else {
255                                         keypos=0;
256                                         enclosing=' ';
257                                 }
258
259                                 if (keypos &&
260                                     data.find(enclosing)!=string::npos &&
261                                     data.length()>1) {
262                                         string tmp = data.substr(keypos,
263                                                                  data.length()-1);
264                                         while (tmp.find('{') != string::npos &&
265                                                tmp.find('}') != string::npos &&
266                                                tmp.find('{') < tmp.find('}') &&
267                                                tmp.find('{') < tmp.find(enclosing)) {
268
269                                                 keypos += tmp.find('{')+1;
270                                                 tmp = data.substr(keypos,
271                                                                   data.length()-1);
272                                                 keypos += tmp.find('}')+1;
273                                                 tmp = data.substr(keypos,
274                                                                   data.length()-1);
275                                         }
276
277                                         if (tmp.find(enclosing)==string::npos)
278                                                 return keyvalue;
279                                         else {
280                                                 keypos += tmp.find(enclosing);
281                                                 tmp = data.substr(keypos,
282                                                                   data.length()-1);
283                                         }
284
285                                         value = data.substr(1, keypos-1);
286
287                                         if (keypos+1<data.length()-1)
288                                                 data = frontStrip(data.substr(keypos+1, data.length()-1));
289                                         else
290                                                 data = "";
291
292                                 } else if (!keypos &&
293                                            (data.find(' ') ||
294                                             data.find(','))) {
295                                         keypos = data.length()-1;
296                                         if (data.find(' ') != string::npos)
297                                                 keypos = data.find(' ');
298                                         if (data.find(',') != string::npos &&
299                                             keypos > data.find(','))
300                                                 keypos = data.find(',');
301
302                                         value = data.substr(0, keypos);
303                   
304                                         if (keypos+1<data.length()-1)
305                                                 data = frontStrip(data.substr(keypos+1, data.length()-1));
306                                         else
307                                                 data = "";
308                                 }
309                                 else
310                                         return keyvalue;
311
312                                 if (findkey == key) {
313                                         keyvalue = value;
314                                         return keyvalue;
315                                 } 
316
317                                 data = frontStrip(frontStrip(data,','));
318                         }
319                 }
320                 else return keyvalue;
321         }
322         return keyvalue;
323 }
324
325
326 } // namespace biblio 
327