#include "buffer.h"
#include "bufferparams.h"
-#include "BufferView.h"
+#include "debug.h"
#include "dispatchresult.h"
#include "funcrequest.h"
#include "LaTeXFeatures.h"
#include "frontends/controllers/biblio.h"
+#include "support/fs_extras.h"
#include "support/lstrings.h"
-using lyx::support::ascii_lowercase;
-using lyx::support::contains;
-using lyx::support::getVectorFromString;
-using lyx::support::ltrim;
-using lyx::support::rtrim;
-using lyx::support::split;
+#include <algorithm>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/exception.hpp>
+
+
+namespace lyx {
+
+using support::ascii_lowercase;
+using support::contains;
+using support::FileName;
+using support::getStringFromVector;
+using support::getVectorFromString;
+using support::ltrim;
+using support::rtrim;
+using support::split;
+using support::tokenPos;
+
+using std::endl;
+using std::replace;
using std::string;
using std::ostream;
using std::vector;
using std::map;
-namespace biblio = lyx::biblio;
+namespace fs = boost::filesystem;
namespace {
if (!buffer.fully_loaded())
return string();
+ // Cache the labels
typedef std::map<Buffer const *, biblio::InfoMap> CachedMap;
static CachedMap cached_keys;
- // build the keylist
- typedef vector<std::pair<string, string> > InfoType;
- InfoType bibkeys;
- buffer.fillWithBibKeys(bibkeys);
-
- InfoType::const_iterator bit = bibkeys.begin();
- InfoType::const_iterator bend = bibkeys.end();
+ // and cache the timestamp of the bibliography files.
+ static std::map<FileName, time_t> bibfileStatus;
biblio::InfoMap infomap;
- for (; bit != bend; ++bit) {
- infomap[bit->first] = bit->second;
+
+ vector<FileName> const & bibfilesCache = buffer.getBibfilesCache();
+ // compare the cached timestamps with the actual ones.
+ bool changed = false;
+ for (vector<FileName>::const_iterator it = bibfilesCache.begin();
+ it != bibfilesCache.end(); ++ it) {
+ FileName const f = *it;
+ try {
+ std::time_t lastw = fs::last_write_time(f.toFilesystemEncoding());
+ if (lastw != bibfileStatus[f]) {
+ changed = true;
+ bibfileStatus[f] = lastw;
+ }
+ }
+ catch (fs::filesystem_error & fserr) {
+ changed = true;
+ lyxerr << "Couldn't find or read bibtex file "
+ << f << endl;
+ lyxerr[Debug::DEBUG] << "Fs error: "
+ << fserr.what() << endl;
+ }
}
+
+ // build the keylist only if the bibfiles have been changed
+ if (cached_keys.empty() || bibfileStatus.empty() || changed) {
+ typedef vector<std::pair<string, string> > InfoType;
+ InfoType bibkeys;
+ buffer.fillWithBibKeys(bibkeys);
+
+ InfoType::const_iterator bit = bibkeys.begin();
+ InfoType::const_iterator bend = bibkeys.end();
+
+ for (; bit != bend; ++bit)
+ infomap[bit->first] = bit->second;
+
+ cached_keys[&buffer] = infomap;
+ } else
+ // use the cached keys
+ infomap = cached_keys[&buffer];
+
if (infomap.empty())
return string();
- cached_keys[&buffer] = infomap;
-
// the natbib citation-styles
// CITET: author (year)
// CITEP: (author,year)
{}
-string const InsetCitation::generateLabel(Buffer const & buffer) const
+docstring const InsetCitation::generateLabel(Buffer const & buffer) const
{
string const before = getSecOptions();
string const after = getOptions();
label = getBasicLabel(getContents(), after);
}
- return label;
+ // FIXME UNICODE
+ return from_utf8(label);
}
-string const InsetCitation::getScreenLabel(Buffer const & buffer) const
+docstring const InsetCitation::getScreenLabel(Buffer const & buffer) const
{
biblio::CiteEngine const engine = biblio::getEngine(buffer);
if (cache.params == params() && cache.engine == engine)
string const before = getSecOptions();
string const after = getOptions();
- string const glabel = generateLabel(buffer);
+ docstring const glabel = generateLabel(buffer);
unsigned int const maxLabelChars = 45;
- string label = glabel;
+ docstring label = glabel;
if (label.size() > maxLabelChars) {
label.erase(maxLabelChars-3);
label += "...";
}
-int InsetCitation::plaintext(Buffer const & buffer, ostream & os, OutputParams const &) const
+int InsetCitation::plaintext(Buffer const & buffer, odocstream & os,
+ OutputParams const &) const
{
if (cache.params == params() &&
cache.engine == biblio::getEngine(buffer))
}
+namespace {
+
+string const cleanupWhitespace(string const & citelist)
+{
+ string::const_iterator it = citelist.begin();
+ string::const_iterator end = citelist.end();
+ // Paranoia check: make sure that there is no whitespace in here
+ // -- at least not behind commas or at the beginning
+ string result;
+ char last = ',';
+ for (; it != end; ++it) {
+ if (*it != ' ')
+ last = *it;
+ if (*it != ' ' || last != ',')
+ result += *it;
+ }
+ return result;
+}
+
+// end anon namyspace
+}
+
+int InsetCitation::docbook(Buffer const &, odocstream & os, OutputParams const &) const
+{
+ os << "<citation>"
+ << from_ascii(cleanupWhitespace(getContents()))
+ << "</citation>";
+ return 0;
+}
+
+
+int InsetCitation::textString(Buffer const & buf, odocstream & os,
+ OutputParams const & op) const
+{
+ return plaintext(buf, os, op);
+}
+
+
// Have to overwrite the default InsetCommand method in order to check that
// the \cite command is valid. Eg, the user has natbib enabled, inputs some
// citations and then changes his mind, turning natbib support off. The output
// should revert to \cite[]{}
-int InsetCitation::latex(Buffer const & buffer, ostream & os,
+int InsetCitation::latex(Buffer const & buffer, odocstream & os,
OutputParams const &) const
{
biblio::CiteEngine const cite_engine = buffer.params().cite_engine;
- string const cite_str =
- biblio::asValidLatexCommand(getCmdName(), cite_engine);
-
+ // FIXME UNICODE
+ docstring const cite_str = from_utf8(
+ biblio::asValidLatexCommand(getCmdName(), cite_engine));
+
os << "\\" << cite_str;
-
- string const before = getSecOptions();
- string const after = getOptions();
+
+ docstring const & before = getParam("before");
+ docstring const & after = getParam("after");
if (!before.empty() && cite_engine != biblio::ENGINE_BASIC)
os << '[' << before << "][" << after << ']';
else if (!after.empty())
os << '[' << after << ']';
- string::const_iterator it = getContents().begin();
- string::const_iterator end = getContents().end();
- // Paranoia check: make sure that there is no whitespace in here
- string content;
- char last = ',';
- for (; it != end; ++it) {
- if (*it != ' ')
- last = *it;
- if (*it != ' ' || last != ',')
- content += *it;
- }
-
- os << '{' << content << '}';
+ // FIXME UNICODE
+ os << '{' << from_utf8(cleanupWhitespace(getContents())) << '}';
return 0;
}
break;
}
}
+
+
+void InsetCitation::replaceContents(string const & from, string const & to)
+{
+ if (tokenPos(getContents(), ',', from) != -1) {
+ vector<string> items = getVectorFromString(getContents());
+ replace(items.begin(), items.end(), from, to);
+ setContents(getStringFromVector(items));
+ }
+}
+
+
+} // namespace lyx