]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetGraphics.cpp
pimpl not needed here
[lyx.git] / src / insets / InsetGraphics.cpp
index 23dda7899f7412f2b29b301108857d39868afaea..7d1ea0bd4d81c8828234bd15136b314ed30b789c 100644 (file)
@@ -58,6 +58,7 @@ TODO
 #include "Cursor.h"
 #include "debug.h"
 #include "DispatchResult.h"
+#include "ErrorList.h"
 #include "Exporter.h"
 #include "Format.h"
 #include "FuncRequest.h"
@@ -70,12 +71,13 @@ TODO
 #include "Mover.h"
 #include "OutputParams.h"
 #include "sgml.h"
+#include "EmbeddedFiles.h"
 
 #include "frontends/alert.h"
 
 #include "support/convert.h"
+#include "support/docstream.h"
 #include "support/filetools.h"
-#include "support/lyxalgo.h" // count
 #include "support/lyxlib.h" // sum
 #include "support/lstrings.h"
 #include "support/os.h"
@@ -84,6 +86,7 @@ TODO
 #include <boost/bind.hpp>
 #include <boost/tuple/tuple.hpp>
 
+#include <algorithm>
 #include <sstream>
 
 
@@ -97,19 +100,19 @@ using support::DocFileName;
 using support::FileName;
 using support::float_equal;
 using support::getExtension;
-using support::isFileReadable;
+using support::isValidLaTeXFilename;
 using support::latex_path;
 using support::onlyFilename;
 using support::removeExtension;
 using support::rtrim;
 using support::subst;
+using support::suffixIs;
 using support::Systemcall;
 using support::unzipFile;
 using support::unzippedFileName;
 
 using std::endl;
 using std::string;
-using std::auto_ptr;
 using std::istringstream;
 using std::ostream;
 using std::ostringstream;
@@ -162,9 +165,9 @@ InsetGraphics::InsetGraphics(InsetGraphics const & ig)
 }
 
 
-auto_ptr<Inset> InsetGraphics::doClone() const
+Inset * InsetGraphics::clone() const
 {
-       return auto_ptr<Inset>(new InsetGraphics(*this));
+       return new InsetGraphics(*this);
 }
 
 
@@ -178,7 +181,7 @@ void InsetGraphics::doDispatch(Cursor & cur, FuncRequest & cmd)
 {
        switch (cmd.action) {
        case LFUN_GRAPHICS_EDIT: {
-               Buffer const & buffer = *cur.bv().buffer();
+               Buffer const & buffer = cur.bv().buffer();
                InsetGraphicsParams p;
                InsetGraphicsMailer::string2params(to_utf8(cmd.argument()), buffer, p);
                editGraphics(p, buffer);
@@ -228,24 +231,40 @@ bool InsetGraphics::getStatus(Cursor & cur, FuncRequest const & cmd,
 }
 
 
+void InsetGraphics::registerEmbeddedFiles(Buffer const &, 
+       EmbeddedFiles & files) const
+{
+       files.registerFile(params().filename.absFilename(), 
+               false, this);
+}
+
+
+void InsetGraphics::updateEmbeddedFile(Buffer const & buf,
+       EmbeddedFile const & file)
+{
+       BOOST_ASSERT(buf.embeddedFiles().enabled());
+       params_.filename = file;
+       LYXERR(Debug::FILES) << "Update InsetGraphic with File " 
+               << params_.filename.toFilesystemEncoding() 
+               << ", embedding status: "
+               << params_.filename.embedded() << std::endl;
+}
+
+
 void InsetGraphics::edit(Cursor & cur, bool)
 {
        InsetGraphicsMailer(*this).showDialog(&cur.bv());
 }
 
 
-bool InsetGraphics::metrics(MetricsInfo & mi, Dimension & dim) const
+void InsetGraphics::metrics(MetricsInfo & mi, Dimension & dim) const
 {
        graphic_->metrics(mi, dim);
-       bool const changed = dim_ != dim;
-       dim_ = dim;
-       return changed;
 }
 
 
 void InsetGraphics::draw(PainterInfo & pi, int x, int y) const
 {
-       setPosCache(pi, x, y);
        graphic_->draw(pi, x, y);
 }
 
@@ -259,7 +278,7 @@ Inset::EDITABLE InsetGraphics::editable() const
 void InsetGraphics::write(Buffer const & buf, ostream & os) const
 {
        os << "Graphics\n";
-       params().Write(os, buf.filePath());
+       params().Write(os, buf);
 }
 
 
@@ -272,6 +291,16 @@ void InsetGraphics::read(Buffer const & buf, Lexer & lex)
        else
                LYXERR(Debug::GRAPHICS) << "Not a Graphics inset!" << endl;
 
+       // InsetGraphics is read, with filename in params_. We do not know if this file actually
+       // exists or is embedded so we need to get the 'availableFile' from buf.embeddedFiles()
+       if (buf.embeddedFiles().enabled()) {
+               EmbeddedFiles::EmbeddedFileList::const_iterator it = 
+                       buf.embeddedFiles().find(params_.filename.toFilesystemEncoding());
+               if (it != buf.embeddedFiles().end())
+                       // using available file, embedded or external, depending on file availability and
+                       // embedding status.
+                       params_.filename = *it;
+       }
        graphic_->update(params().as_grfxParams());
 }
 
@@ -312,18 +341,21 @@ string const InsetGraphics::createLatexOptions() const
            options << "draft,";
        if (params().clip)
            options << "clip,";
+       ostringstream size;
        double const scl = convert<double>(params().scale);
        if (!params().scale.empty() && !float_equal(scl, 0.0, 0.05)) {
                if (!float_equal(scl, 100.0, 0.05))
-                       options << "scale=" << scl / 100.0 << ',';
+                       size << "scale=" << scl / 100.0 << ',';
        } else {
                if (!params().width.zero())
-                       options << "width=" << params().width.asLatexString() << ',';
+                       size << "width=" << params().width.asLatexString() << ',';
                if (!params().height.zero())
-                       options << "height=" << params().height.asLatexString() << ',';
+                       size << "height=" << params().height.asLatexString() << ',';
                if (params().keepAspectRatio)
-                       options << "keepaspectratio,";
+                       size << "keepaspectratio,";
        }
+       if (params().scaleBeforeRotation && !size.str().empty())
+               options << size.str();
 
        // Make sure rotation angle is not very close to zero;
        // a float can be effectively zero but not exactly zero.
@@ -341,13 +373,18 @@ string const InsetGraphics::createLatexOptions() const
                options << ',';
            }
        }
