]> git.lyx.org Git - lyx.git/blobdiff - src/insets/insetgraphics.C
Don't remove cell selections after fontchange.
[lyx.git] / src / insets / insetgraphics.C
index 8640ca9a234a3dd8f9125183030e742771cb8d3e..1dc04a8530c0eea9948d5443e3762bdede8630ab 100644 (file)
@@ -37,10 +37,6 @@ Known BUGS:
                its original size and color, resizing is done in the final output,
                but not in the LyX window.
 
                its original size and color, resizing is done in the final output,
                but not in the LyX window.
 
-       * EPS figures are not fully detected, they may have a lot of possible
-               suffixes so we need to read the file and detect if it's EPS or not.
-               [Implemented, need testing]
-               
 TODO Before initial production release:
     * Replace insetfig everywhere
         * Search for comments of the form
 TODO Before initial production release:
     * Replace insetfig everywhere
         * Search for comments of the form
@@ -95,38 +91,47 @@ TODO Before initial production release:
 
 #include "insets/insetgraphics.h"
 #include "insets/insetgraphicsParams.h"
 
 #include "insets/insetgraphics.h"
 #include "insets/insetgraphicsParams.h"
+
 #include "graphics/GraphicsCache.h"
 #include "graphics/GraphicsCacheItem.h"
 
 #include "graphics/GraphicsCache.h"
 #include "graphics/GraphicsCacheItem.h"
 
-#include "frontends/Dialogs.h"
 #include "LyXView.h"
 #include "buffer.h"
 #include "BufferView.h"
 #include "converter.h"
 #include "LyXView.h"
 #include "buffer.h"
 #include "BufferView.h"
 #include "converter.h"
-#include "frontends/support/LyXImage.h"
 #include "Painter.h"
 #include "lyx_gui_misc.h"
 #include "Painter.h"
 #include "lyx_gui_misc.h"
-#include "support/FileInfo.h"
-#include "support/filetools.h"
-#include "frontends/controllers/helper_funcs.h"
-#include "support/lyxlib.h"
 #include "lyxtext.h"
 #include "lyxrc.h"
 #include "lyxtext.h"
 #include "lyxrc.h"
-#include "font.h" // For the lyxfont class.
-#include "fstream" // for ifstream in isEPS
-#include <algorithm> // For the std::max
-#include "support/lyxmanip.h"
+#include "font.h"
 #include "debug.h"
 #include "gettext.h"
 
 #include "debug.h"
 #include "gettext.h"
 
+#include "frontends/Dialogs.h"
+#include "frontends/Alert.h"
+#include "frontends/controllers/helper_funcs.h"
+#include "frontends/support/LyXImage.h"
+
+#include "support/FileInfo.h"
+#include "support/filetools.h"
+#include "support/lyxlib.h"
+#include "support/lyxmanip.h"
+#include "support/lyxalgo.h"
+
+#include <fstream>
+#include <algorithm>
+
 extern string system_tempdir;
 
 using std::ifstream;
 using std::ostream;
 using std::endl;
 extern string system_tempdir;
 
 using std::ifstream;
 using std::ostream;
 using std::endl;
+using std::max;
+using std::vector;
+
 
 ///////////////////////////////////////////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-int VersionNumber = 1;
+int const VersionNumber = 1;
 ///////////////////////////////////////////////////////////////////////////
 
 // This function is a utility function
 ///////////////////////////////////////////////////////////////////////////
 
 // This function is a utility function
@@ -138,9 +143,25 @@ string const RemoveExtension(string const & filename)
 }
 
 
 }
 
 
+namespace {
+
+string const unique_id()
+{
+       static unsigned int seed = 1000;
+
+       ostringstream ost;
+       ost << "graph" << ++seed;
+
+       // Needed if we use lyxstring.
+       return ost.str().c_str();
+}
+
+} // namespace anon
+
+
 // Initialize only those variables that do not have a constructor.
 InsetGraphics::InsetGraphics()
 // Initialize only those variables that do not have a constructor.
 InsetGraphics::InsetGraphics()
