#include "Converter.h"
#include "Counters.h"
#include "DocIterator.h"
-#include "EmbeddedFiles.h"
#include "Encoding.h"
#include "ErrorList.h"
#include "Exporter.h"
#include "graphics/Previews.h"
+#include "support/lassert.h"
#include "support/convert.h"
#include "support/debug.h"
#include "support/ExceptionMessage.h"
#include "support/Path.h"
#include "support/textutils.h"
#include "support/types.h"
-#include "support/FileZipListDir.h"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
namespace {
-int const LYX_FORMAT = 324;
+int const LYX_FORMAT = 337;
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
/// Container for all sort of Buffer dependant errors.
map<string, ErrorList> errorLists;
- /// all embedded files of this buffer
- EmbeddedFileList embedded_files;
-
/// timestamp and checksum used to test if the file has been externally
/// modified. (Used to properly enable 'File->Revert to saved', bug 4114).
time_t timestamp_;
/// A cache for the bibfiles (including bibfiles of loaded child
/// documents), needed for appropriate update of natbib labels.
- mutable EmbeddedFileList bibfilesCache_;
+ mutable support::FileNameList bibfilesCache_;
+
+ // FIXME The caching mechanism could be improved. At present, we have a
+ // cache for each Buffer, that caches all the bibliography info for that
+ // Buffer. A more efficient solution would be to have a global cache per
+ // file, and then to construct the Buffer's bibinfo from that.
+ /// A cache for bibliography info
+ mutable BiblioInfo bibinfo_;
+ /// whether the bibinfo cache is valid
+ bool bibinfoCacheValid_;
+ /// Cache of timestamps of .bib files
+ map<FileName, time_t> bibfileStatus_;
mutable RefCache ref_cache_;
InsetText inset;
};
+
/// Creates the per buffer temporary directory
static FileName createBufferTmpDir()
{
Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_)
: parent_buffer(0), lyx_clean(true), bak_clean(true), unnamed(false),
read_only(readonly_), filename(file), file_fully_loaded(false),
- toc_backend(&parent), macro_lock(false),
- embedded_files(), timestamp_(0), checksum_(0), wa_(0),
- undo_(parent)
+ toc_backend(&parent), macro_lock(false), timestamp_(0),
+ checksum_(0), wa_(0), undo_(parent), bibinfoCacheValid_(false)
{
temppath = createBufferTmpDir();
lyxvc.setBuffer(&parent);
frontend::WorkAreaManager & Buffer::workAreaManager() const
{
- BOOST_ASSERT(d->wa_);
+ LASSERT(d->wa_, /**/);
return *d->wa_;
}
}
-EmbeddedFileList & Buffer::embeddedFiles()
-{
- return d->embedded_files;
-}
-
-
-EmbeddedFileList const & Buffer::embeddedFiles() const
-{
- return d->embedded_files;
-}
-
-
-bool Buffer::embedded() const
-{
- return params().embedded;
-}
-
-
Undo & Buffer::undo()
{
return d->undo_;
params().branchlist().clear();
params().preamble.erase();
params().options.erase();
+ params().master.erase();
params().float_placement.erase();
params().paperwidth.erase();
params().paperheight.erase();
params().headsep.erase();
params().footskip.erase();
params().columnsep.erase();
+ params().fontsCJK.erase();
params().listings_params.clear();
params().clearLayoutModules();
params().pdfoptions().clear();
ErrorList & errorList = d->errorLists["Parse"];
while (lex.isOK()) {
- lex.next();
- string const token = lex.getString();
+ string token;
+ lex >> token;
if (token.empty())
continue;
LYXERR(Debug::PARSER, "Handling document header token: `"
<< token << '\'');
- string unknown = params().readToken(lex, token, d->filename.onlyPath(),
- d->temppath);
+ string unknown = params().readToken(lex, token, d->filename.onlyPath());
if (!unknown.empty()) {
if (unknown[0] != '\\' && token == "\\textclass") {
Alert::warning(_("Unknown document class"),
ErrorList & errorList = d->errorLists["Parse"];
errorList.clear();
- lex.next();
- string const token = lex.getString();
- if (token != "\\begin_document") {
+ if (!lex.checkFor("\\begin_document")) {
docstring const s = _("\\begin_document is missing");
errorList.push_back(ErrorItem(_("Document header error"),
s, -1, 0, 0));
}
// we are reading in a brand new document
- BOOST_ASSERT(paragraphs().empty());
+ LASSERT(paragraphs().empty(), /**/);
readHeader(lex);
}
}
+ if (!params().master.empty()) {
+ FileName const master_file = makeAbsPath(params().master,
+ onlyPath(absFileName()));
+ if (isLyXFilename(master_file.absFilename())) {
+ Buffer * master = checkAndLoadLyXFile(master_file);
+ d->parent_buffer = master;
+ }
+ }
+
// read main text
bool const res = text().read(*this, lex, errorList, &(d->inset));
- // Enable embeded files, which will set temp path and move
- // inconsistent inzip files if needed.
- try {
- embeddedFiles().validate(*this);
- embeddedFiles().enable(params().embedded, *this, false);
- } catch (ExceptionMessage const & message) {
- Alert::error(message.title_, message.details_);
- Alert::warning(_("Failed to read embedded files"),
- _("Due to most likely a bug, LyX failed to locate all embedded "
- "file. If you unzip the LyX file, you should be able to see and "
- "open content.lyx which is your main text. You may also be able "
- "to recover some embedded files. Please report this bug to the "
- "lyx-devel mailing list."));
- return false;
- }
-
updateMacros();
updateMacroInstances();
return res;
// remove dummy empty par
paragraphs().clear();
- Lexer lex(0, 0);
+ Lexer lex;
istringstream is(s);
lex.setStream(is);
FileName const name = FileName::tempName();
bool Buffer::readFile(FileName const & filename)
{
FileName fname(filename);
- // Check if the file is compressed.
- string format = filename.guessFormatFromContents();
- if (format == "zip") {
- // decompress to a temp directory
- LYXERR(Debug::FILES, filename << " is in zip format. Unzip to " << temppath());
- ::unzipToDir(filename.toFilesystemEncoding(), temppath());
- //
- FileName lyxfile(addName(temppath(), "content.lyx"));
- // if both manifest.txt and file.lyx exist, this is am embedded file
- if (lyxfile.exists()) {
- // if in bundled format, save checksum of the compressed file, not content.lyx
- saveCheckSum(filename);
- params().embedded = true;
- fname = lyxfile;
- }
- }
- // The embedded lyx file can also be compressed, for backward compatibility
- format = fname.guessFormatFromContents();
- if (format == "gzip" || format == "zip" || format == "compress")
- params().compressed = true;
// remove dummy empty par
paragraphs().clear();
- Lexer lex(0, 0);
+ Lexer lex;
lex.setFile(fname);
if (readFile(lex, fname) != success)
return false;
Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename,
bool fromstring)
{
- BOOST_ASSERT(!filename.empty());
-
- if (!lex.isOK()) {
- Alert::error(_("Document could not be read"),
- bformat(_("%1$s could not be read."), from_utf8(filename.absFilename())));
- return failure;
- }
-
- lex.next();
- string const token = lex.getString();
-
- if (!lex) {
- Alert::error(_("Document could not be read"),
- bformat(_("%1$s could not be read."), from_utf8(filename.absFilename())));
- return failure;
- }
-
- // the first token _must_ be...
- if (token != "\\lyxformat") {
- lyxerr << "Token: " << token << endl;
+ LASSERT(!filename.empty(), /**/);
+ // the first (non-comment) token _must_ be...
+ if (!lex.checkFor("\\lyxformat")) {
Alert::error(_("Document format failure"),
- bformat(_("%1$s is not a LyX document."),
+ bformat(_("%1$s is not a readable LyX document."),
from_utf8(filename.absFilename())));
return failure;
}
- lex.next();
- string tmp_format = lex.getString();
+ string tmp_format;
+ lex >> tmp_format;
//lyxerr << "LyX Format: `" << tmp_format << '\'' << endl;
// if present remove ".," from string.
- string::size_type dot = tmp_format.find_first_of(".,");
+ size_t dot = tmp_format.find_first_of(".,");
//lyxerr << " dot found at " << dot << endl;
if (dot != string::npos)
tmp_format.erase(dot, 1);
bool retval = false;
- FileName content;
- if (params().embedded)
- // first write the .lyx file to the temporary directory
- content = FileName(addName(temppath(), "content.lyx"));
- else
- content = fname;
-
docstring const str = bformat(_("Saving document %1$s..."),
- makeDisplayPath(content.absFilename()));
+ makeDisplayPath(fname.absFilename()));
message(str);
if (params().compressed) {
- gz::ogzstream ofs(content.toFilesystemEncoding().c_str(), ios::out|ios::trunc);
+ gz::ogzstream ofs(fname.toFilesystemEncoding().c_str(), ios::out|ios::trunc);
retval = ofs && write(ofs);
} else {
- ofstream ofs(content.toFilesystemEncoding().c_str(), ios::out|ios::trunc);
+ ofstream ofs(fname.toFilesystemEncoding().c_str(), ios::out|ios::trunc);
retval = ofs && write(ofs);
}
removeAutosaveFile(d->filename.absFilename());
- if (params().embedded) {
- message(str + _(" writing embedded files."));
- // if embedding is enabled, write file.lyx and all the embedded files
- // to the zip file fname.
- if (!d->embedded_files.writeFile(fname, *this)) {
- message(str + _(" could not write embedded files!"));
- return false;
- }
- }
saveCheckSum(d->filename);
message(str + _(" done."));
if (it->lyxCode() == BIBTEX_CODE) {
InsetBibtex const & inset =
static_cast<InsetBibtex const &>(*it);
- EmbeddedFileList const bibfiles = inset.getBibFiles();
+ support::FileNameList const bibfiles = inset.getBibFiles();
d->bibfilesCache_.insert(d->bibfilesCache_.end(),
bibfiles.begin(),
bibfiles.end());
InsetInclude & inset =
static_cast<InsetInclude &>(*it);
inset.updateBibfilesCache();
- EmbeddedFileList const & bibfiles =
+ support::FileNameList const & bibfiles =
inset.getBibfilesCache(*this);
d->bibfilesCache_.insert(d->bibfilesCache_.end(),
bibfiles.begin(),
bibfiles.end());
}
}
+ // the bibinfo cache is now invalid
+ d->bibinfoCacheValid_ = false;
}
-EmbeddedFileList const & Buffer::getBibfilesCache() const
+void Buffer::invalidateBibinfoCache()
+{
+ d->bibinfoCacheValid_ = false;
+}
+
+
+support::FileNameList const & Buffer::getBibfilesCache() const
{
// If this is a child document, use the parent's cache instead.
if (d->parent_buffer)
}
+BiblioInfo const & Buffer::masterBibInfo() const
+{
+ // if this is a child document and the parent is already loaded
+ // use the parent's list instead [ale990412]
+ Buffer const * const tmp = masterBuffer();
+ LASSERT(tmp, /**/);
+ if (tmp != this)
+ return tmp->masterBibInfo();
+ return localBibInfo();
+}
+
+
+BiblioInfo const & Buffer::localBibInfo() const
+{
+ if (d->bibinfoCacheValid_) {
+ support::FileNameList const & bibfilesCache = getBibfilesCache();
+ // compare the cached timestamps with the actual ones.
+ support::FileNameList::const_iterator ei = bibfilesCache.begin();
+ support::FileNameList::const_iterator en = bibfilesCache.end();
+ for (; ei != en; ++ ei) {
+ time_t lastw = ei->lastModified();
+ if (lastw != d->bibfileStatus_[*ei]) {
+ d->bibinfoCacheValid_ = false;
+ d->bibfileStatus_[*ei] = lastw;
+ break;
+ }
+ }
+ }
+
+ if (!d->bibinfoCacheValid_) {
+ d->bibinfo_.clear();
+ for (InsetIterator it = inset_iterator_begin(inset()); it; ++it)
+ it->fillWithBibKeys(d->bibinfo_, it);
+ d->bibinfoCacheValid_ = true;
+ }
+ return d->bibinfo_;
+}
+
+
bool Buffer::isDepClean(string const & name) const
{
DepClean::const_iterator const it = d->dep_clean.find(name);
break;
}
+ case LFUN_BRANCH_ACTIVATE:
+ case LFUN_BRANCH_DEACTIVATE: {
+ BranchList & branchList = params().branchlist();
+ docstring const branchName = func.argument();
+ Branch * branch = branchList.find(branchName);
+ if (!branch)
+ LYXERR0("Branch " << branchName << " does not exist.");
+ else
+ branch->setSelected(func.action == LFUN_BRANCH_ACTIVATE);
+ if (result)
+ *result = true;
+ }
+
default:
dispatched = false;
}
void Buffer::changeLanguage(Language const * from, Language const * to)
{
- BOOST_ASSERT(from);
- BOOST_ASSERT(to);
+ LASSERT(from, /**/);
+ LASSERT(to, /**/);
for_each(par_iterator_begin(),
par_iterator_end(),
bool Buffer::isExternallyModified(CheckMethod method) const
{
- BOOST_ASSERT(d->filename.exists());
+ LASSERT(d->filename.exists(), /**/);
// if method == timestamp, check timestamp before checksum
return (method == checksum_method
|| d->timestamp_ != d->filename.lastModified())
InsetCode code)
{
//FIXME: This does not work for child documents yet.
- BOOST_ASSERT(code == CITE_CODE);
+ LASSERT(code == CITE_CODE, /**/);
// Check if the label 'from' appears more than once
vector<docstring> labels;
string paramName;
- BiblioInfo keys;
- keys.fillWithBibKeys(this);
+ BiblioInfo const & keys = masterBibInfo();
BiblioInfo::const_iterator bit = keys.begin();
BiblioInfo::const_iterator bend = keys.end();
}
}
+
} // namespace lyx