#include "debug.h"
#include "gettext.h"
#include "Format.h"
+#include "Lexer.h"
+#include "ErrorList.h"
#include "frontends/alert.h"
#include <boost/filesystem/operations.hpp>
#include "support/filetools.h"
-#include "support/fs_extras.h"
#include "support/convert.h"
#include "support/lyxlib.h"
#include "support/lstrings.h"
using support::DocFileName;
using support::makeAbsPath;
using support::addName;
-using support::onlyPath;
using support::absolutePath;
using support::onlyFilename;
using support::makeRelPath;
EmbeddedFile::EmbeddedFile(string const & file, string const & inzip_name,
bool embed, Inset const * inset)
: DocFileName(file, true), inzip_name_(inzip_name), embedded_(embed),
- valid_(true), inset_list_()
+ inset_list_()
{
if (inset != NULL)
inset_list_.push_back(inset);
if (&(*it) == ptr) {
// this is basically BufferView::saveBookmark(0)
LyX::ref().session().bookmarks().save(
- FileName(buf->fileName()),
+ FileName(buf->absFileName()),
it.bottom().pit(),
it.bottom().pos(),
it.paragraph().id(),
string EmbeddedFile::availableFile(Buffer const * buf) const
{
- if (embedded())
- return embeddedFile(buf);
- else
- return absFilename();
-}
-
-
-void EmbeddedFile::invalidate()
-{
- // Clear inset_list_ because they will be registered again.
- inset_list_.clear();
- valid_ = false;
+ return embedded() ? embeddedFile(buf) : absFilename();
}
bool EmbeddedFile::extract(Buffer const * buf) const
{
-
string ext_file = absFilename();
string emb_file = embeddedFile(buf);
return true;
}
// copy file
- try {
- // need to make directory?
- string path = onlyPath(ext_file);
- if (!fs::is_directory(path))
- makedir(const_cast<char*>(path.c_str()), 0755);
- fs::copy_file(emb_file, ext_file, false);
+
+ // need to make directory?
+ string path = support::onlyPath(ext_file);
+ if (!fs::is_directory(path))
+ makedir(const_cast<char*>(path.c_str()), 0755);
+ FileName emb(emb_file);
+ FileName ext(ext_file);
+ if (emb.copyTo(ext, false))
return true;
- } catch (fs::filesystem_error const & fe) {
- Alert::error(_("Copy file failure"),
- bformat(_("Cannot copy file %1$s to %2$s.\n"
- "Please check whether the directory exists and is writeable."),
- from_utf8(emb_file), from_utf8(ext_file)));
- LYXERR(Debug::DEBUG) << "Fs error: " << fe.what() << endl;
- }
+ Alert::error(_("Copy file failure"),
+ bformat(_("Cannot copy file %1$s to %2$s.\n"
+ "Please check whether the directory exists and is writeable."),
+ from_utf8(emb_file), from_utf8(ext_file)));
+ //LYXERR(Debug::DEBUG) << "Fs error: " << fe.what() << endl;
return false;
}
// other wise, ask if overwrite
int const ret = Alert::prompt(
_("Update embedded file?"),
- bformat(_("Embeddedl file %1$s already exists, do you want to overwrite it"),
+ bformat(_("Embedded file %1$s already exists, do you want to overwrite it"),
from_utf8(ext_file)), 1, 1, _("&Overwrite"), _("&Cancel"));
if (ret != 0)
// if the user does not want to overwrite, we still consider it
return true;
}
// copy file
- try {
- // need to make directory?
- string path = onlyPath(emb_file);
- if (!fs::is_directory(path))
- makedir(const_cast<char*>(path.c_str()), 0755);
- fs::copy_file(ext_file, emb_file, false);
+ FileName emb(emb_file);
+ FileName ext(ext_file);
+ // need to make directory?
+ string path = support::onlyPath(emb_file);
+ if (!fs::is_directory(path))
+ makedir(const_cast<char*>(path.c_str()), 0755);
+ if (ext.copyTo(emb, false))
return true;
- } catch (fs::filesystem_error const & fe) {
- Alert::error(_("Copy file failure"),
- bformat(_("Cannot copy file %1$s to %2$s.\n"
- "Please check whether the directory exists and is writeable."),
- from_utf8(ext_file), from_utf8(emb_file)));
- LYXERR(Debug::DEBUG) << "Fs error: " << fe.what() << endl;
- }
+ Alert::error(_("Copy file failure"),
+ bformat(_("Cannot copy file %1$s to %2$s.\n"
+ "Please check whether the directory exists and is writeable."),
+ from_utf8(ext_file), from_utf8(emb_file)));
+ //LYXERR(Debug::DEBUG) << "Fs error: " << fe.what() << endl;
return false;
}
+void EmbeddedFile::updateInsets(Buffer const * buf) const
+{
+ vector<Inset const *>::const_iterator it = inset_list_.begin();
+ vector<Inset const *>::const_iterator it_end = inset_list_.end();
+ for (; it != it_end; ++it)
+ const_cast<Inset *>(*it)->updateEmbeddedFile(*buf, *this);
+}
+
+
bool EmbeddedFiles::enabled() const
{
return buffer_->params().embedded;
}
-bool EmbeddedFiles::enable(bool flag)
+void EmbeddedFiles::enable(bool flag)
{
if (enabled() != flag) {
// if enable, copy all files to temppath()
// if disable, extract all files
if ((flag && !updateFromExternalFile()) || (!flag && !extract()))
- return false;
+ return;
// if operation is successful
buffer_->markDirty();
buffer_->params().embedded = flag;
+ if (flag)
+ updateInsets();
}
}
-void EmbeddedFiles::registerFile(string const & filename,
- bool embed, Inset const * inset)
+EmbeddedFile & EmbeddedFiles::registerFile(string const & filename,
+ bool embed, Inset const * inset, string const & inzipName)
{
// filename can be relative or absolute, translate to absolute filename
string abs_filename = makeAbsPath(filename, buffer_->filePath()).absFilename();
// find this filename, keep the original embedding status
if (it != file_list_.end()) {
it->addInset(inset);
- // if the file is embedded, the embedded file should have exist
- // check for this to ensure that our logic is correct
- if (it->embedded())
- BOOST_ASSERT(fs::exists(it->embeddedFile(buffer_)));
- it->validate();
- return;
+ return *it;
}
- // try to be more careful
+ //
file_list_.push_back(EmbeddedFile(abs_filename,
- getInzipName(abs_filename), embed, inset));
- // validate if things are OK
- BOOST_ASSERT(fs::exists(file_list_.back().availableFile(buffer_)));
+ getInzipName(abs_filename, inzipName), embed, inset));
+ return file_list_.back();
}
void EmbeddedFiles::update()
{
- // invalidate all files, obsolete files will then not be validated by the
- // following document scan. These files will still be kept though, because
- // they may be added later and their embedding status will be meaningful
- // again (thinking of cut/paste of an InsetInclude).
- EmbeddedFileList::iterator it = file_list_.begin();
- EmbeddedFileList::iterator it_end = file_list_.end();
- for (; it != it_end; ++it)
- // we do not update items that are manually inserted
- if (it->refCount() > 0)
- it->invalidate();
+ file_list_.clear();
for (InsetIterator it = inset_iterator_begin(buffer_->inset()); it; ++it)
it->registerEmbeddedFiles(*buffer_, *this);
-
- LYXERR(Debug::FILES) << "Manifest updated: " << endl
- << *this
- << "End Manifest" << endl;
}
-bool EmbeddedFiles::write(DocFileName const & filename)
+bool EmbeddedFiles::writeFile(DocFileName const & filename)
{
// file in the temporary path has the content
string const content = FileName(addName(buffer_->temppath(),
- onlyFilename(filename.toFilesystemEncoding()))).toFilesystemEncoding();
+ "content.lyx")).toFilesystemEncoding();
- // get a file list and write a manifest file
vector<pair<string, string> > filenames;
- string const manifest = FileName(
- addName(buffer_->temppath(), "manifest.txt")).toFilesystemEncoding();
-
- // write a manifest file
- ofstream os(manifest.c_str());
- os << *this;
- os.close();
+ // add content.lyx to filenames
+ filenames.push_back(make_pair(content, "content.lyx"));
// prepare list of embedded file
EmbeddedFileList::iterator it = file_list_.begin();
EmbeddedFileList::iterator it_end = file_list_.end();
for (; it != it_end; ++it) {
- if (it->valid() && it->embedded()) {
+ if (it->embedded()) {
string file = it->availableFile(buffer_);
if (file.empty())
lyxerr << "File " << it->absFilename() << " does not exist. Skip embedding it. " << endl;
filenames.push_back(make_pair(file, it->inzipName()));
}
}
- // add filename (.lyx) and manifest to filenames
- filenames.push_back(make_pair(content, onlyFilename(filename.toFilesystemEncoding())));
- filenames.push_back(make_pair(manifest, "manifest.txt"));
// write a zip file with all these files. Write to a temp file first, to
// avoid messing up the original file in case something goes terribly wrong.
DocFileName zipfile(addName(buffer_->temppath(),
::zipFiles(zipfile.toFilesystemEncoding(), filenames);
// copy file back
- try {
- fs::copy_file(zipfile.toFilesystemEncoding(), filename.toFilesystemEncoding(), false);
- } catch (fs::filesystem_error const & fe) {
+ if (!zipfile.copyTo(filename, false)) {
Alert::error(_("Save failure"),
bformat(_("Cannot create file %1$s.\n"
"Please check whether the directory exists and is writeable."),
from_utf8(filename.absFilename())));
- LYXERR(Debug::DEBUG) << "Fs error: " << fe.what() << endl;
+ //LYXERR(Debug::DEBUG) << "Fs error: " << fe.what() << endl;
}
return true;
}
-EmbeddedFiles::EmbeddedFileList::const_iterator EmbeddedFiles::find(std::string filename) const
+EmbeddedFiles::EmbeddedFileList::const_iterator
+EmbeddedFiles::find(std::string filename) const
{
EmbeddedFileList::const_iterator it = file_list_.begin();
EmbeddedFileList::const_iterator it_end = file_list_.end();
EmbeddedFileList::const_iterator it = file_list_.begin();
EmbeddedFileList::const_iterator it_end = file_list_.end();
for (; it != it_end; ++it)
- if (it->valid() && it->embedded())
+ if (it->embedded())
if(!it->extract(buffer_))
return false;
return true;
EmbeddedFileList::const_iterator it = file_list_.begin();
EmbeddedFileList::const_iterator it_end = file_list_.end();
for (; it != it_end; ++it)
- if (it->valid() && it->embedded())
+ if (it->embedded())
if (!it->updateFromExternalFile(buffer_))
return false;
return true;
}
-string const EmbeddedFiles::getInzipName(string const & abs_filename)
+string const EmbeddedFiles::getInzipName(string const & abs_filename, string const & name)
{
// register a new one, using relative file path as inzip_name
- string inzip_name = to_utf8(makeRelPath(from_utf8(abs_filename),
- from_utf8(buffer_->fileName())));
+ string inzip_name = name;
+ if (name.empty())
+ inzip_name = to_utf8(makeRelPath(from_utf8(abs_filename),
+ from_utf8(buffer_->filePath())));
// if inzip_name is an absolute path, use filename only to avoid
// leaking of filesystem information in inzip_name
// The second case covers cases '../path/file' and '.'
}
-istream & operator>> (istream & is, EmbeddedFiles & files)
+void EmbeddedFiles::updateInsets() const
{
- files.clear();
- string tmp;
- getline(is, tmp);
- // get version
- istringstream itmp(tmp);
- int version;
- itmp.ignore(string("# LyX manifest version ").size());
- itmp >> version;
-
- if (version != 1) {
- lyxerr << "This version of LyX can only read LyX manifest version 1" << endl;
- return is;
- }
-
- getline(is, tmp);
- if (tmp != "<manifest>") {
- lyxerr << "Invalid manifest file, lacking <manifest>" << endl;
- return is;
- }
- // manifest file may be messed up, be carefully
- while (is.good()) {
- getline(is, tmp);
- if (tmp != "<file>")
- break;
-
- string fname;
- getline(is, fname);
- string inzip_name;
- getline(is, inzip_name);
- getline(is, tmp);
- istringstream itmp(tmp);
- int embed;
- itmp >> embed;
-
- getline(is, tmp);
- if (tmp != "</file>") {
- lyxerr << "Invalid manifest file, lacking </file>" << endl;
- break;
- }
-
- files.registerFile(fname, embed);
- };
- // the last line must be </manifest>
- if (tmp != "</manifest>") {
- lyxerr << "Invalid manifest file, lacking </manifest>" << endl;
- return is;
- }
- return is;
+ EmbeddedFiles::EmbeddedFileList::const_iterator it = begin();
+ EmbeddedFiles::EmbeddedFileList::const_iterator it_end = end();
+ for (; it != it_end; ++it)
+ if (it->refCount() > 0)
+ it->updateInsets(buffer_);
}
-ostream & operator<< (ostream & os, EmbeddedFiles const & files)
-{
- // store a version so that operator >> can read later versions
- // using version information.
- os << "# lyx manifest version 1\n";
- os << "<manifest>\n";
- EmbeddedFiles::EmbeddedFileList::const_iterator it = files.begin();
- EmbeddedFiles::EmbeddedFileList::const_iterator it_end = files.end();
- for (; it != it_end; ++it) {
- if (!it->valid())
- continue;
- // use differnt lines to make reading easier.
- os << "<file>\n"
- // save the relative path
- << to_utf8(makeRelPath(from_utf8(it->absFilename()),
- from_utf8(files.buffer_->filePath()))) << '\n'
- << it->inzipName() << '\n'
- << it->embedded() << '\n'
- << "</file>\n";
- }
- os << "</manifest>\n";
- return os;
-}
-
}