-       : cacheHandle(0), imageLoaded(false)
+       : cacheHandle(0), imageLoaded(false), graphic_label(unique_id())
 {}
 
 
 {}
 
 
@@ -148,6 +169,7 @@ InsetGraphics::InsetGraphics(InsetGraphics const & ig, bool same_id)
        : Inset(), SigC::Object()
        , cacheHandle(ig.cacheHandle)
        , imageLoaded(ig.imageLoaded)
        : Inset(), SigC::Object()
        , cacheHandle(ig.cacheHandle)
        , imageLoaded(ig.imageLoaded)
+       , graphic_label(unique_id())
 {
        setParams(ig.getParams());
        if (same_id)
 {
        setParams(ig.getParams());
        if (same_id)
@@ -230,10 +252,10 @@ int InsetGraphics::width(BufferView *, LyXFont const & font) const
                if (!msg.empty()) {
                        msgFont.setSize(LyXFont::SIZE_TINY);
                        int const msg_width = lyxfont::width(msg, msgFont);
                if (!msg.empty()) {
                        msgFont.setSize(LyXFont::SIZE_TINY);
                        int const msg_width = lyxfont::width(msg, msgFont);
-                       font_width = std::max(font_width, msg_width);
+                       font_width = max(font_width, msg_width);
                }
                
                }
                
-               return std::max(50, font_width + 15);
+               return max(50, font_width + 15);
        }
 }
 
        }
 }
 
@@ -342,7 +364,7 @@ void InsetGraphics::readInsetGraphics(Buffer const * buf, LyXLex & lex)
 
                string const token = lex.getString();
                lyxerr[Debug::INFO] << "Token: '" << token << '\'' 
 
                string const token = lex.getString();
                lyxerr[Debug::INFO] << "Token: '" << token << '\'' 
-                                   << std::endl;
+                                   << endl;
 
                if (token.empty()) {
                        continue;
 
                if (token.empty()) {
                        continue;
@@ -356,13 +378,13 @@ void InsetGraphics::readInsetGraphics(Buffer const * buf, LyXLex & lex)
                                << "This document was created with a newer Graphics widget"
                                ", You should use a newer version of LyX to read this"
                                " file."
                                << "This document was created with a newer Graphics widget"
                                ", You should use a newer version of LyX to read this"
                                " file."
-                               << std::endl;
+                               << endl;
                        // TODO: Possibly open up a dialog?
                }
                else {
                        if (! params.Read(buf, lex, token))
                                lyxerr << "Unknown token, " << token << ", skipping." 
                        // TODO: Possibly open up a dialog?
                }
                else {
                        if (! params.Read(buf, lex, token))
                                lyxerr << "Unknown token, " << token << ", skipping." 
-                                       << std::endl;
+                                       << endl;
                }
        }
 }
                }
        }
 }
