]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
Routines for calculating numerical labels for BibTeX citations.
[lyx.git] / src / Buffer.cpp
index 90512f0b63cbab0329fd588e93584ff600bbbd96..9b8730d4658f080f398f3b1917b26efbc843ca04 100644 (file)
@@ -127,7 +127,7 @@ namespace {
 
 // Do not remove the comment below, so we get merge conflict in
 // independent branches. Instead add your own.
-int const LYX_FORMAT = 373; // jspitzm: merge g-brief class
+int const LYX_FORMAT = 375; // jspitzm: includeonly support
 
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
@@ -147,7 +147,7 @@ class BufferSet : public std::set<Buffer const *> {};
 class Buffer::Impl
 {
 public:
-       Impl(Buffer & parent, FileName const & file, bool readonly);
+       Impl(Buffer & parent, FileName const & file, bool readonly, Buffer const * cloned_buffer);
 
        ~Impl()
        {
@@ -258,9 +258,15 @@ public:
                        LYXERR0("Warning: a buffer should not have two parents!");
                parent_buffer = pb;
        }
+
+       /// 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_;
+
 private:
        /// So we can force access via the accessors.
        mutable Buffer const * parent_buffer;
+
 };
 
 
@@ -283,26 +289,42 @@ static FileName createBufferTmpDir()
 }
 
 
-Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_)
+Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_,
+       Buffer const * cloned_buffer)
        : lyx_clean(true), bak_clean(true), unnamed(false),
          read_only(readonly_), filename(file), file_fully_loaded(false),
          toc_backend(&parent), macro_lock(false), timestamp_(0),
          checksum_(0), wa_(0), undo_(parent), bibinfoCacheValid_(false),
-         parent_buffer(0)
+         cloned_buffer_(cloned_buffer), parent_buffer(0)
 {
-       temppath = createBufferTmpDir();
-       lyxvc.setBuffer(&parent);
-       if (use_gui)
-               wa_ = new frontend::WorkAreaManager;
+       if (!cloned_buffer_) {
+               temppath = createBufferTmpDir();
+               lyxvc.setBuffer(&parent);
+               if (use_gui)
+                       wa_ = new frontend::WorkAreaManager;
+               return;
+       }
+       temppath = cloned_buffer_->d->temppath;
+       file_fully_loaded = true;
+       params = cloned_buffer_->d->params;
 }
 
 
-Buffer::Buffer(string const & file, bool readonly)
-       : d(new Impl(*this, FileName(file), readonly)), gui_(0)
+Buffer::Buffer(string const & file, bool readonly, Buffer const * cloned_buffer)
+       : d(new Impl(*this, FileName(file), readonly, cloned_buffer)), gui_(0)
 {
        LYXERR(Debug::INFO, "Buffer::Buffer()");
-
-       d->inset = new InsetText(this);
+       if (cloned_buffer) {
+               d->inset = new InsetText(*cloned_buffer->d->inset);
+               d->inset->setBuffer(*this);
+               // FIXME: optimize this loop somewhat, maybe by creating a new
+               // general recursive Inset::setId().
+               DocIterator it = doc_iterator_begin(this);
+               DocIterator cloned_it = doc_iterator_begin(cloned_buffer);
+               for (; !it.atEnd(); it.forwardPar(), cloned_it.forwardPar())
+                       it.paragraph().setId(cloned_it.paragraph().id());
+       } else
+               d->inset = new InsetText(this);
        d->inset->setAutoBreakRows(true);
        d->inset->getText(0)->setMacrocontextPosition(par_iterator_begin());
 }
@@ -336,14 +358,14 @@ Buffer::~Buffer()
        if (!isClean()) {
                docstring msg = _("LyX attempted to close a document that had unsaved changes!\n");
                msg += emergencyWrite();
-               frontend::Alert::warning(_("Attempting to close changed document!"), msg);
+               Alert::warning(_("Attempting to close changed document!"), msg);
        }
                
        // clear references to children in macro tables
        d->children_positions.clear();
        d->position_to_children.clear();
 
