3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
10 * Full author contact details are available in file CREDITS.
15 #include "BiblioInfo.h"
17 #include "BufferParams.h"
18 #include "buffer_funcs.h"
20 #include "InsetIterator.h"
21 #include "Paragraph.h"
23 #include "insets/Inset.h"
24 #include "insets/InsetBibitem.h"
25 #include "insets/InsetBibtex.h"
26 #include "insets/InsetInclude.h"
28 #include "support/lstrings.h"
30 #include "boost/regex.hpp"
39 using support::bformat
;
40 using support::compare_no_case
;
41 using support::getVectorFromString
;
45 ////////////////////////////////////////
49 ////////////////////////////////////////
51 BibTeXInfo::BibTeXInfo() : isBibTeX(true)
55 bool BibTeXInfo::hasField(docstring
const & field
) const
57 return count(field
) == 1;
61 docstring
const & BibTeXInfo::getValueForField(docstring
const & field
) const
63 BibTeXInfo::const_iterator it
= find(field
);
66 static docstring
const empty_value
= docstring();
71 docstring
const & BibTeXInfo::getValueForField(string
const & field
) const
73 return getValueForField(from_ascii(field
));
78 docstring
const familyName(docstring
const & name
)
84 docstring fname
= name
;
86 // possible authorname combinations are:
87 // "Surname, FirstName"
89 // "FirstName Surname"
91 docstring::size_type idx
= fname
.find(',');
92 if (idx
!= docstring::npos
)
93 return ltrim(fname
.substr(0, idx
));
94 idx
= fname
.rfind('.');
95 if (idx
!= docstring::npos
&& idx
+ 1 < fname
.size())
96 fname
= ltrim(fname
.substr(idx
+ 1));
97 // test if we have a LaTeX Space in front
99 return fname
.substr(2);
106 docstring
const BibTeXInfo::getAbbreviatedAuthor() const
111 docstring author
= getValueForField("author");
113 if (author
.empty()) {
114 author
= getValueForField("editor");
119 //OK, we've got some names. Let's format them.
120 //Try to split the author list on " and "
121 vector
<docstring
> const authors
=
122 getVectorFromString(author
, from_ascii(" and "));
124 if (authors
.size() == 2)
125 return bformat(_("%1$s and %2$s"),
126 familyName(authors
[0]), familyName(authors
[1]));
127 else if (authors
.size() > 2)
128 return bformat(_("%1$s et al."), familyName(authors
[0]));
130 return familyName(authors
[0]);
133 docstring
const BibTeXInfo::getYear() const
138 docstring year
= getValueForField("year");
145 docstring
const BibTeXInfo::getInfo() const
148 BibTeXInfo::const_iterator it
= find(from_ascii("ref"));
153 //This could be made alot better using the entryType
154 //field to customize the output based upon entry type.
156 //Search for all possible "required" fields
157 docstring author
= getValueForField("author");
159 author
= getValueForField("editor");
161 docstring year
= getValueForField("year");
162 docstring title
= getValueForField("title");
163 docstring docLoc
= getValueForField("pages");
164 if (docLoc
.empty()) {
165 docLoc
= getValueForField("chapter");
167 docLoc
= from_ascii("Ch. ") + docLoc
;
169 docLoc
= from_ascii("pp. ") + docLoc
;
170 docstring media
= getValueForField("journal");
172 media
= getValueForField("publisher");
174 media
= getValueForField("school");
176 media
= getValueForField("institution");
179 docstring volume
= getValueForField("volume");
181 odocstringstream result
;
183 result
<< author
<< ", ";
187 result
<< ", " << media
;
189 result
<< ", " << year
;
191 result
<< ", " << docLoc
;
193 docstring
const result_str
= rtrim(result
.str());
194 if (!result_str
.empty())
197 // This should never happen (or at least be very unusual!)
202 ////////////////////////////////////////
206 ////////////////////////////////////////
209 // A functor for use with std::sort, leading to case insensitive sorting
210 class compareNoCase
: public std::binary_function
<docstring
, docstring
, bool>
213 bool operator()(docstring
const & s1
, docstring
const & s2
) const {
214 return compare_no_case(s1
, s2
) < 0;
220 vector
<docstring
> const BiblioInfo::getKeys() const
222 vector
<docstring
> bibkeys
;
223 BiblioInfo::const_iterator it
= begin();
224 for (; it
!= end(); ++it
)
225 bibkeys
.push_back(it
->first
);
226 std::sort(bibkeys
.begin(), bibkeys
.end(), compareNoCase());
231 vector
<docstring
> const BiblioInfo::getFields() const
233 vector
<docstring
> bibfields
;
234 set
<docstring
>::const_iterator it
= fieldNames
.begin();
235 set
<docstring
>::const_iterator end
= fieldNames
.end();
236 for (; it
!= end
; ++it
)
237 bibfields
.push_back(*it
);
238 std::sort(bibfields
.begin(), bibfields
.end());
243 vector
<docstring
> const BiblioInfo::getEntries() const
245 vector
<docstring
> bibentries
;
246 set
<docstring
>::const_iterator it
= entryTypes
.begin();
247 set
<docstring
>::const_iterator end
= entryTypes
.end();
248 for (; it
!= end
; ++it
)
249 bibentries
.push_back(*it
);
250 std::sort(bibentries
.begin(), bibentries
.end());
255 docstring
const BiblioInfo::getAbbreviatedAuthor(docstring
const & key
) const
257 BiblioInfo::const_iterator it
= find(key
);
260 BibTeXInfo
const & data
= it
->second
;
261 return data
.getAbbreviatedAuthor();
265 docstring
const BiblioInfo::getYear(docstring
const & key
) const
267 BiblioInfo::const_iterator it
= find(key
);
270 BibTeXInfo
const & data
= it
->second
;
271 return data
.getYear();
275 docstring
const BiblioInfo::getInfo(docstring
const & key
) const
277 BiblioInfo::const_iterator it
= find(key
);
280 BibTeXInfo
const & data
= it
->second
;
281 return data
.getInfo();
285 vector
<docstring
> const BiblioInfo::getCiteStrings(
286 docstring
const & key
, Buffer
const & buf
) const
288 biblio::CiteEngine
const engine
= buf
.params().getEngine();
289 if (engine
== biblio::ENGINE_NATBIB_NUMERICAL
)
290 return getNumericalStrings(key
, buf
);
292 return getAuthorYearStrings(key
, buf
);
296 vector
<docstring
> const BiblioInfo::getNumericalStrings(
297 docstring
const & key
, Buffer
const & buf
) const
300 return vector
<docstring
>();
302 docstring
const author
= getAbbreviatedAuthor(key
);
303 docstring
const year
= getYear(key
);
304 if (author
.empty() || year
.empty())
305 return vector
<docstring
>();
307 vector
<biblio::CiteStyle
> const & styles
=
308 biblio::getCiteStyles(buf
.params().getEngine());
310 vector
<docstring
> vec(styles
.size());
311 for (vector
<docstring
>::size_type i
= 0; i
!= vec
.size(); ++i
) {
317 str
= from_ascii("[#ID]");
321 str
= author
+ " [#ID]";
324 case biblio::CITEALT
:
325 str
= author
+ " #ID";
328 case biblio::CITEALP
:
329 str
= from_ascii("#ID");
332 case biblio::CITEAUTHOR
:
336 case biblio::CITEYEAR
:
340 case biblio::CITEYEARPAR
:
341 str
= '(' + year
+ ')';
352 vector
<docstring
> const BiblioInfo::getAuthorYearStrings(
353 docstring
const & key
, Buffer
const & buf
) const
356 return vector
<docstring
>();
358 docstring
const author
= getAbbreviatedAuthor(key
);
359 docstring
const year
= getYear(key
);
360 if (author
.empty() || year
.empty())
361 return vector
<docstring
>();
363 vector
<biblio::CiteStyle
> const & styles
=
364 getCiteStyles(buf
.params().getEngine());
366 vector
<docstring
> vec(styles
.size());
367 for (vector
<docstring
>::size_type i
= 0; i
!= vec
.size(); ++i
) {
372 // jurabib only: Author/Annotator
373 // (i.e. the "before" field, 2nd opt arg)
374 str
= author
+ "/<" + _("before") + '>';
378 str
= author
+ " (" + year
+ ')';
382 str
= '(' + author
+ ", " + year
+ ')';
385 case biblio::CITEALT
:
386 str
= author
+ ' ' + year
;
389 case biblio::CITEALP
:
390 str
= author
+ ", " + year
;
393 case biblio::CITEAUTHOR
:
397 case biblio::CITEYEAR
:
401 case biblio::CITEYEARPAR
:
402 str
= '(' + year
+ ')';
411 void BiblioInfo::fillWithBibKeys(Buffer
const * const buf
)
413 /// if this is a child document and the parent is already loaded
414 /// use the parent's list instead [ale990412]
415 Buffer
const * const tmp
= buf
->masterBuffer();
418 this->fillWithBibKeys(tmp
);
422 // Pre-load all child documents.
423 buf
->loadChildDocuments();
425 for (InsetIterator it
= inset_iterator_begin(buf
->inset()); it
; ++it
)
426 it
->fillWithBibKeys(*buf
, *this, it
);
432 ////////////////////////////////////////
436 ////////////////////////////////////////
441 char const * const citeCommands
[] = {
442 "cite", "citet", "citep", "citealt", "citealp", "citeauthor",
443 "citeyear", "citeyearpar" };
445 unsigned int const nCiteCommands
=
446 sizeof(citeCommands
) / sizeof(char *);
448 CiteStyle
const citeStyles
[] = {
449 CITE
, CITET
, CITEP
, CITEALT
, CITEALP
,
450 CITEAUTHOR
, CITEYEAR
, CITEYEARPAR
};
452 unsigned int const nCiteStyles
=
453 sizeof(citeStyles
) / sizeof(CiteStyle
);
455 CiteStyle
const citeStylesFull
[] = {
456 CITET
, CITEP
, CITEALT
, CITEALP
, CITEAUTHOR
};
458 unsigned int const nCiteStylesFull
=
459 sizeof(citeStylesFull
) / sizeof(CiteStyle
);
461 CiteStyle
const citeStylesUCase
[] = {
462 CITET
, CITEP
, CITEALT
, CITEALP
, CITEAUTHOR
};
464 unsigned int const nCiteStylesUCase
=
465 sizeof(citeStylesUCase
) / sizeof(CiteStyle
);
470 CitationStyle::CitationStyle(string
const & command
)
471 : style(CITE
), full(false), forceUCase(false)
476 string cmd
= command
;
482 string::size_type
const n
= cmd
.size() - 1;
483 if (cmd
!= "cite" && cmd
[n
] == '*') {
485 cmd
= cmd
.substr(0,n
);
488 char const * const * const last
= citeCommands
+ nCiteCommands
;
489 char const * const * const ptr
= std::find(citeCommands
, last
, cmd
);
492 size_t idx
= ptr
- citeCommands
;
493 style
= citeStyles
[idx
];
498 string
const CitationStyle::asLatexStr() const
500 string cite
= citeCommands
[style
];
502 CiteStyle
const * last
= citeStylesFull
+ nCiteStylesFull
;
503 if (std::find(citeStylesFull
, last
, style
) != last
)
508 CiteStyle
const * last
= citeStylesUCase
+ nCiteStylesUCase
;
509 if (std::find(citeStylesUCase
, last
, style
) != last
)
517 vector
<CiteStyle
> const getCiteStyles(CiteEngine
const engine
)
519 unsigned int nStyles
= 0;
520 unsigned int start
= 0;
527 case ENGINE_NATBIB_AUTHORYEAR
:
528 case ENGINE_NATBIB_NUMERICAL
:
529 nStyles
= nCiteStyles
- 1;
533 nStyles
= nCiteStyles
;
538 typedef vector
<CiteStyle
> cite_vec
;
540 cite_vec
styles(nStyles
);
541 cite_vec::size_type i
= 0;
543 for (; i
!= styles
.size(); ++i
, ++j
)
544 styles
[i
] = citeStyles
[j
];
549 } // namespace biblio