@@ -370,7 +392,7 @@ void InsetGraphics::readInsetGraphics(Buffer const * buf, LyXLex & lex)
 // FormatVersion < 1.0  (LyX < 1.2)
 void InsetGraphics::readFigInset(Buffer const * buf, LyXLex & lex)
 {
 // FormatVersion < 1.0  (LyX < 1.2)
 void InsetGraphics::readFigInset(Buffer const * buf, LyXLex & lex)
 {
-       std::vector<string> const oldUnits =
+       vector<string> const oldUnits =
                getVectorFromString("pt,cm,in,p%,c%");
        bool finished = false;
        // set the display default      
                getVectorFromString("pt,cm,in,p%,c%");
        bool finished = false;
        // set the display default      
@@ -410,6 +432,7 @@ void InsetGraphics::readFigInset(Buffer const * buf, LyXLex & lex)
                        // kept for backwards compability. Delete in 0.13.x
                } else if (token == "angle") {
                        if (lex.next())
                        // kept for backwards compability. Delete in 0.13.x
                } else if (token == "angle") {
                        if (lex.next())
+                               params.rotate = true;
                                params.rotateAngle = lex.getFloat();
                } else if (token == "size") {
                        if (lex.next())
                                params.rotateAngle = lex.getFloat();
                } else if (token == "size") {
                        if (lex.next())
@@ -460,43 +483,41 @@ string const InsetGraphics::createLatexOptions() const
        // before writing it to the output stream.
        ostringstream options;
        if (!params.bb.empty())
        // before writing it to the output stream.
        ostringstream options;
        if (!params.bb.empty())
-           options << "bb=" << strip(params.bb) << ',';
+           options << "  bb=" << strip(params.bb) << ",\n";
        if (params.draft)
        if (params.draft)
-           options << "%\n  draft,";
+           options << "  draft,\n";
        if (params.clip)
        if (params.clip)
-           options << "%\n  clip,";
+           options << "  clip,\n";
        if (params.size_type == InsetGraphicsParams::WH) {
            if (!params.width.zero())
        if (params.size_type == InsetGraphicsParams::WH) {
            if (!params.width.zero())
-               options << "%\n  width=" << params.width.asLatexString() << ',';
+               options << "  width=" << params.width.asLatexString() << ",\n";
            if (!params.height.zero())
            if (!params.height.zero())
-               options << "%\n  height=" << params.height.asLatexString() << ',';
+               options << "  height=" << params.height.asLatexString() << ",\n";
        } else if (params.size_type == InsetGraphicsParams::SCALE) {
            if (params.scale > 0)
        } else if (params.size_type == InsetGraphicsParams::SCALE) {
            if (params.scale > 0)
-               options << "%\n  scale=" << double(params.scale)/100.0 << ',';
+               options << "  scale=" << double(params.scale)/100.0 << ",\n";
        }
        if (params.keepAspectRatio)
        }
        if (params.keepAspectRatio)
-           options << "%\n  keepaspectratio,";
+           options << "  keepaspectratio,\n";
        // Make sure it's not very close to zero, a float can be effectively
        // zero but not exactly zero.
        // Make sure it's not very close to zero, a float can be effectively
        // zero but not exactly zero.
-       if (!lyx::float_equal(params.rotateAngle, 0, 0.001)) {
-           options << "%\n  angle=" << params.rotateAngle << ',';
+       if (!lyx::float_equal(params.rotateAngle, 0, 0.001) && params.rotate) {
+           options << "  angle=" << params.rotateAngle << ",\n";
            if (!params.rotateOrigin.empty()) {
            if (!params.rotateOrigin.empty()) {
-               options << "%\n  origin=";
-               options << params.rotateOrigin[0];
+               options << "  origin=" << params.rotateOrigin[0];
                if (contains(params.rotateOrigin,"Top"))
                    options << 't';
                else if (contains(params.rotateOrigin,"Bottom"))
                    options << 'b';
                else if (contains(params.rotateOrigin,"Baseline"))
                    options << 'B';
                if (contains(params.rotateOrigin,"Top"))
                    options << 't';
                else if (contains(params.rotateOrigin,"Bottom"))
                    options << 'b';
                else if (contains(params.rotateOrigin,"Baseline"))
                    options << 'B';
-               options << ',';
+               options << ",\n";
            }
        }
        if (!params.special.empty())
            }
        }
        if (!params.special.empty())
-           options << params.special << ',';
+           options << params.special << ",\n";
        string opts = options.str().c_str();
        string opts = options.str().c_str();
-       opts = strip(opts, ',');
-       return opts;
+       return opts.substr(0,opts.size()-2);    // delete last ",\n"
 }
 
 namespace {
 }
 
 namespace {
@@ -505,7 +526,7 @@ string decideOutputImageFormat(string const & suffix)
        // lyxrc.pdf_mode means:
        // Are we creating a PDF or a PS file?
        // (Should actually mean, are we using latex or pdflatex).      
        // lyxrc.pdf_mode means:
        // Are we creating a PDF or a PS file?
        // (Should actually mean, are we using latex or pdflatex).      
-       lyxerr << "decideOutput::lyxrc.pdf_mode = " << lyxrc.pdf_mode << "\n";
+       lyxerr[Debug::INFO] << "decideOutput::lyxrc.pdf_mode = " << lyxrc.pdf_mode << "\n";
        if (lyxrc.pdf_mode) {
                if (contains(suffix,"ps") || suffix == "pdf")
                        return "pdf";
        if (lyxrc.pdf_mode) {
                if (contains(suffix,"ps") || suffix == "pdf")
                        return "pdf";
@@ -515,7 +536,7 @@ string decideOutputImageFormat(string const & suffix)
                        return "png";
        }
        // If it's postscript, we always do eps.
                        return "png";
        }
        // If it's postscript, we always do eps.
-       lyxerr << "decideOutput: we have PostScript mode\n";
+       lyxerr[Debug::INFO] << "decideOutput: we have PostScript mode\n";
        if (suffix != "ps")
            return "eps";
        else
        if (suffix != "ps")
            return "eps";
        else
@@ -538,33 +559,38 @@ string const InsetGraphics::prepareFile(Buffer const *buf) const
        //   convert_place = original file directory
        //   return original filename without the extension
        //
        //   convert_place = original file directory
        //   return original filename without the extension
        //
+       // if it's a zipped one, than let LaTeX do the rest!!!
+       if ((zippedFile(params.filename) && params.noUnzip) || buf->niceFile) {
+           lyxerr[Debug::INFO] << "don't unzip file or export latex" 
+                   << params.filename << endl;
+           return params.filename;
+       }
+       string filename_ = params.filename;
+       if (zippedFile(filename_))
+           filename_ = unzipFile(filename_);
+       // now we have unzipped files
        // Get the extension (format) of the original file.
        // we handle it like a virtual one, so we can have
        // different extensions with the same type.
        // Get the extension (format) of the original file.
        // we handle it like a virtual one, so we can have
        // different extensions with the same type.
-       // if it's a zipped one, than let LaTeX do the rest!!!
-       //if (zippedFile(params.filename))      
-       //    return params.filename;
-       // now we have unzipped files
-       string const extension = getExtFromContents(params.filename);
-       // Are we creating a PDF or a PS file?
-       // (Should actually mean, are we usind latex or pdflatex).
+       string const extension = getExtFromContents(filename_);
+       // are we usind latex ((e)ps) or pdflatex (pdf,jpg,png)
        string const image_target = decideOutputImageFormat(extension);
        string const image_target = decideOutputImageFormat(extension);
-       if (extension == image_target)
-               return params.filename;
+       if (extension == image_target)          // :-)
+               return filename_;
+//     commented out to check if the "not exist"bug is fixed.
+//     if (!IsFileReadable(filename_)) {       // :-(
+//             Alert::alert(_("File") + params.filename,
+//                        _("isn't readable or doesn't exists!"));
+//             return filename_;
+//     }
        string outfile;
        string outfile;
-       if (!buf->niceFile) {
-               string const temp = AddName(buf->tmppath, params.filename);
-               lyxerr << "temp = " << temp << "\n";
-               outfile = RemoveExtension(temp);
-       } else {
-               string const path = buf->filePath();
-               string const relname = MakeRelPath(params.filename, path);
-               outfile = RemoveExtension(relname);
-       }
-       lyxerr << "buf::tmppath = " << buf->tmppath << "\n";
-       lyxerr << "filename = " << params.filename << "\n";
-       lyxerr << "outfile = " << outfile << endl;
-       converters.convert(buf, params.filename, outfile, extension, image_target);
+       string const temp = AddName(buf->tmppath, filename_);
+       outfile = RemoveExtension(temp);
+       lyxerr[Debug::INFO] << "tempname = " << temp << "\n";
+       lyxerr[Debug::INFO] << "buf::tmppath = " << buf->tmppath << "\n";
+       lyxerr[Debug::INFO] << "filename_ = " << filename_ << "\n";
+       lyxerr[Debug::INFO] << "outfile = " << outfile << endl;
+       converters.convert(buf, filename_, outfile, extension, image_target);
        return outfile;
 }
 
        return outfile;
 }
 