-       if (!d->temppath.destroyDirectory()) {
+       if (!d->cloned_buffer_ && !d->temppath.destroyDirectory()) {
                Alert::warning(_("Could not remove temporary directory"),
                        bformat(_("Could not remove the temporary directory %1$s"),
                        from_utf8(d->temppath.absFilename())));
@@ -358,19 +380,22 @@ Buffer::~Buffer()
 
 Buffer * Buffer::clone() const
 {
-       Buffer * clone = new Buffer(fileName().absFilename(), false);
-       clone->d->file_fully_loaded = true;
-       clone->d->params = d->params;
-       clone->d->inset = static_cast<InsetText *>(d->inset->clone());
-       clone->d->inset->setBuffer(*clone);
-       return clone;
+       // FIXME for asynchronous export and preview: We must also clone all
+       // the child buffers!
+       return new Buffer(fileName().absFilename(), false, this);
 }
 
 
-void Buffer::changed() const
+bool Buffer::isClone() const
+{
+       return d->cloned_buffer_;
+}
+
+
+void Buffer::changed(bool update_metrics) const
 {
        if (d->wa_)
-               d->wa_->redrawAll();
+               d->wa_->redrawAll(update_metrics);
 }
 
 
@@ -582,6 +607,7 @@ int Buffer::readHeader(Lexer & lex)
        params().listings_params.clear();
        params().clearLayoutModules();
        params().clearRemovedModules();
+       params().clearIncludedChildren();
        params().pdfoptions().clear();
        params().indiceslist().clear();
        params().backgroundcolor = lyx::rgbFromHexName("#ffffff");
@@ -1234,7 +1260,9 @@ void Buffer::writeLaTeXSource(odocstream & os,
                listParentMacros(parentMacros, features);
 
                // Write the preamble
-               runparams.use_babel = params().writeLaTeX(os, features, d->texrow);
+               runparams.use_babel = params().writeLaTeX(os, features,
+                                                         d->texrow,
+                                                         d->filename.onlyPath());
 
                runparams.use_japanese = features.isRequired("japanese");
 
@@ -1429,8 +1457,8 @@ void Buffer::writeLyXHTMLSource(odocstream & os,
        LaTeXFeatures features(*this, params(), runparams);
        validate(features);
        updateLabels(UpdateMaster, true);
-
-       d->texrow.reset();
+       checkBibInfoCache();
+       d->bibinfo_.collectCitedEntries(*this);
 
        if (!only_body) {
                os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
@@ -1612,18 +1640,23 @@ BiblioInfo const & Buffer::masterBibInfo() const
 
 BiblioInfo const & Buffer::localBibInfo() const
 {
-       if (d->bibinfoCacheValid_) {
-               support::FileNameList const & bibfilesCache = getBibfilesCache();
-               // compare the cached timestamps with the actual ones.
-               support::FileNameList::const_iterator ei = bibfilesCache.begin();
-               support::FileNameList::const_iterator en = bibfilesCache.end();
-               for (; ei != en; ++ ei) {
-                       time_t lastw = ei->lastModified();
-                       if (lastw != d->bibfileStatus_[*ei]) {
-                               d->bibinfoCacheValid_ = false;
-                               d->bibfileStatus_[*ei] = lastw;
-                               break;
-                       }
+       checkBibInfoCache();
+       return d->bibinfo_;
+}
+
+
+void Buffer::checkBibInfoCache() const 
+{
+       support::FileNameList const & bibfilesCache = getBibfilesCache();
+       // compare the cached timestamps with the actual ones.
+       support::FileNameList::const_iterator ei = bibfilesCache.begin();
+       support::FileNameList::const_iterator en = bibfilesCache.end();
+       for (; ei != en; ++ ei) {
+               time_t lastw = ei->lastModified();
+               time_t prevw = d->bibfileStatus_[*ei];
+               if (lastw != prevw) {
+                       d->bibinfoCacheValid_ = false;
+                       d->bibfileStatus_[*ei] = lastw;
                }
        }
 
@@ -1632,8 +1665,7 @@ BiblioInfo const & Buffer::localBibInfo() const
                for (InsetIterator it = inset_iterator_begin(inset()); it; ++it)
                        it->fillWithBibKeys(d->bibinfo_, it);
                d->bibinfoCacheValid_ = true;
-       }
-       return d->bibinfo_;
+       }       
 }
 
 
@@ -1652,6 +1684,21 @@ void Buffer::markDepClean(string const & name)
 }
 
 
+bool Buffer::isExportableFormat(string const & format) const
+{
+               typedef vector<Format const *> Formats;
+               Formats formats;
+               formats = exportableFormats(true);
+               Formats::const_iterator fit = formats.begin();
+               Formats::const_iterator end = formats.end();
+               for (; fit != end ; ++fit) {
+                       if ((*fit)->name() == format)
+                               return true;
+               }
+               return false;
+}
+
+
 bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 {
        if (isInternal()) {
@@ -1687,27 +1734,6 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                        break;
                }
 
-               case LFUN_MASTER_BUFFER_UPDATE:
-               case LFUN_MASTER_BUFFER_VIEW: 
-                       enable = parent() != 0;
-                       break;
-               case LFUN_BUFFER_UPDATE:
-               case LFUN_BUFFER_VIEW: {
-                       string format = to_utf8(cmd.argument());
-                       if (cmd.argument().empty())
-                               format = getDefaultOutputFormat();
-                       typedef vector<Format const *> Formats;
-                       Formats formats;
-                       formats = exportableFormats(true);
-                       Formats::const_iterator fit = formats.begin();
-                       Formats::const_iterator end = formats.end();
-                       enable = false;
-                       for (; fit != end ; ++fit) {
-                               if ((*fit)->name() == format)
-                                       enable = true;
-                       }
-                       break;
-               }
                case LFUN_BUFFER_CHKTEX:
                        enable = isLatex() && !lyxrc.chktex_command.empty();
                        break;
@@ -1773,10 +1799,6 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                break;
 
        case LFUN_BUFFER_EXPORT: {
-               if (argument == "custom") {
-                       lyx::dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"));
-                       break;
-               }
                bool success = doExport(argument, false);
                dr.setError(success);
                if (!success)
@@ -1785,38 +1807,6 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                break;
        }
 
-       case LFUN_BUFFER_UPDATE: {
-               string format = argument;
-               if (argument.empty())
-                       format = getDefaultOutputFormat();
-               doExport(format, true);
-               break;
-       }
-
-       case LFUN_BUFFER_VIEW: {
-               string format = argument;
-               if (argument.empty())
-                       format = getDefaultOutputFormat();
-               preview(format);
-               break;
-       }
-
-       case LFUN_MASTER_BUFFER_UPDATE: {
-               string format = argument;
-               if (argument.empty())
-                       format = masterBuffer()->getDefaultOutputFormat();
-               masterBuffer()->doExport(format, true);
-               break;
-       }
-
-       case LFUN_MASTER_BUFFER_VIEW: {
-               string format = argument;
-               if (argument.empty())
-                       format = masterBuffer()->getDefaultOutputFormat();
-               masterBuffer()->preview(format);
-               break;
-       }
-
        case LFUN_BUILD_PROGRAM:
                doExport("program", true);
                break;
@@ -2356,9 +2346,8 @@ DocIterator Buffer::firstChildPosition(Buffer const * child)
 }
 
 
-std::vector<Buffer *> Buffer::getChildren(bool grand_children) const
+void Buffer::getChildren(std::vector<Buffer *> & clist, bool grand_children) const
 {
-       std::vector<Buffer *> clist;
        // loop over children
        Impl::BufferPositionMap::iterator it = d->children_positions.begin();
        Impl::BufferPositionMap::iterator end = d->children_positions.end();
@@ -2373,7 +2362,14 @@ std::vector<Buffer *> Buffer::getChildren(bool grand_children) const
                                clist.push_back(*git);
                }
        }
-       return clist;
+}
+
+
+std::vector<Buffer *> Buffer::getChildren(bool grand_children) const
+{
+       std::vector<Buffer *> v;
+       getChildren(v, grand_children);
+       return v;
 }
 
 
@@ -3132,14 +3128,18 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
                                path = p;
                        }
                }
