]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
xyfigure.png: update the screenshot
[lyx.git] / src / Buffer.cpp
index 9eded216f1f32daa5203f5344a3b75ba3cf29bc9..ffe522e0f9845a7838526037969df4aedc4856bf 100644 (file)
@@ -55,6 +55,7 @@
 #include "ParagraphParameters.h"
 #include "ParIterator.h"
 #include "PDFOptions.h"
+#include "Session.h"
 #include "SpellChecker.h"
 #include "sgml.h"
 #include "texstream.h"
@@ -76,7 +77,7 @@
 
 #include "mathed/InsetMathHull.h"
 #include "mathed/MacroTable.h"
-#include "mathed/MathMacroTemplate.h"
+#include "mathed/InsetMathMacroTemplate.h"
 #include "mathed/MathSupport.h"
 
 #include "graphics/GraphicsCache.h"
@@ -136,7 +137,7 @@ int const LYX_FORMAT = LYX_FORMAT_LYX;
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
 
-} // namespace anon
+} // namespace
 
 
 // A storehouse for the cloned buffers.
@@ -379,14 +380,11 @@ public:
        // Make sure the file monitor monitors the good file.
        void refreshFileMonitor();
 
-       /// has it been notified of an external modification?
-       bool isExternallyModified() const { return externally_modified_; }
-
        /// Notify or clear of external modification
-       void fileExternallyModified(bool modified) const;
+       void fileExternallyModified(bool exists);
 
-       /// Block notifications of external modifications
-       FileMonitorBlocker blockFileMonitor() { return file_monitor_->block(); }
+       /// has been externally modified? Can be reset by the user.
+       mutable bool externally_modified_;
 
 private:
        /// So we can force access via the accessors.
@@ -396,9 +394,6 @@ private:
        int char_count_;
        int blank_count_;
 
-       /// has been externally modified? Can be reset by the user.
-       mutable bool externally_modified_;
-
        FileMonitorPtr file_monitor_;
 };
 
@@ -440,9 +435,8 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
          bibfile_cache_valid_(false), cite_labels_valid_(false), preview_error_(false),
          inset(0), preview_loader_(0), cloned_buffer_(cloned_buffer),
          clone_list_(0), doing_export(false),
-         tracked_changes_present_(0), parent_buffer(0),
-         word_count_(0), char_count_(0), blank_count_(0),
-         externally_modified_(false)
+         tracked_changes_present_(0), externally_modified_(false), parent_buffer(0),
+         word_count_(0), char_count_(0), blank_count_(0)
 {
        refreshFileMonitor();
        if (!cloned_buffer_) {
@@ -543,11 +537,11 @@ 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)) { 
-                        if (theBufferList().isOthersChild(this, child))
-                                child->setParent(0);
-                        else
-                               theBufferList().release(child);
+                       if (theBufferList().isLoaded(child)) {
+                               if (theBufferList().isOthersChild(this, child))
+                                       child->setParent(0);
+                               else
+                                       theBufferList().release(child);
                        }
                }
 
@@ -987,6 +981,8 @@ int Buffer::readHeader(Lexer & lex)
                errorList.push_back(ErrorItem(_("Document header error"), s));
        }
 
+       params().shell_escape = theSession().shellescapeFiles().find(absFileName());
+
        params().makeDocumentClass();
 
        return unknown_tokens;