@@ -579,30 +605,32 @@ int InsetGraphics::latex(Buffer const *buf, ostream & os,
                        << _("empty figure path") << "}\n";
                return 1; // One end of line marker added to the stream.
        }
                        << _("empty figure path") << "}\n";
                return 1; // One end of line marker added to the stream.
        }
-       // Keep count of newlines that we issued.
-       int newlines = 0;
-       // This variables collect all the latex code that should be before and
+       // These variables collect all the latex code that should be before and
        // after the actual includegraphics command.
        string before;
        string after;
        // Do we want subcaptions?
        if (params.subcaption) {
                before += "\\subfigure[" + params.subcaptionText + "]{";
        // after the actual includegraphics command.
        string before;
        string after;
        // Do we want subcaptions?
        if (params.subcaption) {
                before += "\\subfigure[" + params.subcaptionText + "]{";
-               after = '}' + after;
+               after = '}';
        }
        // We never use the starred form, we use the "clip" option instead.
        }
        // We never use the starred form, we use the "clip" option instead.
-       os << before << "\\includegraphics";
+       before += "\\includegraphics";
        // Write the options if there are any.
        string const opts = createLatexOptions();
        if (!opts.empty()) {
        // Write the options if there are any.
        string const opts = createLatexOptions();
        if (!opts.empty()) {
-               os << "[%\n  " << opts << ']';
+               before += ("[%\n" + opts +']');
        }
        // Make the filename relative to the lyx file
        // and remove the extension so the LaTeX will use whatever is
        // appropriate (when there are several versions in different formats)
        }
        // Make the filename relative to the lyx file
        // and remove the extension so the LaTeX will use whatever is
        // appropriate (when there are several versions in different formats)
