]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
More requires --> required, for C++2a.
[lyx.git] / src / Buffer.cpp
index 0dcd81ab5ebed7c6cc4b0c8a27caaa08a4bc5a68..a300b2dd4bd829853c63b74192786acae02d678f 100644 (file)
@@ -153,11 +153,12 @@ typedef vector<LabelInfo> LabelCache;
 
 typedef map<docstring, Buffer::References> RefCache;
 
-} // namespace
+// A storehouse for the cloned buffers.
+typedef list<CloneList_ptr> CloneStore;
+CloneStore cloned_buffers;
 
+} // namespace
 
-// A storehouse for the cloned buffers.
-list<CloneList *> cloned_buffers;
 
 
 class Buffer::Impl
@@ -200,40 +201,9 @@ public:
        /// need to regenerate .tex?
        DepClean dep_clean;
 
-       /// is save needed?
-       mutable bool lyx_clean;
-
-       /// is autosave needed?
-       mutable bool bak_clean;
-
-       /// is this an unnamed file (New...)?
-       bool unnamed;
-
-       /// is this an internal bufffer?
-       bool internal_buffer;
-
-       /// buffer is r/o
-       bool read_only;
-
        /// name of the file the buffer is associated with.
        FileName filename;
 
-       /** Set to true only when the file is fully loaded.
-        *  Used to prevent the premature generation of previews
-        *  and by the citation inset.
-        */
-       bool file_fully_loaded;
-
-       /// original format of loaded file
-       int file_format;
-
-       /// if the file was originally loaded from an older format, do
-       /// we need to back it up still?
-       bool need_format_backup;
-
-       /// Ignore the parent (e.g. when exporting a child standalone)?
-       bool ignore_parent;
-
        ///
        mutable TocBackend toc_backend;
 
@@ -250,13 +220,11 @@ public:
        /// map from the macro name to the position map,
        /// which maps the macro definition position to the scope and the MacroData.
        NamePositionScopeMacroMap macros;
-       /// This seem to change the way Buffer::getMacro() works
-       mutable bool macro_lock;
 
        /// positions of child buffers in the buffer
        typedef map<Buffer const * const, DocIterator> BufferPositionMap;
        struct ScopeBuffer {
-               ScopeBuffer() : buffer(0) {}
+               ScopeBuffer() : buffer(nullptr) {}
                ScopeBuffer(DocIterator const & s, Buffer const * b)
                        : scope(s), buffer(b) {}
                DocIterator scope;
@@ -303,25 +271,13 @@ public:
        // 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
-       mutable bool bibinfo_cache_valid_;
        /// Cache of timestamps of .bib files
        map<FileName, time_t> bibfile_status_;
-       /// Indicates whether the bibinfo has changed since the last time
-       /// we ran updateBuffer(), i.e., whether citation labels may need
-       /// to be updated.
-       mutable bool cite_labels_valid_;
-       /// Do we have a bibliography environment?
-       mutable bool have_bibitems_;
 
        /// These two hold the file name and format, written to by
        /// Buffer::preview and read from by LFUN_BUFFER_VIEW_CACHE.
        FileName preview_file_;
        string preview_format_;
-       /// If there was an error when previewing, on the next preview we do
-       /// a fresh compile (e.g. in case the user installed a package that
-       /// was missing).
-       bool require_fresh_start_;
 
        /// Cache the references associated to a label and their positions
        /// in the buffer.
@@ -335,6 +291,81 @@ public:
        ///
        PreviewLoader * preview_loader_;
 
+       /// If non zero, this buffer is a clone of existing buffer \p cloned_buffer_
+       /// This one is useful for preview detached in a thread.
+       Buffer const * cloned_buffer_;
+       ///
+       CloneList_ptr clone_list_;
+
+private:
+       /// So we can force access via the accessors.
+       mutable Buffer const * parent_buffer;
+
+       FileMonitorPtr file_monitor_;
+
+/// ints and bools are all listed last so as to avoid alignment issues
+public:
+       /// original format of loaded file
+       int file_format;
+
+       /// are we in the process of exporting this buffer?
+       mutable bool doing_export;
+
+       /// If there was an error when previewing, on the next preview we do
+       /// a fresh compile (e.g. in case the user installed a package that
+       /// was missing).
+       bool require_fresh_start_;
+
+       /// Indicates whether the bibinfo has changed since the last time
+       /// we ran updateBuffer(), i.e., whether citation labels may need
+       /// to be updated.
+       mutable bool cite_labels_valid_;
+       /// Do we have a bibliography environment?
+       mutable bool have_bibitems_;
+
+       /// is save needed?
+       mutable bool lyx_clean;
+
+       /// is autosave needed?
+       mutable bool bak_clean;
+
+       /// is this an unnamed file (New...)?
+       bool unnamed;
+
+       /// is this an internal bufffer?
+       bool internal_buffer;
+
+       /// buffer is r/o
+       bool read_only;
+
+       /** Set to true only when the file is fully loaded.
+        *  Used to prevent the premature generation of previews
+        *  and by the citation inset.
+        */
+       bool file_fully_loaded;
+
+       /// if the file was originally loaded from an older format, do
+       /// we need to back it up still?
+       bool need_format_backup;
+
+       /// Ignore the parent (e.g. when exporting a child standalone)?
+       bool ignore_parent;
+
+       /// This seem to change the way Buffer::getMacro() works
+       mutable bool macro_lock;
+
+       /// has been externally modified? Can be reset by the user.
+       mutable bool externally_modified_;
+
+       /// whether the bibinfo cache is valid
+       mutable bool bibinfo_cache_valid_;
+
+private:
+       int word_count_;
+       int char_count_;
+       int blank_count_;
+
+public:
        /// This is here to force the test to be done whenever parent_buffer
        /// is accessed.
        Buffer const * parent() const
@@ -342,7 +373,7 @@ public:
                // ignore_parent temporarily "orphans" a buffer
                // (e.g. if a child is compiled standalone)
                if (ignore_parent)
-                       return 0;
+                       return nullptr;
                // if parent_buffer is not loaded, then it has been unloaded,
                // which means that parent_buffer is an invalid pointer. So we
                // set it to null in that case.
@@ -350,7 +381,7 @@ public:
                // they will always be regarded as unloaded. in that case, we hope
                // for the best.
                if (!cloned_buffer_ && !theBufferList().isLoaded(parent_buffer))
-                       parent_buffer = 0;
+                       parent_buffer = nullptr;
                return parent_buffer;
        }
 
