commit 4543bf288d0839f5a9bb93e76928d5cb061ea7dd
Author: Enrico Forestieri <[email protected]>
Date: Mon May 4 03:11:30 2015 +0200
Update paths of included files when saving to a different folder.
Fixes #9528 and #5115.
diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index d47abd9..52212e8 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -237,6 +237,9 @@ public:
/// map from children inclusion positions to their scope and their
buffer
PositionScopeBufferMap position_to_children;
+ /// Keeps track of old buffer filePath() for save-as operations
+ string old_position;
+
/// Container for all sort of Buffer dependant errors.
map<string, ErrorList> errorLists;
@@ -4866,6 +4869,8 @@ bool Buffer::saveAs(FileName const & fn)
FileName const old_name = fileName();
FileName const old_auto = getAutosaveFileName();
bool const old_unnamed = isUnnamed();
+ bool success = true;
+ d->old_position = filePath();
setFileName(fn);
markDirty();
@@ -4883,22 +4888,19 @@ bool Buffer::saveAs(FileName const & fn)
// are still valid.
checkChildBuffers();
checkMasterBuffer();
- return true;
} else {
// save failed
// reset the old filename and unnamed state
setFileName(old_name);
setUnnamed(old_unnamed);
- return false;
+ success = false;
}
+
+ d->old_position.clear();
+ return success;
}
-// FIXME We could do better here, but it is complicated. What would be
-// nice is to offer either (a) to save the child buffer to an appropriate
-// location, so that it would "move with the master", or else (b) to update
-// the InsetInclude so that it pointed to the same file. But (a) is a bit
-// complicated, because the code for this lives in GuiView.
void Buffer::checkChildBuffers()
{
Impl::BufferPositionMap::iterator it = d->children_positions.begin();
@@ -4918,11 +4920,6 @@ void Buffer::checkChildBuffers()
if (oldloc == newloc)
continue;
// the location of the child file is incorrect.
- Alert::warning(_("Included File Invalid"),
- bformat(_("Saving this document to a new
location has made the file:\n"
- " %1$s\n"
- "inaccessible. You will need to update the
included filename."),
- from_utf8(oldloc)));
cbuf->setParent(0);
inset_inc->setChildBuffer(0);
}
@@ -4952,4 +4949,18 @@ void Buffer::checkMasterBuffer()
setParent(0);
}
+
+string Buffer::includedFilePath(string const & name) const
+{
+ if (d->old_position.empty() || d->old_position == filePath())
+ return name;
+
+ if (FileName::isAbsolute(name))
+ return to_utf8(makeRelPath(from_utf8(name),
from_utf8(filePath())));
+
+ // old_position already contains a trailing path separator
+ string const cleanpath = FileName(d->old_position + name).realPath();
+ return to_utf8(makeRelPath(from_utf8(cleanpath),
from_utf8(filePath())));
+}
+
} // namespace lyx
diff --git a/src/Buffer.h b/src/Buffer.h
index fe0294b..e855c20 100644
--- a/src/Buffer.h
+++ b/src/Buffer.h
@@ -707,6 +707,12 @@ public:
///
void checkMasterBuffer();
+ /// If the document is being saved to a new location, return the
+ /// updated path of an included file relative to the new buffer path
+ /// if possible, otherwise return its absolute path.
+ /// In all other cases, this is a no-op and name is returned unchanged.
+ std::string includedFilePath(std::string const & name) const;
+
/// compute statistics between \p from and \p to
/// \p from initial position
/// \p to points to the end position
diff --git a/src/insets/InsetBibtex.cpp b/src/insets/InsetBibtex.cpp
index c925bfe..eb0cf8f 100644
--- a/src/insets/InsetBibtex.cpp
+++ b/src/insets/InsetBibtex.cpp
@@ -1025,6 +1025,12 @@ docstring InsetBibtex::xhtml(XHTMLStream & xs,
OutputParams const &) const
}
+void InsetBibtex::write(ostream & os) const
+{
+ params().Write(os, &buffer());
+}
+
+
string InsetBibtex::contextMenuName() const
{
return "context-bibtex";
diff --git a/src/insets/InsetBibtex.h b/src/insets/InsetBibtex.h
index 8c4fa18..a4310ad 100644
--- a/src/insets/InsetBibtex.h
+++ b/src/insets/InsetBibtex.h
@@ -38,6 +38,8 @@ public:
bool addDatabase(docstring const &);
///
bool delDatabase(docstring const &);
+ ///
+ void write(std::ostream &) const;
/// \name Public functions inherited from Inset class
//@{
diff --git a/src/insets/InsetCommandParams.cpp
b/src/insets/InsetCommandParams.cpp
index af04f83..519e937 100644
--- a/src/insets/InsetCommandParams.cpp
+++ b/src/insets/InsetCommandParams.cpp
@@ -28,6 +28,7 @@
#include "InsetRef.h"
#include "InsetTOC.h"
+#include "Buffer.h"
#include "Encoding.h"
#include "Lexer.h"
#include "OutputParams.h"
@@ -321,6 +322,12 @@ void InsetCommandParams::read(Lexer & lex)
void InsetCommandParams::write(ostream & os) const
{
+ Write(os, 0);
+}
+
+
+void InsetCommandParams::Write(ostream & os, Buffer const * buffer) const
+{
os << "CommandInset " << insetType() << '\n';
os << "LatexCommand " << cmdName_ << '\n';
if (preview_)
@@ -328,12 +335,27 @@ void InsetCommandParams::write(ostream & os) const
ParamInfo::const_iterator it = info_.begin();
ParamInfo::const_iterator end = info_.end();
for (; it != end; ++it) {
- std::string const & name = it->name();
- docstring const & data = (*this)[name];
+ string const & name = it->name();
+ string data = to_utf8((*this)[name]);
if (!data.empty()) {
- // FIXME UNICODE
+ // Adjust path of files if document was moved
+ if (buffer && name == "filename") {
+ data = buffer->includedFilePath(data);
+ } else if (buffer && name == "bibfiles") {
+ int i = 0;
+ string newdata;
+ string bib = token(data, ',', i);
+ while (!bib.empty()) {
+ bib = buffer->includedFilePath(bib);
+ if (!newdata.empty())
+ newdata.append(1, ',');
+ newdata.append(bib);
+ bib = token(data, ',', ++i);
+ }
+ data = newdata;
+ }
os << name << ' '
- << Lexer::quoteString(to_utf8(data))
+ << Lexer::quoteString(data)
<< '\n';
}
}
diff --git a/src/insets/InsetCommandParams.h b/src/insets/InsetCommandParams.h
index a5d4678..52f79ba 100644
--- a/src/insets/InsetCommandParams.h
+++ b/src/insets/InsetCommandParams.h
@@ -28,6 +28,7 @@
namespace lyx {
class Lexer;
+class Buffer;
class ParamInfo {
public:
@@ -117,6 +118,8 @@ public:
/// Parse the command
///
void write(std::ostream &) const;
+ ///
+ void Write(std::ostream & os, Buffer const * buf) const;
/// Build the complete LaTeX command
docstring getCommand(OutputParams const &) const;
/// Return the command name
diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp
index e3960c4..5f99944 100644
--- a/src/insets/InsetInclude.cpp
+++ b/src/insets/InsetInclude.cpp
@@ -1030,6 +1030,12 @@ void InsetInclude::draw(PainterInfo & pi, int x, int y)
const
}
+void InsetInclude::write(ostream & os) const
+{
+ params().Write(os, &buffer());
+}
+
+
string InsetInclude::contextMenuName() const
{
return "context-include";
diff --git a/src/insets/InsetInclude.h b/src/insets/InsetInclude.h
index 3e28346..bee2089 100644
--- a/src/insets/InsetInclude.h
+++ b/src/insets/InsetInclude.h
@@ -64,6 +64,8 @@ public:
///
void updateCommand();
+ ///
+ void write(std::ostream &) const;
/// \name Public functions inherited from Inset class
//@{
diff --git a/status.21x b/status.21x
index 1f13747..6688024 100644
--- a/status.21x
+++ b/status.21x
@@ -82,6 +82,9 @@ What's new
* DOCUMENT INPUT/OUTPUT
+- Update path of included files when saving a document to a different
+ location (bugs 9528, 5115).
+
- Fix LaTeX errors caused by too late loading of fixltx2e package
(bugs 9452, 9361).