+       if (!params().scaleBeforeRotation && !size.str().empty())
+               options << size.str();
 
        if (!params().special.empty())
            options << params().special << ',';
 
        string opts = options.str();
        // delete last ','
-       return opts.substr(0, opts.size() - 1);
+       if (suffixIs(opts, ','))
+               opts = opts.substr(0, opts.size() - 1);
+
+       return opts;
 }
 
 
@@ -413,7 +450,8 @@ docstring const InsetGraphics::createDocBookAttributes() const
        // Calculate the options part of the command, we must do it to a string
        // stream since we copied the code from createLatexParams() ;-)
 
-       // FIXME: av: need to translate spec -> Docbook XSL spec (http://www.sagehill.net/docbookxsl/ImageSizing.html)
+       // FIXME: av: need to translate spec -> Docbook XSL spec
+       // (http://www.sagehill.net/docbookxsl/ImageSizing.html)
        // Right now it only works with my version of db2latex :-)
 
        odocstringstream options;
@@ -447,7 +485,7 @@ docstring const InsetGraphics::createDocBookAttributes() const
 
 namespace {
 
-enum CopyStatus {
+enum GraphicsCopyStatus {
        SUCCESS,
        FAILURE,
        IDENTICAL_PATHS,
@@ -455,7 +493,7 @@ enum CopyStatus {
 };
 
 
-std::pair<CopyStatus, FileName> const
+std::pair<GraphicsCopyStatus, FileName> const
 copyFileIfNeeded(FileName const & file_in, FileName const & file_out)
 {
        unsigned long const checksum_in  = support::sum(file_in);
@@ -476,12 +514,12 @@ copyFileIfNeeded(FileName const & file_in, FileName const & file_out)
                        << std::endl;
        }
 
-       CopyStatus status = success ? SUCCESS : FAILURE;
+       GraphicsCopyStatus status = success ? SUCCESS : FAILURE;
        return std::make_pair(status, file_out);
 }
 
 
-std::pair<CopyStatus, FileName> const
+std::pair<GraphicsCopyStatus, FileName> const
 copyToDirIfNeeded(DocFileName const & file, string const & dir)
 {
        using support::rtrim;
@@ -569,34 +607,41 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
 
        // The master buffer. This is useful when there are multiple levels
        // of include files
-       Buffer const * m_buffer = buf.getMasterBuffer();
+       Buffer const * masterBuffer = buf.masterBuffer();
 
        // Return the output name if we are inside a comment or the file does
        // not exist.
        // We are not going to change the extension or using the name of the
        // temporary file, the code is already complicated enough.
-       if (runparams.inComment || !isFileReadable(params().filename))
-               return params().filename.outputFilename(m_buffer->filePath());
+       if (runparams.inComment || !params().filename.isFileReadable())
+               return params().filename.outputFilename(masterBuffer->filePath());
 
        // We place all temporary files in the master buffer's temp dir.
        // This is possible because we use mangled file names.
        // This is necessary for DVI export.
-       string const temp_path = m_buffer->temppath();
+       string const temp_path = masterBuffer->temppath();
 
-       CopyStatus status;
+       GraphicsCopyStatus status;
        boost::tie(status, temp_file) =
                        copyToDirIfNeeded(params().filename, temp_path);
 
        if (status == FAILURE)
                return orig_file;
 
-       // a relative filename should be relative to the master
-       // buffer.
+       // a relative filename should be relative to the master buffer.
        // "nice" means that the buffer is exported to LaTeX format but not
-       //        run through the LaTeX compiler.
-       string output_file = support::os::external_path(runparams.nice ?
-               params().filename.outputFilename(m_buffer->filePath()) :
-               onlyFilename(temp_file.absFilename()));
+       // run through the LaTeX compiler.
+       string output_file = runparams.nice ?
+               params().filename.outputFilename(masterBuffer->filePath()) :
+               onlyFilename(temp_file.absFilename());
+
+       if (runparams.nice && !isValidLaTeXFilename(output_file)) {
+               frontend::Alert::warning(_("Invalid filename"),
+                                        _("The following filename is likely to cause trouble "
+                                          "when running the exported file through LaTeX: ") +
+                                           from_utf8(output_file));
+       }
+
        FileName source_file = runparams.nice ? FileName(params().filename) : temp_file;
        string const tex_format = (runparams.flavor == OutputParams::LATEX) ?
                        "latex" : "pdflatex";
@@ -726,8 +771,8 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
        // FIXME (Abdel 12/08/06): Is there a need to show these errors?
        ErrorList el;
        if (theConverters().convert(&buf, temp_file, to_file, params().filename,
-                              from, to, el,
-                              Converters::try_default | Converters::try_cache)) {
+                              from, to, el,
+                              Converters::try_default | Converters::try_cache)) {
                runparams.exportdata->addExternalFile(tex_format,
                                to_file, output_to_file);
                runparams.exportdata->addExternalFile("dvi",
@@ -739,7 +784,7 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
 
 
 int InsetGraphics::latex(Buffer const & buf, odocstream & os,
-                         OutputParams const & runparams) const
+                        OutputParams const & runparams) const
 {
        // If there is no file specified or not existing,
        // just output a message about it in the latex output.
@@ -750,8 +795,8 @@ int InsetGraphics::latex(Buffer const & buf, odocstream & os,
        string const relative_file =
                params().filename.relFilename(buf.filePath());
 
-       bool const file_exists = !params().filename.empty() &&
-                                isFileReadable(params().filename);
+       bool const file_exists = !params().filename.empty()
+                       && params().filename.isFileReadable();
        string const message = file_exists ?
                string() : string("bb = 0 0 200 100, draft, type=eps");
        // if !message.empty() then there was no existing file
@@ -804,12 +849,12 @@ int InsetGraphics::latex(Buffer const & buf, odocstream & os,
        LYXERR(Debug::GRAPHICS) << "InsetGraphics::latex outputting:\n"
                                << latex_str << endl;
        // Return how many newlines we issued.
-       return int(lyx::count(latex_str.begin(), latex_str.end(),'\n'));
+       return int(std::count(latex_str.begin(), latex_str.end(),'\n'));
 }
 
 
 int InsetGraphics::plaintext(Buffer const & buf, odocstream & os,
-                             OutputParams const &) const
+                            OutputParams const &) const
 {
        // No graphics in ascii output. Possible to use gifscii to convert
        // images to ascii approximation.
@@ -820,7 +865,7 @@ int InsetGraphics::plaintext(Buffer const & buf, odocstream & os,
        // FIXME: We have no idea what the encoding of the filename is
 
        docstring const str = bformat(buf.B_("Graphics file: %1$s"),
-                                     from_utf8(params().filename.absFilename()));
+                                     from_utf8(params().filename.absFilename()));
        os << '<' << str << '>';
 
        return 2 + str.size();
@@ -829,21 +874,24 @@ int InsetGraphics::plaintext(Buffer const & buf, odocstream & os,
 
 namespace {
 
-int writeImageObject(char * format, odocstream & os, OutputParams const & runparams,
-                     docstring const graphic_label, docstring const attributes)
+int writeImageObject(char const * format,
+                     odocstream & os,
+                     OutputParams const & runparams,
+                    docstring const & graphic_label,
+                     docstring const & attributes)
 {
                if (runparams.flavor != OutputParams::XML) {
                        os << "<![ %output.print."
-                           << format
-                           << "; ["
-                           << std::endl;
+                          << format
+                          << "; ["
+                          << std::endl;
                }
                os <<"<imageobject><imagedata fileref=\"&"
                   << graphic_label
-                   << ";."
-                   << format
-                   << "\" "
-                   << attributes;
+                  << ";."
+                  << format
+                  << "\" "
+                  << attributes;
                if (runparams.flavor == OutputParams::XML) {
                        os <<  " role=\"" << format << "\"/>" ;
                }
@@ -902,8 +950,8 @@ void InsetGraphics::validate(LaTeXFeatures & features) const
        features.require("graphicx");
 
        if (features.runparams().nice) {
-               Buffer const * m_buffer = features.buffer().getMasterBuffer();
-               string const rel_file = removeExtension(params().filename.relFilename(m_buffer->filePath()));
+               Buffer const * masterBuffer = features.buffer().masterBuffer();
+               string const rel_file = removeExtension(params().filename.relFilename(masterBuffer->filePath()));
                if (contains(rel_file, "."))
                        features.require("lyxdot");
        }
@@ -986,7 +1034,7 @@ InsetGraphicsMailer::params2string(InsetGraphicsParams const & params,
 {
        ostringstream data;
        data << name_ << ' ';
-       params.Write(data, buffer.filePath());
+       params.Write(data, buffer);
        data << "\\end_inset\n";
        return data.str();
 }