]> git.lyx.org Git - lyx.git/blobdiff - src/insets/insetinclude.C
Final touch 'inset display()'; fix 'is a bit silly' bug
[lyx.git] / src / insets / insetinclude.C
index 018da0fb3889ba136a3e577a273ed7962a3aac7c..5a02886a53564a4e42acb938db38f3edd0bcd55b 100644 (file)
@@ -1,70 +1,70 @@
-#include <config.h>
+/**
+ * \file insetinclude.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjønnes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
 
-#ifdef __GNUG__
-#pragma implementation
-#endif
+#include <config.h>
 
 #include "insetinclude.h"
+
 #include "buffer.h"
+#include "buffer_funcs.h"
 #include "bufferlist.h"
+#include "bufferparams.h"
 #include "BufferView.h"
 #include "debug.h"
-#include "lyxrc.h"
-#include "LaTeXFeatures.h"
+#include "funcrequest.h"
 #include "gettext.h"
+#include "LaTeXFeatures.h"
+#include "latexrunparams.h"
+#include "lyx_main.h"
+#include "lyxlex.h"
+#include "metricsinfo.h"
 
-#include "frontends/Dialogs.h"
 #include "frontends/LyXView.h"
 #include "frontends/Painter.h"
 
-#include "support/filetools.h"
-#include "support/FileInfo.h"
-#include "support/FileMonitor.h"
-#include "support/lstrings.h"
+#include "graphics/PreviewLoader.h"
 
-#include "graphics/PreviewedInset.h"
-#include "graphics/PreviewImage.h"
+#include "insets/render_preview.h"
 
-#include <boost/bind.hpp>
+#include "support/FileInfo.h"
+#include "support/filetools.h"
+#include "support/lstrings.h" // contains
+#include "support/tostr.h"
 
-#include <cstdlib>
+#include <boost/bind.hpp>
 
+#include "support/std_ostream.h"
+#include "support/std_sstream.h"
+
+using lyx::support::AddName;
+using lyx::support::ChangeExtension;
+using lyx::support::contains;
+using lyx::support::FileInfo;
+using lyx::support::GetFileContents;
+using lyx::support::IsFileReadable;
+using lyx::support::IsLyXFilename;
+using lyx::support::MakeAbsPath;
+using lyx::support::MakeDisplayPath;
+using lyx::support::OnlyFilename;
+using lyx::support::OnlyPath;
+using lyx::support::subst;
 
-using std::ostream;
 using std::endl;
-using std::vector;
-using std::pair;
-
-extern BufferList bufferlist;
-
-
-class InsetInclude::PreviewImpl : public grfx::PreviewedInset {
-public:
-       ///
-       PreviewImpl(InsetInclude & p) : PreviewedInset(p) {}
+using std::string;
+using std::auto_ptr;
+using std::istringstream;
+using std::ostream;
+using std::ostringstream;
 
-       ///
-       bool previewWanted() const;
-       ///
-       string const latexString() const;
-       ///
-       InsetInclude & parent() const {
-               return *static_cast<InsetInclude*>(inset());
-       }
 
-       ///
-       bool monitoring() const { return monitor_.get(); }
-       ///
-       void startMonitoring();
-       ///
-       void stopMonitoring() { monitor_.reset(); }
-
-private:
-       /// Invoked by monitor_ should the parent file change.
-       void restartLoading();
-       ///
-       boost::scoped_ptr<FileMonitor> monitor_;
-};
+extern BufferList bufferlist;
 
 
 namespace {
@@ -72,148 +72,182 @@ namespace {
 string const uniqueID()
 {
        static unsigned int seed = 1000;
-
-       ostringstream ost;
-       ost << "file" << ++seed;
-
-       // Needed if we use lyxstring.
-       return ost.str().c_str();
+       return "file" + tostr(++seed);
 }
 
 } // namespace anon
 
 
-InsetInclude::InsetInclude(Params const & p)
+InsetInclude::InsetInclude(InsetCommandParams const & p)
        : params_(p), include_label(uniqueID()),
-         preview_(new PreviewImpl(*this))
-{}
+         preview_(new RenderMonitoredPreview),
+         set_label_(false)
+{
+       preview_->connect(boost::bind(&InsetInclude::statusChanged, this));
+       preview_->fileChanged(boost::bind(&InsetInclude::fileChanged, this));
+}
 
 
-InsetInclude::InsetInclude(InsetCommandParams const & p, Buffer const & b)
-       : include_label(uniqueID()),
-         preview_(new PreviewImpl(*this))
+InsetInclude::InsetInclude(InsetInclude const & other)
+       : InsetOld(other),
+         params_(other.params_),
+         include_label(other.include_label),
+         preview_(new RenderMonitoredPreview),
+         set_label_(other.set_label_)
 {
-       params_.cparams = p;
-       params_.masterFilename_ = b.fileName();
+       preview_->connect(boost::bind(&InsetInclude::statusChanged, this));
+       preview_->fileChanged(boost::bind(&InsetInclude::fileChanged, this));
 }
 
 
 InsetInclude::~InsetInclude()
 {
-       hideDialog();
+       InsetIncludeMailer mailer(*this);
+       mailer.hideDialog();
 }
 
 
-InsetInclude::Params const & InsetInclude::params() const
+dispatch_result
+InsetInclude::priv_dispatch(FuncRequest const & cmd, idx_type &, pos_type &)
+{
+       switch (cmd.action) {
+
+       case LFUN_INSET_MODIFY: {
+               InsetCommandParams p;
+               InsetIncludeMailer::string2params(cmd.argument, p);
+               if (!p.getCmdName().empty()) {
+                       set(p, *cmd.view()->buffer());
+                       cmd.view()->updateInset(this);
+               }
+               return DISPATCHED;
+       }
+
+       case LFUN_INSET_DIALOG_UPDATE:
+               InsetIncludeMailer(*this).updateDialog(cmd.view());
+               return DISPATCHED;
+
+       case LFUN_MOUSE_RELEASE:
+               if (button_.box().contains(cmd.x, cmd.y))
+                       InsetIncludeMailer(*this).showDialog(cmd.view());
+               return DISPATCHED;
+
+       case LFUN_INSET_DIALOG_SHOW:
+               InsetIncludeMailer(*this).showDialog(cmd.view());
+               return DISPATCHED;
+
+       default:
+               return UNDISPATCHED;
+       }
+}
+
+
+InsetCommandParams const & InsetInclude::params() const
 {
        return params_;
 }
 
 
-bool InsetInclude::Params::operator==(Params const & o) const
+namespace {
+
+/// the type of inclusion
+enum Types {
+       INCLUDE = 0,
+       VERB = 1,
+       INPUT = 2,
+       VERBAST = 3
+};
+
+
+Types type(InsetCommandParams const & params)
 {
-       if (cparams == o.cparams && flag == o.flag &&
-           noload == o.noload && masterFilename_ == o.masterFilename_)
-               return true;
+       string const command_name = params.getCmdName();
 
-       return false;
+       if (command_name == "input")
+               return INPUT;
+       if  (command_name == "verbatiminput")
+               return VERB;
+       if  (command_name == "verbatiminput*")
+               return VERBAST;
+       return INCLUDE;
 }
 
 
-bool InsetInclude::Params::operator!=(Params const & o) const
+bool isVerbatim(InsetCommandParams const & params)
 {
-       return !(*this == o);
+       string const command_name = params.getCmdName();
+       return command_name == "verbatiminput" ||
+               command_name == "verbatiminput*";
 }
 
 
-void InsetInclude::set(Params const & p)
+string const masterFilename(Buffer const & buffer)
 {
-       params_ = p;
+       return buffer.fileName();
+}
 
-       // Just to be safe...
-       string command;
-
-       switch (params_.flag) {
-               case INCLUDE:
-                       command="include";
-                       break;
-               case VERB:
-                       command="verbatiminput";
-                       break;
-               case INPUT:
-                       command="input";
-                       break;
-               case VERBAST:
-                       command="verbatiminput*";
-                       break;
-       }
 
-       params_.cparams.setCmdName(command);
+string const includedFilename(Buffer const & buffer,
+                             InsetCommandParams const & params)
+{
+       return MakeAbsPath(params.getContents(),
+                          OnlyPath(masterFilename(buffer)));
+}
+
 
-       if (preview_->monitoring())
-               preview_->stopMonitoring();
+void generate_preview(RenderPreview &, InsetInclude const &, Buffer const &);
 
-       if (grfx::PreviewedInset::activated() && params_.flag == INPUT)
-               preview_->generatePreview();
-}
+} // namespace anon
 
 
-Inset * InsetInclude::clone(Buffer const & buffer, bool) const
+void InsetInclude::set(InsetCommandParams const & p, Buffer const & buffer)
 {
-       Params p(params_);
-       p.masterFilename_ = buffer.fileName();
+       params_ = p;
+       set_label_ = false;
+
+       if (preview_->monitoring())
+               preview_->stopMonitoring();
 
-       return new InsetInclude(p);
+       if (type(params_) == INPUT)
+               generate_preview(*preview_, *this, buffer);
 }
 
 
-void InsetInclude::edit(BufferView * bv, int, int, mouse_button::state)
+auto_ptr<InsetBase> InsetInclude::clone() const
 {
-       bv->owner()->getDialogs()->showInclude(this);
+       return auto_ptr<InsetBase>(new InsetInclude(*this));
 }
 
 
-void InsetInclude::edit(BufferView * bv, bool)
+void InsetInclude::write(Buffer const &, ostream & os) const
 {
-       edit(bv, 0, 0, mouse_button::none);
+       write(os);
 }
 
 
-void InsetInclude::write(Buffer const *, ostream & os) const
+void InsetInclude::write(ostream & os) const
 {
-       os << "Include " << params_.cparams.getCommand() << '\n'
-          << "preview " << tostr(params_.cparams.preview()) << '\n';
+       os << "Include " << params_.getCommand() << '\n'
+          << "preview " << tostr(params_.preview()) << '\n';
 }
 
 
-void InsetInclude::read(Buffer const *, LyXLex & lex)
+void InsetInclude::read(Buffer const &, LyXLex & lex)
 {
-       params_.cparams.read(lex);
-
-       if (params_.cparams.getCmdName() == "include")
-               params_.flag = INCLUDE;
-       else if (params_.cparams.getCmdName() == "input")
-               params_.flag = INPUT;
-       /* FIXME: is this logic necessary now ? */
-       else if (contains(params_.cparams.getCmdName(), "verbatim")) {
-               params_.flag = VERB;
-               if (params_.cparams.getCmdName() == "verbatiminput*")
-                       params_.flag = VERBAST;
-       }
+       read(lex);
 }
 
 
