]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
Merge branch 'master' of git.lyx.org:lyx
[lyx.git] / src / Buffer.cpp
index d24342c09a34a73f768f8723ffdd50892a4ae8eb..12e3400f7c2ee402308bd17f9a81878e596c9a93 100644 (file)
 #include "support/types.h"
 
 #include "support/bind.h"
-#include "support/shared_ptr.h"
 
 #include <algorithm>
 #include <fstream>
 #include <iomanip>
 #include <map>
+#include <memory>
 #include <set>
 #include <sstream>
 #include <vector>
@@ -236,8 +236,8 @@ public:
        /// positions of child buffers in the buffer
        typedef map<Buffer const * const, DocIterator> BufferPositionMap;
        struct ScopeBuffer {
-               ScopeBuffer() {}
-               ScopeBuffer(DocIterator const & s,Buffer const * b)
+               ScopeBuffer() : buffer(0) {}
+               ScopeBuffer(DocIterator const & s, Buffer const * b)
                        : scope(s), buffer(b) {}
                DocIterator scope;
                Buffer const * buffer;
@@ -370,6 +370,10 @@ public:
                + (with_blanks ? blank_count_ : 0);
        }
 
+       // does the buffer contain tracked changes? (if so, we automatically
+       // display the review toolbar, for instance)
+       mutable bool tracked_changes_present_;
+
 private:
        /// So we can force access via the accessors.
        mutable Buffer const * parent_buffer;
@@ -442,6 +446,7 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
        preview_file_ = cloned_buffer_->d->preview_file_;
        preview_format_ = cloned_buffer_->d->preview_format_;
        preview_error_ = cloned_buffer_->d->preview_error_;
+       tracked_changes_present_ = cloned_buffer_->d->tracked_changes_present_;
 }
 
 
@@ -517,8 +522,12 @@ Buffer::~Buffer()
                Impl::BufferPositionMap::iterator end = d->children_positions.end();
                for (; it != end; ++it) {
                        Buffer * child = const_cast<Buffer *>(it->first);
-                       if (theBufferList().isLoaded(child))
-                               theBufferList().releaseChild(this, child);
+                       if (theBufferList().isLoaded(child)) { 
+                        if (theBufferList().isOthersChild(this, child))
+                                child->setParent(0);
+                        else
+                               theBufferList().release(child);
+                       }
                }
 
                if (!isClean()) {
@@ -1029,7 +1038,10 @@ bool Buffer::readDocument(Lexer & lex)
        params().indiceslist().addDefault(B_("Index"));
 
        // read main text
-       d->old_position = originFilePath();
+       if (FileName::isAbsolute(params().origin))
+               d->old_position = params().origin;
+       else
+               d->old_position = filePath();
        bool const res = text().read(lex, errorList, d->inset);
        d->old_position.clear();
 
@@ -1306,7 +1318,7 @@ Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn,
 }
 
 