@@ -367,14 +398,6 @@ public:
                        parent_buffer->invalidateBibinfoCache();
        }
 
-       /// If non zero, this buffer is a clone of existing buffer \p cloned_buffer_
-       /// This one is useful for preview detached in a thread.
-       Buffer const * cloned_buffer_;
-       ///
-       CloneList * clone_list_;
-       /// are we in the process of exporting this buffer?
-       mutable bool doing_export;
-
        /// compute statistics
        /// \p from initial position
        /// \p to points to the end position
@@ -397,24 +420,11 @@ public:
        /// Notify or clear of external modification
        void fileExternallyModified(bool exists);
 
-       /// has been externally modified? Can be reset by the user.
-       mutable bool externally_modified_;
-
        ///Binding LaTeX lines with buffer positions.
        //Common routine for LaTeX and Reference errors listing.
         void traverseErrors(TeXErrors::Errors::const_iterator err,
                TeXErrors::Errors::const_iterator end,
                ErrorList & errorList) const;
-
-private:
-       /// So we can force access via the accessors.
-       mutable Buffer const * parent_buffer;
-
-       int word_count_;
-       int char_count_;
-       int blank_count_;
-
-       FileMonitorPtr file_monitor_;
 };
 
 
@@ -447,15 +457,15 @@ static FileName createBufferTmpDir()
 
 Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
        Buffer const * cloned_buffer)