-       string const filename = prepareFile(buf);
-       os << '{' << filename << '}' << after;
+       string const latex_str = before + '{' + prepareFile(buf) + '}' + after;
+       os << latex_str;
        // Return how many newlines we issued.
        // Return how many newlines we issued.
+       int const newlines =
+               int(lyx::count(latex_str.begin(), latex_str.end(),'\n') + 1);
+       // lyxerr << "includegraphics: " << newlines << " lines of text"
+       //        << endl; 
        return newlines;
 }
 
        return newlines;
 }
 
@@ -629,20 +657,12 @@ int InsetGraphics::linuxdoc(Buffer const *, ostream &) const
 // For explanation on inserting graphics into DocBook checkout:
 // http://linuxdoc.org/LDP/LDP-Author-Guide/inserting-pictures.html
 // See also the docbook guide at http://www.docbook.org/
 // For explanation on inserting graphics into DocBook checkout:
 // http://linuxdoc.org/LDP/LDP-Author-Guide/inserting-pictures.html
 // See also the docbook guide at http://www.docbook.org/
-int InsetGraphics::docbook(Buffer const * buf, ostream & os) const
+int InsetGraphics::docbook(Buffer const *, ostream & os) const
 {
 {
-       // Change the path to be relative to the main file.
-       string const buffer_dir = buf->filePath();
-       string filename = RemoveExtension(
-               MakeRelPath(params.filename, buffer_dir));
-
-       if (suffixIs(filename, ".eps"))
-               filename.erase(filename.length() - 4);
-
        // In DocBook v5.0, the graphic tag will be eliminated from DocBook, will 
        // need to switch to MediaObject. However, for now this is sufficient and 
        // easier to use.
        // In DocBook v5.0, the graphic tag will be eliminated from DocBook, will 
        // need to switch to MediaObject. However, for now this is sufficient and 
        // easier to use.
-       os << "<graphic fileref=\"" << filename << "\"></graphic>";
+       os << "<graphic fileref=\"&" << graphic_label << ";\">";
        return 0;
 }
 
        return 0;
 }
 
@@ -653,6 +673,8 @@ void InsetGraphics::validate(LaTeXFeatures & features) const
        if (params.filename.empty())
                return ;
 
        if (params.filename.empty())
                return ;
 
+       features.includeFile(graphic_label, RemoveExtension(params.filename));
+
        features.require("graphicx");
 
        if (params.subcaption)
        features.require("graphicx");
 
        if (params.subcaption)