@@ -1383,7 +1379,6 @@ FileName Buffer::getBackupName() const {
 // Should probably be moved to somewhere else: BufferView? GuiView?
 bool Buffer::save() const
 {
-       FileMonitorBlocker block = d->blockFileMonitor();
        docstring const file = makeDisplayPath(absFileName(), 20);
        d->filename.refresh();
 
@@ -1942,7 +1937,7 @@ void Buffer::writeLaTeXSource(otexstream & os,
                                            support::bformat(_("The languages %1$s are only supported by Polyglossia."), langs)
                                          : support::bformat(_("The language %1$s is only supported by Polyglossia."), langs);
                                if (!blangs.empty())
-                                       plangs += "\n"; 
+                                       plangs += "\n";
                        }
 
                        frontend::Alert::warning(
@@ -2062,7 +2057,7 @@ void Buffer::writeDocBookSource(odocstream & os, string const & fname,
                        os << from_ascii(tclass.class_header());
                else if (runparams.flavor == OutputParams::XML)
                        os << "PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\" "
-                           << "\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\"";
+                           << "\"https://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\"";
                else
                        os << " PUBLIC \"-//OASIS//DTD DocBook V4.2//EN\"";
 
@@ -2451,15 +2446,16 @@ void Buffer::reloadBibInfoCache() const
                return;
 
        d->bibinfo_.clear();
-       collectBibKeys();
+       FileNameList checkedFiles;
+       collectBibKeys(checkedFiles);
        d->bibinfo_cache_valid_ = true;
 }
 
 
-void Buffer::collectBibKeys() const
+void Buffer::collectBibKeys(FileNameList & checkedFiles) const
 {
        for (InsetIterator it = inset_iterator_begin(inset()); it; ++it)
-               it->collectBibKeys(it);
+               it->collectBibKeys(it, checkedFiles);
 }
 
 
@@ -3606,7 +3602,7 @@ void Buffer::Impl::updateMacros(DocIterator & it, DocIterator & scope)
                                continue;
 
                        // get macro data
-                       MathMacroTemplate & macroTemplate =
+                       InsetMathMacroTemplate & macroTemplate =
                                *iit->inset->asInsetMath()->asMacroTemplate();
                        MacroContext mc(owner_, it);
                        macroTemplate.updateToContext(mc);
@@ -3725,8 +3721,12 @@ void Buffer::listMacroNames(MacroNameSet & macros) const
        // loop over children
        Impl::BufferPositionMap::iterator it = d->children_positions.begin();
        Impl::BufferPositionMap::iterator end = d->children_positions.end();
-       for (; it != end; ++it)
-               it->first->listMacroNames(macros);
+       for (; it != end; ++it) {
+               Buffer * child = const_cast<Buffer *>(it->first);
+               // The buffer might have been closed (see #10766).
+               if (theBufferList().isLoaded(child))
+                       child->listMacroNames(macros);
+       }
 
        // call parent
        Buffer const * const pbuf = d->parent();
@@ -3756,7 +3756,7 @@ void Buffer::listParentMacros(MacroSet & macros, LaTeXFeatures & features) const
                if (data) {
                        macros.insert(data);
 
-                       // we cannot access the original MathMacroTemplate anymore
+                       // we cannot access the original InsetMathMacroTemplate anymore
                        // here to calls validate method. So we do its work here manually.
                        // FIXME: somehow make the template accessible here.
                        if (data->optionals() > 0)
@@ -4108,7 +4108,7 @@ int AutoSaveBuffer::generateChild()
        return pid;
 }
 
-} // namespace anon
+} // namespace
 
 
 FileName Buffer::getEmergencyFileName() const
@@ -4733,7 +4733,7 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const
                        // not updated during the updateBuffer call and TocModel::toc_ is invalid
                        // (bug 5699). The same happens if the master buffer is open in a different
                        // window. This test catches both possibilities.
-                       // See: http://marc.info/?l=lyx-devel&m=138590578911716&w=2
+                       // See: https://marc.info/?l=lyx-devel&m=138590578911716&w=2
                        // There remains a problem here: If there is another child open in yet a third
                        // window, that TOC is not updated. So some more general solution is needed at
                        // some point.
@@ -4917,8 +4917,10 @@ void Buffer::Impl::setLabel(ParIterator & it, UpdateType utype) const
                switch (par.itemdepth) {
                case 2:
                        enumcounter += 'i';
+                       // fall through
                case 1:
                        enumcounter += 'i';
+                       // fall through
                case 0:
                        enumcounter += 'i';
                        break;
@@ -5031,7 +5033,7 @@ void Buffer::updateBuffer(ParIterator & parit, UpdateType utype) const
                // set the counter for this paragraph
                d->setLabel(parit, utype);
 
-               // update change-tracking flag 
+               // update change-tracking flag
                parit->addChangesToBuffer(*this);
 
                // now the insets
@@ -5157,7 +5159,7 @@ int Buffer::charCount(bool with_blanks) const
 Buffer::ReadStatus Buffer::reload()
 {
        setBusy(true);
-       // c.f. bug http://www.lyx.org/trac/ticket/6587
+       // c.f. bug https://www.lyx.org/trac/ticket/6587
        removeAutosaveFile();
        // e.g., read-only status could have changed due to version control
        d->filename.refresh();
@@ -5332,40 +5334,49 @@ void Buffer::Impl::refreshFileMonitor()
        // The previous file monitor is invalid
        // This also destroys the previous file monitor and all its connections
        file_monitor_ = FileSystemWatcher::monitor(filename);
-       fileExternallyModified(false);
        // file_monitor_ will be destroyed with *this, so it is not going to call a
        // destroyed object method.
-       file_monitor_->connect([this](){ fileExternallyModified(true); });
+       file_monitor_->connect([this](bool exists) {
+                       fileExternallyModified(exists);
+               });
 }
 
 
-void Buffer::Impl::fileExternallyModified(bool modified) const
+void Buffer::Impl::fileExternallyModified(bool const exists)
 {
-       if (modified) {
-               // prevent false positives, because FileMonitorBlocker is not enough on
-               // OSX.
-               if (filename.exists() && checksum_ == filename.checksum()) {
-                       LYXERR(Debug::FILES, "External modification but "
-                              "checksum unchanged: " << filename);
-                       return;
-               }
-               lyx_clean = bak_clean = false;
+       // ignore notifications after our own saving operations
+       if (checksum_ == filename.checksum()) {
+               LYXERR(Debug::FILES, "External modification but "
+                      "checksum unchanged: " << filename);
+               return;
        }
-       externally_modified_ = modified;
-       if (wa_)
+       lyx_clean = bak_clean = false;
+       // If the file has been deleted, only mark the file as dirty since it is
+       // pointless to prompt for reloading. If later a file is moved into this
+       // location, then the externally modified warning will appear then.
+       if (exists)
+                       externally_modified_ = true;
+       // Update external modification notification.
+       // Dirty buffers must be visible at all times.
+       if (wa_ && wa_->unhide(owner_))
                wa_->updateTitles();
+       else
+               // Unable to unhide the buffer (e.g. no GUI or not current View)
+               lyx_clean = true;
 }
 
 
 bool Buffer::notifiesExternalModification() const
 {
-       return d->isExternallyModified();
+       return d->externally_modified_;
 }
 
 
 void Buffer::clearExternalModification() const
 {
-       d->fileExternallyModified(false);
+       d->externally_modified_ = false;
+       if (d->wa_)
+               d->wa_->updateTitles();
 }