]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetGraphics.cpp
Embedding: prepare to read/write manifest in .lyx file
[lyx.git] / src / insets / InsetGraphics.cpp
index 0b0e9dc533d26110414f41af6b743cd06a2978b0..70cfe9767d719a3d35a8a24788fe9cca231b2310 100644 (file)
@@ -52,38 +52,40 @@ TODO
 #include "insets/InsetGraphics.h"
 #include "insets/RenderGraphic.h"
 
-#include "buffer.h"
+#include "Buffer.h"
 #include "BufferView.h"
-#include "converter.h"
-#include "cursor.h"
+#include "Converter.h"
+#include "Cursor.h"
 #include "debug.h"
-#include "dispatchresult.h"
-#include "exporter.h"
-#include "format.h"
-#include "funcrequest.h"
+#include "DispatchResult.h"
+#include "ErrorList.h"
+#include "Exporter.h"
+#include "Format.h"
+#include "FuncRequest.h"
 #include "FuncStatus.h"
 #include "gettext.h"
 #include "LaTeXFeatures.h"
-#include "lyxlength.h"
-#include "lyxlex.h"
-#include "metricsinfo.h"
-#include "mover.h"
-#include "outputparams.h"
+#include "Length.h"
+#include "Lexer.h"
+#include "MetricsInfo.h"
+#include "Mover.h"
+#include "OutputParams.h"
 #include "sgml.h"
+#include "EmbeddedFiles.h"
 
-#include "frontends/Alert.h"
+#include "frontends/alert.h"
 
 #include "support/convert.h"
 #include "support/filetools.h"
-#include "support/lyxalgo.h" // count
 #include "support/lyxlib.h" // sum
 #include "support/lstrings.h"
 #include "support/os.h"
-#include "support/systemcall.h"
+#include "support/Systemcall.h"
 
 #include <boost/bind.hpp>
 #include <boost/tuple/tuple.hpp>
 
+#include <algorithm>
 #include <sstream>
 
 
@@ -98,18 +100,19 @@ 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;
@@ -153,7 +156,7 @@ InsetGraphics::InsetGraphics()
 
 
 InsetGraphics::InsetGraphics(InsetGraphics const & ig)
-       : InsetOld(ig),
+       : Inset(ig),
          boost::signals::trackable(),
                graphic_label(sgml::uniqueID(from_ascii("graph"))),
          graphic_(new RenderGraphic(*ig.graphic_, this))
@@ -162,9 +165,9 @@ InsetGraphics::InsetGraphics(InsetGraphics const & ig)
 }
 
 
-auto_ptr<InsetBase> InsetGraphics::doClone() const
+Inset * InsetGraphics::clone() const
 {
-       return auto_ptr<InsetBase>(new InsetGraphics(*this));
+       return new InsetGraphics(*this);
 }
 
 
@@ -174,11 +177,11 @@ InsetGraphics::~InsetGraphics()
 }
 
 
-void InsetGraphics::doDispatch(LCursor & cur, FuncRequest & cmd)
+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);
@@ -201,17 +204,18 @@ void InsetGraphics::doDispatch(LCursor & cur, FuncRequest & cmd)
                break;
 
        case LFUN_MOUSE_RELEASE:
-               InsetGraphicsMailer(*this).showDialog(&cur.bv());
+               if (!cur.selection())
+                       InsetGraphicsMailer(*this).showDialog(&cur.bv());
                break;
 
        default:
-               InsetBase::doDispatch(cur, cmd);
+               Inset::doDispatch(cur, cmd);
                break;
        }
 }
 
 
-bool InsetGraphics::getStatus(LCursor & cur, FuncRequest const & cmd,
+bool InsetGraphics::getStatus(Cursor & cur, FuncRequest const & cmd,
                FuncStatus & flag) const
 {
        switch (cmd.action) {
@@ -222,12 +226,20 @@ bool InsetGraphics::getStatus(LCursor & cur, FuncRequest const & cmd,
                return true;
 
        default:
-               return InsetBase::getStatus(cur, cmd, flag);
+               return Inset::getStatus(cur, cmd, flag);
        }
 }
 
 
-void InsetGraphics::edit(LCursor & cur, bool)
+void InsetGraphics::registerEmbeddedFiles(Buffer const &, 
+       EmbeddedFiles & files) const
+{
+       files.registerFile(params().filename.absFilename(), 
+               false, this);
+}
+
+
+void InsetGraphics::edit(Cursor & cur, bool)
 {
        InsetGraphicsMailer(*this).showDialog(&cur.bv());
 }
@@ -249,7 +261,7 @@ void InsetGraphics::draw(PainterInfo & pi, int x, int y) const
 }
 
 
-InsetBase::EDITABLE InsetGraphics::editable() const
+Inset::EDITABLE InsetGraphics::editable() const
 {
        return IS_EDITABLE;
 }
@@ -258,11 +270,11 @@ InsetBase::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);
 }
 
 
-void InsetGraphics::read(Buffer const & buf, LyXLex & lex)
+void InsetGraphics::read(Buffer const & buf, Lexer & lex)
 {
        string const token = lex.getString();
 
@@ -271,11 +283,21 @@ void InsetGraphics::read(Buffer const & buf, LyXLex & 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 = DocFileName(it->availableFile(&buf));
+       }
        graphic_->update(params().as_grfxParams());
 }
 
 
-void InsetGraphics::readInsetGraphics(LyXLex & lex, string const & bufpath)
+void InsetGraphics::readInsetGraphics(Lexer & lex, string const & bufpath)
 {
        bool finished = false;
 
@@ -311,18 +333,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.
@@ -340,63 +365,68 @@ 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;
 }
 
 