-bool InsetInclude::display() const
+void InsetInclude::read(LyXLex & lex)
 {
-       return !(params_.flag == INPUT);
+       params_.read(lex);
 }
 
 
-string const InsetInclude::getScreenLabel(Buffer const *) const
+string const InsetInclude::getScreenLabel(Buffer const &) const
 {
        string temp;
 
-       switch (params_.flag) {
+       switch (type(params_)) {
                case INPUT: temp += _("Input"); break;
                case VERB: temp += _("Verbatim Input"); break;
                case VERBAST: temp += _("Verbatim Input*"); break;
@@ -222,116 +256,105 @@ string const InsetInclude::getScreenLabel(Buffer const *) const
 
        temp += ": ";
 
-       if (params_.cparams.getContents().empty())
+       if (params_.getContents().empty())
                temp += "???";
        else
-               temp += params_.cparams.getContents();
+               temp += OnlyFilename(params_.getContents());
 
        return temp;
 }
 
 
-string const InsetInclude::getRelFileBaseName() const
-{
-       return OnlyFilename(ChangeExtension(params_.cparams.getContents(), string()));
-}
-
-
-string const InsetInclude::getFileName() const
-{
-       return MakeAbsPath(params_.cparams.getContents(),
-                          OnlyPath(getMasterFilename()));
-}
-
-
-string const InsetInclude::getMasterFilename() const
-{
-       return params_.masterFilename_;
-}
-
+namespace {
 
-bool InsetInclude::loadIfNeeded() const
+/// return true if the file is or got loaded.
+bool loadIfNeeded(Buffer const & buffer, InsetCommandParams const & params)
 {
-       if (params_.noload || isVerbatim())
+       if (isVerbatim(params))
                return false;
 
-       if (!IsLyXFilename(getFileName()))
+       string const included_file = includedFilename(buffer, params);
+       if (!IsLyXFilename(included_file))
                return false;
 
-       if (bufferlist.exists(getFileName()))
+       if (bufferlist.exists(included_file))
                return true;
 
        // the readonly flag can/will be wrong, not anymore I think.
-       FileInfo finfo(getFileName());
+       FileInfo finfo(included_file);
        if (!finfo.isOK())
                return false;
-
-       return bufferlist.readFile(getFileName(), !finfo.writable()) != 0;
+       return loadLyXFile(bufferlist.newBuffer(included_file),
+                          included_file);
 }
 
 
-int InsetInclude::latex(Buffer const * buffer, ostream & os,
-                       bool /*fragile*/, bool /*fs*/) const
+} // namespace anon
+
+
+int InsetInclude::latex(Buffer const & buffer, ostream & os,
+                       LatexRunParams const & runparams) const
 {
-       string incfile(params_.cparams.getContents());
+       string incfile(params_.getContents());
 
        // Do nothing if no file name has been specified
        if (incfile.empty())
                return 0;
 
-       if (loadIfNeeded()) {
-               Buffer * tmp = bufferlist.getBuffer(getFileName());
+       string const included_file = includedFilename(buffer, params_);
+
+       if (loadIfNeeded(buffer, params_)) {
+               Buffer * tmp = bufferlist.getBuffer(included_file);
 
                // FIXME: this should be a GUI warning
-               if (tmp->params.textclass != buffer->params.textclass) {
+               if (tmp->params().textclass != buffer.params().textclass) {
                        lyxerr << "WARNING: Included file `"
-                              << MakeDisplayPath(getFileName())
+                              << MakeDisplayPath(included_file)
                               << "' has textclass `"
-                              << tmp->params.getLyXTextClass().name()
+                              << tmp->params().getLyXTextClass().name()
                               << "' while parent file has textclass `"
-                              << buffer->params.getLyXTextClass().name()
+                              << buffer.params().getLyXTextClass().name()
                               << "'." << endl;
                        //return 0;
                }
 
                // write it to a file (so far the complete file)
-               string writefile = ChangeExtension(getFileName(), ".tex");
+               string writefile = ChangeExtension(included_file, ".tex");
 
-               if (!buffer->tmppath.empty()
-                   && !buffer->niceFile) {
+               if (!buffer.temppath().empty() && !runparams.nice) {
                        incfile = subst(incfile, '/','@');
 #ifdef __EMX__
                        incfile = subst(incfile, ':', '$');
 #endif
-                       writefile = AddName(buffer->tmppath, incfile);
+                       writefile = AddName(buffer.temppath(), incfile);
                } else
-                       writefile = getFileName();
+                       writefile = included_file;
                writefile = ChangeExtension(writefile, ".tex");
                lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
                lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
 
-               tmp->markDepClean(buffer->tmppath);
+               tmp->markDepClean(buffer.temppath());
 
                tmp->makeLaTeXFile(writefile,
-                                  OnlyPath(getMasterFilename()),
-                                  buffer->niceFile, true);
+                                  OnlyPath(masterFilename(buffer)),
+                                  runparams, false);
        }
 
-       if (isVerbatim()) {
-               os << '\\' << params_.cparams.getCmdName() << '{' << incfile << '}';
-       } else if (params_.flag == INPUT) {
+       if (isVerbatim(params_)) {
+               os << '\\' << params_.getCmdName() << '{' << incfile << '}';
+       } else if (type(params_) == INPUT) {
                // \input wants file with extension (default is .tex)
-               if (!IsLyXFilename(getFileName())) {
-                       os << '\\' << params_.cparams.getCmdName() << '{' << incfile << '}';
+               if (!IsLyXFilename(included_file)) {
+                       os << '\\' << params_.getCmdName() << '{' << incfile << '}';
                } else {
-                       os << '\\' << params_.cparams.getCmdName() << '{'
+                       os << '\\' << params_.getCmdName() << '{'
                           << ChangeExtension(incfile, ".tex")
                           <<  '}';
                }
        } else {
                // \include don't want extension and demands that the
                // file really have .tex
-               os << '\\' << params_.cparams.getCmdName() << '{'
+               os << '\\' << params_.getCmdName() << '{'
                   << ChangeExtension(incfile, string())
                   << '}';
        }
@@ -340,45 +363,47 @@ int InsetInclude::latex(Buffer const * buffer, ostream & os,
 }
 
 
-int InsetInclude::ascii(Buffer const *, ostream & os, int) const
+int InsetInclude::ascii(Buffer const & buffer, ostream & os, int) const
 {
-       if (isVerbatim())
-               os << GetFileContents(getFileName());
+       if (isVerbatim(params_))
+               os << GetFileContents(includedFilename(buffer, params_));
        return 0;
 }
 
 
-int InsetInclude::linuxdoc(Buffer const * buffer, ostream & os) const
+int InsetInclude::linuxdoc(Buffer const & buffer, ostream & os) const
 {
-       string incfile(params_.cparams.getContents());
+       string incfile(params_.getContents());
 
        // Do nothing if no file name has been specified
        if (incfile.empty())
                return 0;
 
-       if (loadIfNeeded()) {
-               Buffer * tmp = bufferlist.getBuffer(getFileName());
+       string const included_file = includedFilename(buffer, params_);
+
+       if (loadIfNeeded(buffer, params_)) {
+               Buffer * tmp = bufferlist.getBuffer(included_file);
 
                // write it to a file (so far the complete file)
-               string writefile = ChangeExtension(getFileName(), ".sgml");
-               if (!buffer->tmppath.empty() && !buffer->niceFile) {
+               string writefile = ChangeExtension(included_file, ".sgml");
+               if (!buffer.temppath().empty() && !buffer.niceFile()) {
                        incfile = subst(incfile, '/','@');
-                       writefile = AddName(buffer->tmppath, incfile);
+                       writefile = AddName(buffer.temppath(), incfile);
                } else
-                       writefile = getFileName();
+                       writefile = included_file;
 
-               if (IsLyXFilename(getFileName()))
+               if (IsLyXFilename(included_file))
                        writefile = ChangeExtension(writefile, ".sgml");
 
                lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
                lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
 
-               tmp->makeLinuxDocFile(writefile, buffer->niceFile, true);
+               tmp->makeLinuxDocFile(writefile, buffer.niceFile(), true);
        }
 
-       if (isVerbatim()) {
+       if (isVerbatim(params_)) {
                os << "<![CDATA["
-                  << GetFileContents(getFileName())
+                  << GetFileContents(included_file)
                   << "]]>";
        } else
                os << '&' << include_label << ';';
@@ -387,35 +412,37 @@ int InsetInclude::linuxdoc(Buffer const * buffer, ostream & os) const
 }
 
 
-int InsetInclude::docbook(Buffer const * buffer, ostream & os,
+int InsetInclude::docbook(Buffer const & buffer, ostream & os,
                          bool /*mixcont*/) const
 {
-       string incfile(params_.cparams.getContents());
+       string incfile(params_.getContents());
 
        // Do nothing if no file name has been specified
        if (incfile.empty())
                return 0;
 
-       if (loadIfNeeded()) {
-               Buffer * tmp = bufferlist.getBuffer(getFileName());
+       string const included_file = includedFilename(buffer, params_);
+
+       if (loadIfNeeded(buffer, params_)) {
+               Buffer * tmp = bufferlist.getBuffer(included_file);
 
                // write it to a file (so far the complete file)
-               string writefile = ChangeExtension(getFileName(), ".sgml");
-               if (!buffer->tmppath.empty() && !buffer->niceFile) {
+               string writefile = ChangeExtension(included_file, ".sgml");
+               if (!buffer.temppath().empty() && !buffer.niceFile()) {
                        incfile = subst(incfile, '/','@');
-                       writefile = AddName(buffer->tmppath, incfile);
+                       writefile = AddName(buffer.temppath(), incfile);
                } else
-                       writefile = getFileName();
-               if (IsLyXFilename(getFileName()))
+                       writefile = included_file;
+               if (IsLyXFilename(included_file))
                        writefile = ChangeExtension(writefile, ".sgml");
 
                lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
                lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
 
-               tmp->makeDocBookFile(writefile, buffer->niceFile, true);
+               tmp->makeDocBookFile(writefile, buffer.niceFile(), true);
        }
 
-       if (isVerbatim()) {
+       if (isVerbatim(params_)) {
                os << "<inlinegraphic fileref=\""
                   << '&' << include_label << ';'
                   << "\" format=\"linespecific\">";
@@ -428,160 +455,232 @@ int InsetInclude::docbook(Buffer const * buffer, ostream & os,
 
 void InsetInclude::validate(LaTeXFeatures & features) const
 {
-
-       string incfile(params_.cparams.getContents());
+       string incfile(params_.getContents());
        string writefile;
 
-       Buffer const * const b = bufferlist.getBuffer(getMasterFilename());
+       Buffer const & buffer = features.buffer();
+
+       string const included_file = includedFilename(buffer, params_);
 
-       if (b && !b->tmppath.empty() && !b->niceFile && !isVerbatim()) {
+       if (!buffer.temppath().empty() &&
+           !buffer.niceFile() &&
+           !isVerbatim(params_)) {
                incfile = subst(incfile, '/','@');
-               writefile = AddName(b->tmppath, incfile);
+               writefile = AddName(buffer.temppath(), incfile);
        } else
-               writefile = getFileName();
+               writefile = included_file;
 
-       if (IsLyXFilename(getFileName()))
+       if (IsLyXFilename(included_file))
                writefile = ChangeExtension(writefile, ".sgml");
 
        features.includeFile(include_label, writefile);
 
-       if (isVerbatim())
+       if (isVerbatim(params_))
                features.require("verbatim");
 
        // Here we must do the fun stuff...
        // Load the file in the include if it needs
        // to be loaded:
-       if (loadIfNeeded()) {
+       if (loadIfNeeded(buffer, params_)) {
                // a file got loaded
-               Buffer * const tmp = bufferlist.getBuffer(getFileName());
+               Buffer * const tmp = bufferlist.getBuffer(included_file);
                if (tmp) {
-                       if (b)
-                               tmp->niceFile = b->niceFile;
+                       tmp->niceFile() = buffer.niceFile();
                        tmp->validate(features);
                }
        }
 }
 
 
-vector<string> const InsetInclude::getLabelList() const
+void InsetInclude::getLabelList(Buffer const & buffer,
+                               std::vector<string> & list) const
 {
-       vector<string> l;
-
-       if (loadIfNeeded()) {
-               Buffer * tmp = bufferlist.getBuffer(getFileName());
+       if (loadIfNeeded(buffer, params_)) {
+               string const included_file = includedFilename(buffer, params_);
+               Buffer * tmp = bufferlist.getBuffer(included_file);
                tmp->setParentName("");
-               l = tmp->getLabelList();
-               tmp->setParentName(getMasterFilename());
+               tmp->getLabelList(list);
+               tmp->setParentName(masterFilename(buffer));
        }
-
-       return l;
 }
 
 
-vector<pair<string,string> > const InsetInclude::getKeys() const
+void InsetInclude::fillWithBibKeys(Buffer const & buffer,
+                                  std::vector<std::pair<string,string> > & keys) const
 {
-       vector<pair<string,string> > keys;
-
-       if (loadIfNeeded()) {
-               Buffer * tmp = bufferlist.getBuffer(getFileName());
+       if (loadIfNeeded(buffer, params_)) {
+               string const included_file = includedFilename(buffer, params_);
+               Buffer * tmp = bufferlist.getBuffer(included_file);
                tmp->setParentName("");
-               keys = tmp->getBibkeyList();
-               tmp->setParentName(getMasterFilename());
+               tmp->fillWithBibKeys(keys);
+               tmp->setParentName(masterFilename(buffer));
        }
-
-       return keys;
 }
 
 
-int InsetInclude::ascent(BufferView * bv, LyXFont const & font) const
+void InsetInclude::metrics(MetricsInfo & mi, Dimension & dim) const
 {
-       return preview_->previewReady() ?
-               preview_->pimage()->ascent() : InsetButton::ascent(bv, font);
+       if (RenderPreview::activated() && preview_->previewReady()) {
+               preview_->metrics(mi, dim);
+       } else {
+               if (!set_label_) {
+                       set_label_ = true;
+                       button_.update(getScreenLabel(*mi.base.bv->buffer()),
+                                      editable() != NOT_EDITABLE);
+               }
+               button_.metrics(mi, dim);
+       }
+       int center_indent = type(params_) == INPUT ?
+               0 : (mi.base.textwidth - dim.wid) / 2;
+       Box b(center_indent, center_indent + dim.wid, -dim.asc, dim.des);
+       button_.setBox(b);
+
+       dim.wid = mi.base.textwidth;
+       dim_ = dim;
 }
 
 
-int InsetInclude::descent(BufferView * bv, LyXFont const & font) const
+void InsetInclude::draw(PainterInfo & pi, int x, int y) const
 {
-       return preview_->previewReady() ?
-               preview_->pimage()->descent() : InsetButton::descent(bv, font);
+       if (!RenderPreview::activated() || !preview_->previewReady()) {
+               button_.draw(pi, x + button_.box().x1, y);
+               return;
+       }
+
+       BOOST_ASSERT(pi.base.bv);
+       Buffer const * const buffer = pi.base.bv->buffer();
+       if (!preview_->monitoring() && buffer) {
+               string const included_file = includedFilename(*buffer, params_);
+               preview_->startMonitoring(included_file);
+       }
+
+       preview_->draw(pi, x + button_.box().x1, y);
 }
 
 
-int InsetInclude::width(BufferView * bv, LyXFont const & font) const
+//
+// preview stuff
+//
+
+void InsetInclude::statusChanged() const
 {
-       return preview_->previewReady() ?
-               preview_->pimage()->width() : InsetButton::width(bv, font);
+       LyX::cref().updateInset(this);
 }
 
 
-void InsetInclude::draw(BufferView * bv, LyXFont const & font, int y,
-                       float & xx, bool b) const
+void InsetInclude::fileChanged() const
 {
-       preview_->setView(bv);
-       if (!preview_->previewReady()) {
-               InsetButton::draw(bv, font, y, xx, b);
+       Buffer const * const buffer_ptr = LyX::cref().updateInset(this);
+       if (!buffer_ptr)
                return;
-       }
 
-       if (!preview_->monitoring())
-               preview_->startMonitoring();
+       Buffer const & buffer = *buffer_ptr;
+       preview_->removePreview(buffer);
+       generate_preview(*preview_.get(), *this, buffer);
+}
+
 
-       int const x = int(xx);
-       int const w = width(bv, font);
-       int const d = descent(bv, font);
-       int const a = ascent(bv, font);
-       int const h = a + d;
+namespace {
 
-       bv->painter().image(x, y - a, w, h,
-                           *(preview_->pimage()->image(*this, *bv)));
+bool preview_wanted(InsetCommandParams const & params, Buffer const & buffer)
+{
+       string const included_file = includedFilename(buffer, params);
 
-       xx += w;
+       return type(params) == INPUT && params.preview() &&
+               IsFileReadable(included_file);
 }
 
 
-//
-// preview stuff
-//
-
-void InsetInclude::addPreview(grfx::PreviewLoader & ploader) const
+string const latex_string(InsetInclude const & inset, Buffer const & buffer)
 {
-       preview_->addPreview(ploader);
+       ostringstream os;
+       LatexRunParams runparams;
+       runparams.flavor = LatexRunParams::LATEX;
+       inset.latex(buffer, os, runparams);
+
+       return os.str();
 }
 
 
-bool InsetInclude::PreviewImpl::previewWanted() const
+void generate_preview(RenderPreview & renderer,
+                     InsetInclude const & inset,
+                     Buffer const & buffer)
 {
-       return parent().params_.flag == InsetInclude::INPUT &&
-               parent().params_.cparams.preview() &&
-               IsFileReadable(parent().getFileName());
+       InsetCommandParams const & params = inset.params();
+       if (RenderPreview::activated() && preview_wanted(params, buffer)) {
+               string const snippet = latex_string(inset, buffer);
+               renderer.generatePreview(snippet, buffer);
+       }
 }
 
+} // namespace anon
+
 
-string const InsetInclude::PreviewImpl::latexString() const
+void InsetInclude::addPreview(lyx::graphics::PreviewLoader & ploader) const
 {
-       if (!view() || !view()->buffer())
-               return string();
+       if (preview_wanted(params(), ploader.buffer())) {
+               string const snippet = latex_string(*this, ploader.buffer());
+               preview_->addPreview(snippet, ploader);
+       }
+}
+
+
+string const InsetIncludeMailer::name_("include");
+
+InsetIncludeMailer::InsetIncludeMailer(InsetInclude & inset)
+       : inset_(inset)
+{}
 
-       ostringstream os;
-       parent().latex(view()->buffer(), os, false, false);
 
-       return os.str().c_str();
+string const InsetIncludeMailer::inset2string(Buffer const &) const
+{
+       return params2string(inset_.params());
 }
 
 
-void InsetInclude::PreviewImpl::startMonitoring()
+void InsetIncludeMailer::string2params(string const & in,
+                                      InsetCommandParams & params)
 {
-       monitor_.reset(new FileMonitor(parent().getFileName(), 2000));
-       monitor_->connect(boost::bind(&PreviewImpl::restartLoading, this));
-       monitor_->start();
+       params = InsetCommandParams();
+
+       if (in.empty())
+               return;
+
+       istringstream data(in);
+       LyXLex lex(0,0);
+       lex.setStream(data);
+
+       if (lex.isOK()) {
+               lex.next();
+               string const token = lex.getString();
+               if (token != name_)
+                       return;
+       }
+
+       // This is part of the inset proper that is usually swallowed
+       // by Buffer::readInset
+       if (lex.isOK()) {
+               lex.next();
+               string const token = lex.getString();
+               if (token != "Include")
+                       return;
+       }
+
+       if (lex.isOK()) {
+               InsetInclude inset(params);
+               inset.read(lex);
+               params = inset.params();
+       }
 }
 
 
-void InsetInclude::PreviewImpl::restartLoading()
+string const
+InsetIncludeMailer::params2string(InsetCommandParams const & params)
 {
-       lyxerr << "restartLoading()" << std::endl;
-       removePreview();
-       if (view())
-               view()->updateInset(&parent(), false);
-       generatePreview();
+       InsetInclude inset(params);
+       ostringstream data;
+       data << name_ << ' ';
+       inset.write(data);
+       data << "\\end_inset\n";
+       return data.str();
 }