-               if (!path.empty())
-                       runparams.flavor = theConverters().getFlavor(path);
-               else {
-                       Alert::error(_("Couldn't export file"),
-                               bformat(_("No information for exporting the format %1$s."),
-                                  formats.prettyName(format)));
+               if (path.empty()) {
+                       if (!put_in_tempdir) {
+                               // Only show this alert if this is an export to a non-temporary
+                               // file (not for previewing).
+                               Alert::error(_("Couldn't export file"), bformat(
+                                       _("No information for exporting the format %1$s."),
+                                       formats.prettyName(format)));
+                       }
                        return false;
                }
+               runparams.flavor = theConverters().getFlavor(path);
+
        } else {
                backend_format = format;
                // FIXME: Don't hardcode format names here, but use a flag
@@ -3207,6 +3207,14 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
        if (!success)
                return false;
 
+       if (d->cloned_buffer_) {
+               // Enable reverse dvi or pdf to work by copying back the texrow
+               // object to the cloned buffer.
+               // FIXME: There is a possibility of concurrent access to texrow
+               // here from the main GUI thread that should be securized.
+               d->cloned_buffer_->d->texrow = d->texrow;
+       }
+
        if (put_in_tempdir) {
                result_file = tmp_result_file.absFilename();
                return true;
@@ -3770,4 +3778,26 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to,
        return progress;
 }
 
+
+bool Buffer::reload()
+{
+       setBusy(true);
+       // e.g., read-only status could have changed due to version control
+       d->filename.refresh();
+       docstring const disp_fn = makeDisplayPath(d->filename.absFilename());
+
+       bool const success = loadLyXFile(d->filename);
+       if (success) {
+               updateLabels();
+               changed(true);
+               errors("Parse");
+               message(bformat(_("Document %1$s reloaded."), disp_fn));
+       } else {
+               message(bformat(_("Could not reload document %1$s."), disp_fn));
+       }       
+       setBusy(false);
+       return success;
+}
+
+
 } // namespace lyx