-       : owner_(owner), lyx_clean(true), bak_clean(true), unnamed(false),
-         internal_buffer(false), read_only(readonly_), filename(file),
-         file_fully_loaded(false), file_format(LYX_FORMAT), need_format_backup(false),
-         ignore_parent(false),  toc_backend(owner), macro_lock(false),
-         checksum_(0), wa_(0),  gui_(0), undo_(*owner), bibinfo_cache_valid_(false),
-         cite_labels_valid_(false), have_bibitems_(false), require_fresh_start_(false),
-         inset(0), preview_loader_(0), cloned_buffer_(cloned_buffer),
-         clone_list_(0), doing_export(false),
-         externally_modified_(false), parent_buffer(0),
+       : owner_(owner), filename(file), toc_backend(owner), checksum_(0),
+         wa_(nullptr),  gui_(nullptr), undo_(*owner), inset(nullptr),
+         preview_loader_(nullptr), cloned_buffer_(cloned_buffer),
+         clone_list_(nullptr), parent_buffer(nullptr), file_format(LYX_FORMAT),
+         doing_export(false), require_fresh_start_(false), cite_labels_valid_(false),
+         have_bibitems_(false), lyx_clean(true), bak_clean(true), unnamed(false),
+         internal_buffer(false), read_only(readonly_), file_fully_loaded(false),
+         need_format_backup(false), ignore_parent(false), macro_lock(false),
+         externally_modified_(false), bibinfo_cache_valid_(false),
          word_count_(0), char_count_(0), blank_count_(0)
 {
        refreshFileMonitor();
@@ -515,7 +525,7 @@ Buffer::~Buffer()
        // saved properly, before it goes into the void.
 
        // GuiView already destroyed
-       d->gui_ = 0;
+       d->gui_ = nullptr;
 
        if (isInternal()) {
                // No need to do additional cleanups for internal buffer.
@@ -530,8 +540,8 @@ Buffer::~Buffer()
                // loop over children
                for (auto const & p : d->children_positions) {
                        Buffer * child = const_cast<Buffer *>(p.first);
-                               if (d->clone_list_->erase(child))
-                                       delete child;
+                       if (d->clone_list_->erase(child))
+                               delete child;
                }
                // if we're the master buffer, then we should get rid of the list
                // of clones
@@ -540,14 +550,15 @@ Buffer::~Buffer()
                        // children still has a reference to this list. But we will try to
                        // continue, rather than shut down.
                        LATTEST(d->clone_list_->empty());
-                       list<CloneList *>::iterator it =
+                       // The clone list itself is empty, but it's still referenced in our list
+                       // of clones. So let's find it and remove it.
+                       CloneStore::iterator it =
                                find(cloned_buffers.begin(), cloned_buffers.end(), d->clone_list_);
                        if (it == cloned_buffers.end()) {
                                // We will leak in this case, but it is safe to continue.
                                LATTEST(false);
                        } else
                                cloned_buffers.erase(it);
-                       delete d->clone_list_;
                }
                // FIXME Do we really need to do this right before we delete d?
                // clear references to children in macro tables
@@ -559,7 +570,7 @@ Buffer::~Buffer()
                        Buffer * child = const_cast<Buffer *>(p.first);
                        if (theBufferList().isLoaded(child)) {
                                if (theBufferList().isOthersChild(this, child))
-                                       child->setParent(0);
+                                       child->setParent(nullptr);
                                else
                                        theBufferList().release(child);
                        }
@@ -594,21 +605,21 @@ Buffer::~Buffer()
 Buffer * Buffer::cloneWithChildren() const
 {
        BufferMap bufmap;
-       cloned_buffers.push_back(new CloneList);
-       CloneList * clones = cloned_buffers.back();
+       cloned_buffers.emplace_back(new CloneList);
+       CloneList_ptr clones = cloned_buffers.back();
 
        cloneWithChildren(bufmap, clones);
 
        // make sure we got cloned
        BufferMap::const_iterator bit = bufmap.find(this);
-       LASSERT(bit != bufmap.end(), return 0);
+       LASSERT(bit != bufmap.end(), return nullptr);
        Buffer * cloned_buffer = bit->second;
 
        return cloned_buffer;
 }
 
 
-void Buffer::cloneWithChildren(BufferMap & bufmap, CloneList * clones) const
+void Buffer::cloneWithChildren(BufferMap & bufmap, CloneList_ptr clones) const
 {
        // have we already been cloned?
        if (bufmap.find(this) != bufmap.end())
@@ -658,8 +669,8 @@ void Buffer::cloneWithChildren(BufferMap & bufmap, CloneList * clones) const
 
 
 Buffer * Buffer::cloneBufferOnly() const {
-       cloned_buffers.push_back(new CloneList);
-       CloneList * clones = cloned_buffers.back();
+       cloned_buffers.emplace_back(new CloneList);
+       CloneList_ptr clones = cloned_buffers.back();
        Buffer * buffer_clone = new Buffer(fileName().absFileName(), false, this);
 
        // The clone needs its own DocumentClass, since running updateBuffer() will
@@ -1133,7 +1144,7 @@ bool Buffer::importFile(string const & format, FileName const & name, ErrorList
 
        FileName const lyx = tempFileName("Buffer_importFileXXXXXX.lyx");
        Converters::RetVal const retval =
-           theConverters().convert(0, name, lyx, name, format, "lyx", errorList);
+               theConverters().convert(nullptr, name, lyx, name, format, "lyx", errorList);
        if (retval == Converters::SUCCESS) {
                bool const success = readFile(lyx) == ReadSuccess;
                removeTempFile(lyx);
@@ -1248,7 +1259,7 @@ void Buffer::requireFreshStart(bool const b) const
 PreviewLoader * Buffer::loader() const
 {
        if (!isExporting() && lyxrc.preview == LyXRC::PREVIEW_OFF)
-               return 0;
+               return nullptr;
        if (!d->preview_loader_)
                d->preview_loader_ = new PreviewLoader(*this);
        return d->preview_loader_;
@@ -1258,7 +1269,7 @@ PreviewLoader * Buffer::loader() const
 void Buffer::removePreviews() const
 {
        delete d->preview_loader_;
-       d->preview_loader_ = 0;
+       d->preview_loader_ = nullptr;
 }
 
 
@@ -2605,7 +2616,7 @@ void Buffer::collectBibKeys(FileNameList & checkedFiles) const
        for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
                it->collectBibKeys(it, checkedFiles);
                if (it->lyxCode() == BIBITEM_CODE) {
-                       if (parent() != 0)
+                       if (parent() != nullptr)
                                parent()->d->have_bibitems_ = true;
                        else
                                d->have_bibitems_ = true;
@@ -2622,7 +2633,7 @@ void Buffer::addBiblioInfo(BiblioInfo const & bin) const
        BiblioInfo & bi = d->bibinfo_;
        bi.mergeBiblioInfo(bin);
 
-       if (parent() != 0) {
+       if (parent() != nullptr) {
                BiblioInfo & masterbi = parent()->d->bibinfo_;
                masterbi.mergeBiblioInfo(bin);
        }
@@ -2637,7 +2648,7 @@ void Buffer::addBibTeXInfo(docstring const & key, BibTeXInfo const & bin) const
        BiblioInfo & bi = d->bibinfo_;
        bi[key] = bin;
 
-       if (parent() != 0) {
+       if (parent() != nullptr) {
                BiblioInfo & masterbi = masterBuffer()->d->bibinfo_;
                masterbi[key] = bin;
        }
@@ -3465,7 +3476,7 @@ bool Buffer::isReadonly() const
 void Buffer::setParent(Buffer const * buffer)
 {
        // Avoids recursive include.
-       d->setParent(buffer == this ? 0 : buffer);
+       d->setParent(buffer == this ? nullptr : buffer);
        updateMacros();
 }
 
@@ -3585,11 +3596,11 @@ MacroData const * Buffer::Impl::getBufferMacro(docstring const & name,
 
        // if paragraphs have no macro context set, pos will be empty
        if (pos.empty())
-               return 0;
+               return nullptr;
 
        // we haven't found anything yet
        DocIterator bestPos = owner_->par_iterator_begin();
-       MacroData const * bestData = 0;
+       MacroData const * bestData = nullptr;
 
        // find macro definitions for name
        NamePositionScopeMacroMap::const_iterator nameIt = macros.find(name);
@@ -3660,11 +3671,11 @@ MacroData const * Buffer::getMacro(docstring const & name,
        DocIterator const & pos, bool global) const
 {
        if (d->macro_lock)
-               return 0;
+               return nullptr;
 
        // query buffer macros
        MacroData const * data = d->getBufferMacro(name, pos);
-       if (data != 0)
+       if (data != nullptr)
                return data;
 
        // If there is a master buffer, query that
@@ -3680,11 +3691,11 @@ MacroData const * Buffer::getMacro(docstring const & name,
 
        if (global) {
                data = MacroTable::globalMacros().get(name);
-               if (data != 0)
+               if (data != nullptr)
                        return data;
        }
 
-       return 0;
+       return nullptr;
 }
 
 
@@ -3704,7 +3715,7 @@ MacroData const * Buffer::getMacro(docstring const & name,
        // look where the child buffer is included first
        Impl::BufferPositionMap::iterator it = d->children_positions.find(&child);
        if (it == d->children_positions.end())
-               return 0;
+               return nullptr;
 
        // check for macros at the inclusion position
        return getMacro(name, it->second, global);
@@ -3882,7 +3893,7 @@ void Buffer::updateMacroInstances(UpdateType utype) const
                MacroContext mc = MacroContext(this, it);
                for (DocIterator::idx_type i = 0; i < n; ++i) {
                        MathData & data = minset->cell(i);
-                       data.updateMacros(0, mc, utype, 0);
+                       data.updateMacros(nullptr, mc, utype, 0);
                }
        }
 }
@@ -4224,91 +4235,6 @@ void Buffer::setGuiDelegate(frontend::GuiBufferDelegate * gui)
 }
 
 
-
-namespace {
-
-class AutoSaveBuffer : public ForkedProcess {
-public:
-       ///
-       AutoSaveBuffer(Buffer const & buffer, FileName const & fname)
-               : buffer_(buffer), fname_(fname) {}
-       ///
-       virtual shared_ptr<ForkedProcess> clone() const
-       {
-               return make_shared<AutoSaveBuffer>(*this);
-       }
-       ///
-       int start()
-       {
-               command_ = to_utf8(bformat(_("Auto-saving %1$s"),
-                                                from_utf8(fname_.absFileName())));
-               return run(DontWait);
-       }
-private:
-       ///
-       virtual int generateChild();
-       ///
-       Buffer const & buffer_;
-       FileName fname_;
-};
-
-
-int AutoSaveBuffer::generateChild()
-{
-#if defined(__APPLE__)
-       /* FIXME fork() is not usable for autosave on Mac OS X 10.6 (snow leopard)
-        *   We should use something else like threads.
-        *
-        * Since I do not know how to determine at run time what is the OS X
-        * version, I just disable forking altogether for now (JMarc)
-        */
-       pid_t const pid = -1;
-#else
-       // tmp_ret will be located (usually) in /tmp
-       // will that be a problem?
-       // Note that this calls ForkedCalls::fork(), so it's
-       // ok cross-platform.
-       pid_t const pid = fork();
-       // If you want to debug the autosave
-       // you should set pid to -1, and comment out the fork.
-       if (pid != 0 && pid != -1)
-               return pid;
-#endif
-
-       // pid = -1 signifies that lyx was unable
-       // to fork. But we will do the save
-       // anyway.
-       bool failed = false;
-       TempFile tempfile("lyxautoXXXXXX.lyx");
-       tempfile.setAutoRemove(false);
-       FileName const tmp_ret = tempfile.name();
-       if (!tmp_ret.empty()) {
-               if (!buffer_.writeFile(tmp_ret))
-                       failed = true;
-               else if (!tmp_ret.moveTo(fname_))
-                       failed = true;
-       } else
-               failed = true;
-
-       if (failed) {
-               // failed to write/rename tmp_ret so try writing direct
-               if (!buffer_.writeFile(fname_)) {
-                       // It is dangerous to do this in the child,
-                       // but safe in the parent, so...
-                       if (pid == -1) // emit message signal.
-                               buffer_.message(_("Autosave failed!"));
-               }
-       }
-
-       if (pid == 0) // we are the child so...
-               _exit(0);
-
-       return pid;
-}
-
-} // namespace
-
-
 FileName Buffer::getEmergencyFileName() const
 {
        return FileName(d->filename.absFileName() + ".emergency");
@@ -4912,7 +4838,7 @@ void Buffer::Impl::traverseErrors(TeXErrors::Errors::const_iterator err, TeXErro
        for (; err != end; ++err) {
                TexRow::TextEntry start = TexRow::text_none, end = TexRow::text_none;
                int errorRow = err->error_in_line;
-               Buffer const * buf = 0;
+               Buffer const * buf = nullptr;
                Impl const * p = this;
                if (err->child_name.empty())
                        tie(start, end) = p->texrow.getEntriesFromRow(errorRow);
@@ -5478,7 +5404,7 @@ Buffer::ReadStatus Buffer::reload()
        docstring const disp_fn = makeDisplayPath(d->filename.absFileName());
 
        // clear parent. this will get reset if need be.
-       d->setParent(0);
+       d->setParent(nullptr);
        ReadStatus const status = loadLyXFile();
        if (status == ReadSuccess) {
                updateBuffer();
@@ -5552,8 +5478,8 @@ void Buffer::checkChildBuffers()
                if (oldloc == newloc)
                        continue;
                // the location of the child file is incorrect.
-               cbuf->setParent(0);
-               inset_inc->setChildBuffer(0);
+               cbuf->setParent(nullptr);
+               inset_inc->setChildBuffer(nullptr);
        }
        // invalidate cache of children
        d->children_positions.clear();
@@ -5578,7 +5504,7 @@ void Buffer::checkMasterBuffer()
        if (master->isChild(this))
                setParent(master);
        else
-               setParent(0);
+               setParent(nullptr);
 }