-string Buffer::getBackupName() const {
+FileName Buffer::getBackupName() const {
        FileName const & fn = fileName();
        string const fname = fn.onlyFileNameWithoutExt();
        string const fext  = fn.extension();
@@ -1314,7 +1326,7 @@ string Buffer::getBackupName() const {
                fn.onlyPath().absFileName() :
                lyxrc.backupdir_path;
        string const fform = convert<string>(d->file_format);
-       string const backname = fname + "-" + fform;
+       string const backname = fname + "-lyxformat-" + fform;
        FileName backup(addName(fpath, addExtension(backname, fext)));
 
        // limit recursion, just in case
@@ -1333,11 +1345,11 @@ string Buffer::getBackupName() const {
                        v = 1000;
                        break;
                }
-               string newbackname = backname + "-" + convert<string>(v);
+               string const newbackname = backname + "-" + convert<string>(v);
                backup.set(addName(fpath, addExtension(newbackname, fext)));
                v++;
        }
-       return v < 100 ? backup.onlyFileName() : "";
+       return v < 100 ? backup : FileName();
 }
 
 
@@ -1385,9 +1397,8 @@ bool Buffer::save() const
        // proper location once that has been done successfully. that
        // way we preserve the original file if something goes wrong.
        string const justname = fileName().onlyFileNameWithoutExt();
-       boost::scoped_ptr<TempFile>
-               tempfile(new TempFile(fileName().onlyPath(),
-                  justname + "-XXXXXX.lyx"));
+       auto tempfile = make_unique<TempFile>(fileName().onlyPath(),
+                                             justname + "-XXXXXX.lyx");
        bool const symlink = fileName().isSymLink();
        if (!symlink)
                tempfile->setAutoRemove(false);
@@ -1401,12 +1412,10 @@ bool Buffer::save() const
        bool made_backup = true;
 
        FileName backupName;
-       if (lyxrc.make_backup || d->need_format_backup) {
-               if (d->need_format_backup) {
-                       string backup_name = getBackupName();
-                       if (!backup_name.empty())
-                               backupName.set(backup_name);
-               }
+       bool const needBackup = lyxrc.make_backup || d->need_format_backup;
+       if (needBackup) {
+               if (d->need_format_backup)
+                       backupName = getBackupName();
 
                // If we for some reason failed to find a backup name in case of
                // a format change, this will still set one. It's the best we can
@@ -1461,8 +1470,8 @@ bool Buffer::save() const
        }
        // else we saved the file, but failed to move it to the right location.
 
-       if (lyxrc.make_backup && made_backup && !symlink) {
-               // the original file was moved to filename.lyx~, so it will look
+       if (needBackup && made_backup && !symlink) {
+               // the original file was moved to some new location, so it will look
                // to the user as if it was deleted. (see bug #9234.) we could try
                // to restore it, but that would basically mean trying to do again
                // what we just failed to do. better to leave things as they are.
@@ -1650,9 +1659,11 @@ bool Buffer::makeLaTeXFile(FileName const & fname,
 {
        OutputParams runparams = runparams_in;
 
-       // XeTeX with TeX fonts is only safe with ASCII encoding,
-       // but the "flavor" is not known in BufferParams::encoding().
-       if (!params().useNonTeXFonts && (runparams.flavor == OutputParams::XETEX))
+       // XeTeX with TeX fonts is only safe with ASCII encoding (see also #9740),
+       // Check here, because the "flavor" is not known in BufferParams::encoding()
+       // (power users can override this safety measure selecting "utf8-plain").
+       if (!params().useNonTeXFonts && (runparams.flavor == OutputParams::XETEX)
+           && (runparams.encoding->name() != "utf8-plain"))
                runparams.encoding = encodings.fromLyXName("ascii");
 
        string const encoding = runparams.encoding->iconvName();
@@ -1738,8 +1749,10 @@ void Buffer::writeLaTeXSource(otexstream & os,
        OutputParams runparams = runparams_in;
 
        // XeTeX with TeX fonts is only safe with ASCII encoding,
-       // but the "flavor" is not known in BufferParams::encoding().
-       if (!params().useNonTeXFonts && (runparams.flavor == OutputParams::XETEX))
+       // Check here, because the "flavor" is not known in BufferParams::encoding()
+       // (power users can override this safety measure selecting "utf8-plain").
+       if (!params().useNonTeXFonts && (runparams.flavor == OutputParams::XETEX)
+           && (runparams.encoding->name() != "utf8-plain"))
                runparams.encoding = encodings.fromLyXName("ascii");
        // FIXME: when only the current paragraph is shown, this is ignored
        //        (or not reached) and characters encodable in the current
@@ -2224,8 +2237,8 @@ void Buffer::getLabelList(vector<docstring> & list) const
 
        list.clear();
        shared_ptr<Toc> toc = d->toc_backend.toc("label");
-       TocIterator toc_it = toc->begin();
-       TocIterator end = toc->end();
+       Toc::const_iterator toc_it = toc->begin();
+       Toc::const_iterator end = toc->end();
        for (; toc_it != end; ++toc_it) {
                if (toc_it->depth() == 0)
                        list.push_back(toc_it->str());
@@ -2760,12 +2773,16 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                break;
 
        case LFUN_CHANGES_TRACK:
-               undo().recordUndoBufferParams(CursorData());
+               if (params().save_transient_properties)
+                       undo().recordUndoBufferParams(CursorData());
                params().track_changes = !params().track_changes;
+               if (!params().track_changes)
+                       dr.forceChangesUpdate();
                break;
 
        case LFUN_CHANGES_OUTPUT:
-               undo().recordUndoBufferParams(CursorData());
+               if (params().save_transient_properties)
+                       undo().recordUndoBufferParams(CursorData());
                params().output_changes = !params().output_changes;
                if (params().output_changes) {
                        bool dvipost    = LaTeXFeatures::isAvailable("dvipost");
@@ -3027,12 +3044,21 @@ string Buffer::filePath() const
 }
 
 
-string Buffer::originFilePath() const
+DocFileName Buffer::getReferencedFileName(string const & fn) const
 {
-       if (FileName::isAbsolute(params().origin))
-               return params().origin;
+       DocFileName result;
+       if (FileName::isAbsolute(fn) || !FileName::isAbsolute(params().origin))
+               result.set(fn, filePath());
+       else {
+               // filePath() ends with a path separator
+               FileName const test(filePath() + fn);
+               if (test.exists())
+                       result.set(fn, filePath());
+               else
+                       result.set(fn, params().origin);
+       }
 
-       return filePath();
+       return result;
 }
 
 
@@ -3631,11 +3657,11 @@ void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to)
 }
 
 // returns NULL if id-to-row conversion is unsupported
-auto_ptr<TexRow> Buffer::getSourceCode(odocstream & os, string const & format,
-                          pit_type par_begin, pit_type par_end,
-                          OutputWhat output, bool master) const
+unique_ptr<TexRow> Buffer::getSourceCode(odocstream & os, string const & format,
+                                         pit_type par_begin, pit_type par_end,
+                                         OutputWhat output, bool master) const
 {
-       auto_ptr<TexRow> texrow(NULL);
+       unique_ptr<TexRow> texrow;
        OutputParams runparams(&params().encoding());
        runparams.nice = true;
        runparams.flavor = params().getOutputFlavor(format);
@@ -3689,7 +3715,7 @@ auto_ptr<TexRow> Buffer::getSourceCode(odocstream & os, string const & format,
                        LaTeXFeatures features(*this, params(), runparams);
                        params().validate(features);
                        runparams.use_polyglossia = features.usePolyglossia();
-                       texrow.reset(new TexRow());
+                       texrow = make_unique<TexRow>();
                        texrow->newline();
                        texrow->newline();
                        // latex or literate
@@ -3732,7 +3758,7 @@ auto_ptr<TexRow> Buffer::getSourceCode(odocstream & os, string const & format,
                                writeDocBookSource(os, absFileName(), runparams, output);
                } else {
                        // latex or literate
-                       texrow.reset(new TexRow());
+                       texrow = make_unique<TexRow>();
                        texrow->newline();
                        texrow->newline();
                        otexstream ots(os, *texrow);
@@ -3825,7 +3851,7 @@ public:
        ///
        virtual shared_ptr<ForkedProcess> clone() const
        {
-               return shared_ptr<ForkedProcess>(new AutoSaveBuffer(*this));
+               return make_shared<AutoSaveBuffer>(*this);
        }
        ///
        int start()
@@ -4568,6 +4594,7 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const
        // update all caches
        clearReferenceCache();
        updateMacros();
+       setChangesPresent(false);
 
        Buffer & cbuf = const_cast<Buffer &>(*this);
 
@@ -4595,6 +4622,11 @@ static depth_type getDepth(DocIterator const & it)
                if (!it[i].inset().inMathed())
                        depth += it[i].paragraph().getDepth() + 1;
        // remove 1 since the outer inset does not count
+       // we should have at least one non-math inset, so
+       // depth should nevery be 0. but maybe it is worth
+       // marking this, just in case.
+       LATTEST(depth > 0);
+       // coverity[INTEGER_OVERFLOW]
        return depth - 1;
 }
 
@@ -4831,6 +4863,9 @@ void Buffer::updateBuffer(ParIterator & parit, UpdateType utype) const
                // set the counter for this paragraph
                d->setLabel(parit, utype);
 
+               // update change-tracking flag 
+               parit->addChangesToBuffer(*this);
+
                // now the insets
                InsetList::const_iterator iit = parit->insetList().begin();
                InsetList::const_iterator end = parit->insetList().end();
@@ -5069,13 +5104,23 @@ void Buffer::checkMasterBuffer()
 
 string Buffer::includedFilePath(string const & name, string const & ext) const
 {
+       if (d->old_position.empty() ||
+           equivalent(FileName(d->old_position), FileName(filePath())))
+               return name;
+
        bool isabsolute = FileName::isAbsolute(name);
-       // old_position already contains a trailing path separator
-       string const absname = isabsolute ? name : d->old_position + name;
+       // both old_position and filePath() end with a path separator
+       string absname = isabsolute ? name : d->old_position + name;
 
-       if (d->old_position.empty()
-           || equivalent(FileName(d->old_position), FileName(filePath()))
-           || !FileName(addExtension(absname, ext)).exists())
+       // if old_position is set to origin, we need to do the equivalent of
+       // getReferencedFileName() (see readDocument())
+       if (!isabsolute && d->old_position == params().origin) {
+               FileName const test(addExtension(filePath() + name, ext));
+               if (test.exists())
+                       absname = filePath() + name;
+       }
+
+       if (!FileName(addExtension(absname, ext)).exists())
                return name;
 
        if (isabsolute)
@@ -5085,4 +5130,29 @@ string Buffer::includedFilePath(string const & name, string const & ext) const
                                   from_utf8(filePath())));
 }
 
+
+void Buffer::setChangesPresent(bool b) const
+{
+       d->tracked_changes_present_ = b;
+}
+
+
+bool Buffer::areChangesPresent() const
+{
+       return d->tracked_changes_present_;
+}
+
+
+void Buffer::updateChangesPresent() const
+{
+       LYXERR(Debug::CHANGES, "Buffer::updateChangesPresent");
+       setChangesPresent(false);
+       ParConstIterator it = par_iterator_begin();
+       ParConstIterator const end = par_iterator_end();
+       for (; !areChangesPresent() && it != end; ++it)
+               it->addChangesToBuffer(*this);
+}
+
+
+
 } // namespace lyx