-docstring const InsetGraphics::toDocbookLength(LyXLength const & len) const
+docstring const InsetGraphics::toDocbookLength(Length const & len) const
 {
        odocstringstream result;
        switch (len.unit()) {
-               case LyXLength::SP: // Scaled point (65536sp = 1pt) TeX's smallest unit.
+               case Length::SP: // Scaled point (65536sp = 1pt) TeX's smallest unit.
                        result << len.value() * 65536.0 * 72 / 72.27 << "pt";
                        break;
-               case LyXLength::PT: // Point = 1/72.27in = 0.351mm
+               case Length::PT: // Point = 1/72.27in = 0.351mm
                        result << len.value() * 72 / 72.27 << "pt";
                        break;
-               case LyXLength::BP: // Big point (72bp = 1in), also PostScript point
+               case Length::BP: // Big point (72bp = 1in), also PostScript point
                        result << len.value() << "pt";
                        break;
-               case LyXLength::DD: // Didot point = 1/72 of a French inch, = 0.376mm
+               case Length::DD: // Didot point = 1/72 of a French inch, = 0.376mm
                        result << len.value() * 0.376 << "mm";
                        break;
-               case LyXLength::MM: // Millimeter = 2.845pt
+               case Length::MM: // Millimeter = 2.845pt
                        result << len.value() << "mm";
                        break;
-               case LyXLength::PC: // Pica = 12pt = 4.218mm
+               case Length::PC: // Pica = 12pt = 4.218mm
                        result << len.value() << "pc";
                        break;
-               case LyXLength::CC: // Cicero = 12dd = 4.531mm
+               case Length::CC: // Cicero = 12dd = 4.531mm
                        result << len.value() * 4.531 << "mm";
                        break;
-               case LyXLength::CM: // Centimeter = 10mm = 2.371pc
+               case Length::CM: // Centimeter = 10mm = 2.371pc
                        result << len.value() << "cm";
                        break;
-               case LyXLength::IN: // Inch = 25.4mm = 72.27pt = 6.022pc
+               case Length::IN: // Inch = 25.4mm = 72.27pt = 6.022pc
                        result << len.value() << "in";
                        break;
-               case LyXLength::EX: // Height of a small "x" for the current font.
+               case Length::EX: // Height of a small "x" for the current font.
                        // Obviously we have to compromise here. Any better ratio than 1.5 ?
                        result << len.value() / 1.5 << "em";
                        break;
-               case LyXLength::EM: // Width of capital "M" in current font.
+               case Length::EM: // Width of capital "M" in current font.
                        result << len.value() << "em";
                        break;
-               case LyXLength::MU: // Math unit (18mu = 1em) for positioning in math mode
+               case Length::MU: // Math unit (18mu = 1em) for positioning in math mode
                        result << len.value() * 18 << "em";
                        break;
-               case LyXLength::PTW: // Percent of TextWidth
-               case LyXLength::PCW: // Percent of ColumnWidth
-               case LyXLength::PPW: // Percent of PageWidth
-               case LyXLength::PLW: // Percent of LineWidth
-               case LyXLength::PTH: // Percent of TextHeight
-               case LyXLength::PPH: // Percent of Paper
+               case Length::PTW: // Percent of TextWidth
+               case Length::PCW: // Percent of ColumnWidth
+               case Length::PPW: // Percent of PageWidth
+               case Length::PLW: // Percent of LineWidth
+               case Length::PTH: // Percent of TextHeight
+               case Length::PPH: // Percent of Paper
                        // Sigh, this will go wrong.
                        result << len.value() << "%";
                        break;
@@ -596,6 +626,14 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
        string output_file = support::os::external_path(runparams.nice ?
                params().filename.outputFilename(m_buffer->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";
@@ -725,8 +763,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",
@@ -738,7 +776,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,7 +788,7 @@ int InsetGraphics::latex(Buffer const & buf, odocstream & os,
                params().filename.relFilename(buf.filePath());
 
        bool const file_exists = !params().filename.empty() &&
-                                isFileReadable(params().filename);
+                                isFileReadable(params().filename);
        string const message = file_exists ?
                string() : string("bb = 0 0 200 100, draft, type=eps");
        // if !message.empty() then there was no existing file
@@ -803,12 +841,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 &, odocstream & os,
-                             OutputParams const &) const
+int InsetGraphics::plaintext(Buffer const & buf, odocstream & os,
+                            OutputParams const &) const
 {
        // No graphics in ascii output. Possible to use gifscii to convert
        // images to ascii approximation.
@@ -818,8 +856,8 @@ int InsetGraphics::plaintext(Buffer const &, odocstream & os,
        // FIXME UNICODE
        // FIXME: We have no idea what the encoding of the filename is
 
-       docstring const str = bformat(_("Graphics file: %1$s"),
-                                     from_utf8(params().filename.absFilename()));
+       docstring const str = bformat(buf.B_("Graphics file: %1$s"),
+                                     from_utf8(params().filename.absFilename()));
        os << '<' << str << '>';
 
        return 2 + str.size();
@@ -828,21 +866,24 @@ int InsetGraphics::plaintext(Buffer const &, 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 << "\"/>" ;
                }
@@ -965,7 +1006,7 @@ void InsetGraphicsMailer::string2params(string const & in,
                return;
 
        istringstream data(in);
-       LyXLex lex(0,0);
+       Lexer lex(0,0);
        lex.setStream(data);
 
        string name;
@@ -985,7 +1026,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();
 }