]> git.lyx.org Git - lyx.git/blob - src/insets/insetgraphics.C
Don't remove cell selections after fontchange.
[lyx.git] / src / insets / insetgraphics.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *           Copyright 1995-2002 the LyX Team.
7  *           
8  * \author Baruch Even
9  * \author Herbert Voss <voss@lyx.org>
10  * ====================================================== */
11
12 /*
13 Known BUGS:
14     
15     * If the image is from the clipart, and the document is moved to another
16        directory, the user is screwed. Need a way to handle it.
17        This amounts to a problem of when to use relative or absolute file paths
18        We should probably use what the user asks to use... but when he chooses
19        by the file dialog we normally get an absolute path and this may not be 
20        what the user meant.
21        [Note that browseRelFile in helper_funcs.* provides a file name
22         which is relative if it is at reference path (here puffer path)
23         level or below, and an absolute path if the file name is not a
24         `natural' relative file name. In any case,
25             MakeAbsPath(filename, buf->filePath())
26         is guaranteed to provide the correct absolute path. This is what is
27         done know for include insets. Feel free to ask me -- JMarc
28         14/01/2002]
29         
30         * If we are trying to create a file in a read-only directory and there
31                 are graphics that need converting, the converting will fail because
32                 it is done in-place, into the same directory as the original image.
33                 This needs to be fixed in the src/converter.C file
34                 [ This is presumed to be fixed, needs testing.]
35
36         * We do not dither or resize the image in a WYSIWYM way, we load it at
37                 its original size and color, resizing is done in the final output,
38                 but not in the LyX window.
39
40 TODO Before initial production release:
41     * Replace insetfig everywhere
42         * Search for comments of the form
43             // INSET_GRAPHICS: remove this when InsetFig is thrown.
44           And act upon them. Make sure not to remove InsetFig code for the 
45                   1.2.0 release, only afterwards, after deployment shows InsetGraphics
46                   to be ok.
47         * What advanced features the users want to do?
48             Implement them in a non latex dependent way, but a logical way.
49             LyX should translate it to latex or any other fitting format.
50     * Add a way to roll the image file into the file format.
51     * When loading, if the image is not found in the expected place, try
52        to find it in the clipart, or in the same directory with the image.
53     * Keep a tab on the image file, if it changes, update the lyx view.
54         * The image choosing dialog could show thumbnails of the image formats
55           it knows of, thus selection based on the image instead of based on
56           filename.
57         * Add support for the 'picins' package.
58         * Add support for the 'picinpar' package.
59         * Improve support for 'subfigure' - Allow to set the various options
60                 that are possible.
61  */
62
63 /* NOTES:
64  * Fileformat:
65  * Current version is 1 (inset file format version), when changing it
66  * it should be changed in the Write() function when writing in one place
67  * and when reading one should change the version check and the error message.
68  * The filename is kept in  the lyx file in a relative way, so as to allow
69  * moving the document file and its images with no problem.
70  * 
71  *
72  * Conversions:
73  *   Postscript output means EPS figures.
74  *
75  *   PDF output is best done with PDF figures if it's a direct conversion
76  *   or PNG figures otherwise.
77  *      Image format
78  *      from        to
79  *      EPS         epstopdf
80  *      PS          ps2pdf
81  *      JPG/PNG     direct
82  *      PDF         direct
83  *      others      PNG
84  */
85
86 #include <config.h> 
87
88 #ifdef __GNUG__
89 #pragma implementation
90 #endif 
91
92 #include "insets/insetgraphics.h"
93 #include "insets/insetgraphicsParams.h"
94
95 #include "graphics/GraphicsCache.h"
96 #include "graphics/GraphicsCacheItem.h"
97
98 #include "LyXView.h"
99 #include "buffer.h"
100 #include "BufferView.h"
101 #include "converter.h"
102 #include "Painter.h"
103 #include "lyx_gui_misc.h"
104 #include "lyxtext.h"
105 #include "lyxrc.h"
106 #include "font.h"
107 #include "debug.h"
108 #include "gettext.h"
109
110 #include "frontends/Dialogs.h"
111 #include "frontends/Alert.h"
112 #include "frontends/controllers/helper_funcs.h"
113 #include "frontends/support/LyXImage.h"
114
115 #include "support/FileInfo.h"
116 #include "support/filetools.h"
117 #include "support/lyxlib.h"
118 #include "support/lyxmanip.h"
119 #include "support/lyxalgo.h"
120
121 #include <fstream>
122 #include <algorithm>
123
124 extern string system_tempdir;
125
126 using std::ifstream;
127 using std::ostream;
128 using std::endl;
129 using std::max;
130 using std::vector;
131
132
133 ///////////////////////////////////////////////////////////////////////////
134 int const VersionNumber = 1;
135 ///////////////////////////////////////////////////////////////////////////
136
137 // This function is a utility function
138 // ... that should be with ChangeExtension ...
139 inline
140 string const RemoveExtension(string const & filename)
141 {
142         return ChangeExtension(filename, string());
143 }
144
145
146 namespace {
147
148 string const unique_id()
149 {
150         static unsigned int seed = 1000;
151
152         ostringstream ost;
153         ost << "graph" << ++seed;
154
155         // Needed if we use lyxstring.
156         return ost.str().c_str();
157 }
158
159 } // namespace anon
160
161
162 // Initialize only those variables that do not have a constructor.
163 InsetGraphics::InsetGraphics()
164         : cacheHandle(0), imageLoaded(false), graphic_label(unique_id())
165 {}
166
167
168 InsetGraphics::InsetGraphics(InsetGraphics const & ig, bool same_id)
169         : Inset(), SigC::Object()
170         , cacheHandle(ig.cacheHandle)
171         , imageLoaded(ig.imageLoaded)
172         , graphic_label(unique_id())
173 {
174         setParams(ig.getParams());
175         if (same_id)
176                 id_ = ig.id_;
177 }
178
179
180 InsetGraphics::~InsetGraphics()
181 {
182         // Emits the hide signal to the dialog connected (if any)
183         hideDialog();
184 }
185
186
187 string const InsetGraphics::statusMessage() const
188 {
189         string msg;
190         if (cacheHandle.get()) {
191                 switch (cacheHandle->getImageStatus()) {
192                 case GraphicsCacheItem::UnknownError:
193                         msg = _("Unknown Error");
194                         break;
195                 case GraphicsCacheItem::Loading:
196                         msg = _("Loading...");
197                         break;
198                 case GraphicsCacheItem::ErrorReading:
199                         msg = _("Error reading");
200                         break;
201                 case GraphicsCacheItem::Converting:
202                         msg = _("Converting Image");
203                         break;
204                 case GraphicsCacheItem::ErrorConverting:
205                         msg = _("Error converting");
206                         break;
207                 case GraphicsCacheItem::Loaded:
208                         // No message to write.
209                         break;
210                 }
211         }
212         return msg;
213 }
214
215
216 int InsetGraphics::ascent(BufferView *, LyXFont const &) const
217 {
218         LyXImage * pixmap = 0;
219         if (cacheHandle.get() && (pixmap = cacheHandle->getImage()))
220                 return pixmap->getHeight();
221         else
222                 return 50;
223 }
224
225
226 int InsetGraphics::descent(BufferView *, LyXFont const &) const
227 {
228         // this is not true if viewport is used and clip is not.
229         return 0;
230 }
231
232
233 int InsetGraphics::width(BufferView *, LyXFont const & font) const
234 {
235         LyXImage * pixmap = 0;
236         
237         if (cacheHandle.get() && (pixmap = cacheHandle->getImage()))
238                 return pixmap->getWidth();
239         else {
240                 int font_width = 0;
241
242                 LyXFont msgFont(font);
243                 msgFont.setFamily(LyXFont::SANS_FAMILY);
244
245                 string const justname = OnlyFilename (params.filename);
246                 if (!justname.empty()) {
247                         msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
248                         font_width = lyxfont::width(justname, msgFont);
249                 }
250
251                 string const msg = statusMessage();
252                 if (!msg.empty()) {
253                         msgFont.setSize(LyXFont::SIZE_TINY);
254                         int const msg_width = lyxfont::width(msg, msgFont);
255                         font_width = max(font_width, msg_width);
256                 }
257                 
258                 return max(50, font_width + 15);
259         }
260 }
261
262
263 void InsetGraphics::draw(BufferView * bv, LyXFont const & font,
264                          int baseline, float & x, bool) const
265 {
266         Painter & paint = bv->painter();
267
268         int ldescent = descent(bv, font);
269         int lascent = ascent(bv, font);
270         int lwidth = width(bv, font);
271
272         // Make sure x is updated upon exit from this routine
273         int old_x = int(x);
274         x += lwidth;
275
276         // This will draw the graphics. If the graphics has not been loaded yet,
277         // we draw just a rectangle.
278         if (imageLoaded) {
279
280                 paint.image(old_x + 2, baseline - lascent,
281                             lwidth - 4, lascent + ldescent,
282                             cacheHandle->getImage());
283         } else {        
284                 // Get the image status, default to unknown error.
285                 GraphicsCacheItem::ImageStatus status = GraphicsCacheItem::UnknownError;
286                 if (lyxrc.use_gui && params.display != InsetGraphicsParams::NONE &&
287                     cacheHandle.get())
288                         status = cacheHandle->getImageStatus();
289                 // Check if the image is now ready.
290                 if (status == GraphicsCacheItem::Loaded) {
291                         imageLoaded = true;
292                         // Tell BufferView we need to be updated!
293                         bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
294                         return;
295                 }
296                 paint.rectangle(old_x + 2, baseline - lascent,
297                                 lwidth - 4,
298                                 lascent + ldescent);
299                 // Print the file name.
300                 LyXFont msgFont(font);
301                 msgFont.setFamily(LyXFont::SANS_FAMILY);
302                 string const justname = OnlyFilename (params.filename);
303                 if (!justname.empty()) {
304                         msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
305                         paint.text(old_x + 8, 
306                                    baseline - lyxfont::maxAscent(msgFont) - 4,
307                                    justname, msgFont);
308                 }
309                 // Print the message.
310                 string const msg = statusMessage();
311                 if (!msg.empty()) {
312                         msgFont.setSize(LyXFont::SIZE_TINY);
313                         paint.text(old_x + 8, baseline - 4, msg, msgFont);
314                 }
315         }
316 }
317
318
319 void InsetGraphics::edit(BufferView *bv, int, int, unsigned int)
320 {
321         bv->owner()->getDialogs()->showGraphics(this);
322 }
323
324
325 void InsetGraphics::edit(BufferView * bv, bool)
326 {
327         edit(bv, 0, 0, 0);
328 }
329
330
331 Inset::EDITABLE InsetGraphics::editable() const
332 {
333         return IS_EDITABLE;
334 }
335
336
337 void InsetGraphics::write(Buffer const * buf, ostream & os) const
338 {
339         os << "Graphics FormatVersion " << VersionNumber << '\n';
340         params.Write(buf, os);
341 }
342
343
344 void InsetGraphics::read(Buffer const * buf, LyXLex & lex)
345 {
346         string const token = lex.getString();
347
348         if (token == "Graphics")
349                 readInsetGraphics(buf, lex);
350         else if (token == "Figure") // Compatibility reading of FigInset figures.
351                 readFigInset(buf, lex);
352         else
353                 lyxerr[Debug::INFO] << "Not a Graphics or Figure inset!\n";
354
355         updateInset();
356 }
357
358 void InsetGraphics::readInsetGraphics(Buffer const * buf, LyXLex & lex)
359 {
360         bool finished = false;
361
362         while (lex.isOK() && !finished) {
363                 lex.next();
364
365                 string const token = lex.getString();
366                 lyxerr[Debug::INFO] << "Token: '" << token << '\'' 
367                                     << endl;
368
369                 if (token.empty()) {
370                         continue;
371                 } else if (token == "\\end_inset") {
372                         finished = true;
373                 } else if (token == "FormatVersion") {
374                         lex.next();
375                         int version = lex.getInteger();
376                         if (version > VersionNumber)
377                                 lyxerr
378                                 << "This document was created with a newer Graphics widget"
379                                 ", You should use a newer version of LyX to read this"
380                                 " file."
381                                 << endl;
382                         // TODO: Possibly open up a dialog?
383                 }
384                 else {
385                         if (! params.Read(buf, lex, token))
386                                 lyxerr << "Unknown token, " << token << ", skipping." 
387                                         << endl;
388                 }
389         }
390 }
391
392 // FormatVersion < 1.0  (LyX < 1.2)
393 void InsetGraphics::readFigInset(Buffer const * buf, LyXLex & lex)
394 {
395         vector<string> const oldUnits =
396                 getVectorFromString("pt,cm,in,p%,c%");
397         bool finished = false;
398         // set the display default      
399         if (lyxrc.display_graphics == "mono") 
400             params.display = InsetGraphicsParams::MONOCHROME;
401         else if (lyxrc.display_graphics == "gray") 
402             params.display = InsetGraphicsParams::GRAYSCALE;
403         else if (lyxrc.display_graphics == "color") 
404             params.display = InsetGraphicsParams::COLOR;
405         else
406             params.display = InsetGraphicsParams::NONE;
407         while (lex.isOK() && !finished) {
408                 lex.next();
409
410                 string const token = lex.getString();
411                 lyxerr[Debug::INFO] << "Token: " << token << endl;
412                 
413                 if (token.empty())
414                         continue;
415                 else if (token == "\\end_inset") {
416                         finished = true;
417                 } else if (token == "file") {
418                         if (lex.next()) {
419                                 string const name = lex.getString();
420                                 string const path = buf->filePath();
421                                 params.filename = MakeAbsPath(name, path);
422                         }
423                 } else if (token == "extra") {
424                         if (lex.next());
425                         // kept for backwards compability. Delete in 0.13.x
426                 } else if (token == "subcaption") {
427                         if (lex.eatLine())
428                                 params.subcaptionText = lex.getString();
429                         params.subcaption = true;
430                 } else if (token == "label") {
431                         if (lex.next());
432                         // kept for backwards compability. Delete in 0.13.x
433                 } else if (token == "angle") {
434                         if (lex.next())
435                                 params.rotate = true;
436                                 params.rotateAngle = lex.getFloat();
437                 } else if (token == "size") {
438                         if (lex.next())
439                                 params.lyxwidth = LyXLength(lex.getString()+"pt");
440                         if (lex.next())
441                                 params.lyxheight = LyXLength(lex.getString()+"pt");
442                 } else if (token == "flags") {
443                         if (lex.next())
444                                 switch (lex.getInteger()) {
445                                 case 1: params.display = InsetGraphicsParams::MONOCHROME; 
446                                     break;
447                                 case 2: params.display = InsetGraphicsParams::GRAYSCALE; 
448                                     break;
449                                 case 3: params.display = InsetGraphicsParams::COLOR; 
450                                     break;
451                                 }
452                 } else if (token == "subfigure") {
453                         params.subcaption = true;
454                 } else if (token == "width") {
455                     if (lex.next()) {
456                         int i = lex.getInteger();
457                         if (lex.next()) {
458                             if (i == 5) {
459                                 params.scale = lex.getInteger();
460                                 params.size_type = InsetGraphicsParams::SCALE;
461                             } else {
462                                 params.width = LyXLength(lex.getString()+oldUnits[i]);
463                                 params.size_type = InsetGraphicsParams::WH;
464                             }
465                         }
466                     }
467                 } else if (token == "height") {
468                     if (lex.next()) {
469                         int i = lex.getInteger();
470                         if (lex.next()) {
471                             params.height = LyXLength(lex.getString()+oldUnits[i]);
472                             params.size_type = InsetGraphicsParams::WH;
473                         }
474                     }
475                 }
476         }
477 }
478
479 string const InsetGraphics::createLatexOptions() const
480 {
481         // Calculate the options part of the command, we must do it to a string
482         // stream since we might have a trailing comma that we would like to remove
483         // before writing it to the output stream.
484         ostringstream options;
485         if (!params.bb.empty())
486             options << "  bb=" << strip(params.bb) << ",\n";
487         if (params.draft)
488             options << "  draft,\n";
489         if (params.clip)
490             options << "  clip,\n";
491         if (params.size_type == InsetGraphicsParams::WH) {
492             if (!params.width.zero())
493                 options << "  width=" << params.width.asLatexString() << ",\n";
494             if (!params.height.zero())
495                 options << "  height=" << params.height.asLatexString() << ",\n";
496         } else if (params.size_type == InsetGraphicsParams::SCALE) {
497             if (params.scale > 0)
498                 options << "  scale=" << double(params.scale)/100.0 << ",\n";
499         }
500         if (params.keepAspectRatio)
501             options << "  keepaspectratio,\n";
502         // Make sure it's not very close to zero, a float can be effectively
503         // zero but not exactly zero.
504         if (!lyx::float_equal(params.rotateAngle, 0, 0.001) && params.rotate) {
505             options << "  angle=" << params.rotateAngle << ",\n";
506             if (!params.rotateOrigin.empty()) {
507                 options << "  origin=" << params.rotateOrigin[0];
508                 if (contains(params.rotateOrigin,"Top"))
509                     options << 't';
510                 else if (contains(params.rotateOrigin,"Bottom"))
511                     options << 'b';
512                 else if (contains(params.rotateOrigin,"Baseline"))
513                     options << 'B';
514                 options << ",\n";
515             }
516         }
517         if (!params.special.empty())
518             options << params.special << ",\n";
519         string opts = options.str().c_str();
520         return opts.substr(0,opts.size()-2);    // delete last ",\n"
521 }
522
523 namespace {
524 string decideOutputImageFormat(string const & suffix)
525 {
526         // lyxrc.pdf_mode means:
527         // Are we creating a PDF or a PS file?
528         // (Should actually mean, are we using latex or pdflatex).      
529         lyxerr[Debug::INFO] << "decideOutput::lyxrc.pdf_mode = " << lyxrc.pdf_mode << "\n";
530         if (lyxrc.pdf_mode) {
531                 if (contains(suffix,"ps") || suffix == "pdf")
532                         return "pdf";
533                 else if (suffix == "jpg")
534                         return suffix;
535                 else
536                         return "png";
537         }
538         // If it's postscript, we always do eps.
539         lyxerr[Debug::INFO] << "decideOutput: we have PostScript mode\n";
540         if (suffix != "ps")
541             return "eps";
542         else
543             return "ps";
544 }
545
546 } // Anon. namespace
547
548 string const InsetGraphics::prepareFile(Buffer const *buf) const
549 {
550         // do_convert = Do we need to convert the file?
551         // nice = Do we create a nice version?
552         //        This is used when exporting the latex file only.
553         // if (!do_convert)
554         //   return original filename
555         // if (!nice)
556         //   convert_place = temp directory
557         //   return new filename in temp directory
558         // else
559         //   convert_place = original file directory
560         //   return original filename without the extension
561         //
562         // if it's a zipped one, than let LaTeX do the rest!!!
563         if ((zippedFile(params.filename) && params.noUnzip) || buf->niceFile) {
564             lyxerr[Debug::INFO] << "don't unzip file or export latex" 
565                     << params.filename << endl;
566             return params.filename;
567         }
568         string filename_ = params.filename;
569         if (zippedFile(filename_))
570             filename_ = unzipFile(filename_);
571         // now we have unzipped files
572         // Get the extension (format) of the original file.
573         // we handle it like a virtual one, so we can have
574         // different extensions with the same type.
575         string const extension = getExtFromContents(filename_);
576         // are we usind latex ((e)ps) or pdflatex (pdf,jpg,png)
577         string const image_target = decideOutputImageFormat(extension);
578         if (extension == image_target)          // :-)
579                 return filename_;
580 //      commented out to check if the "not exist"bug is fixed.
581 //      if (!IsFileReadable(filename_)) {       // :-(
582 //              Alert::alert(_("File") + params.filename,
583 //                         _("isn't readable or doesn't exists!"));
584 //              return filename_;
585 //      }
586         string outfile;
587         string const temp = AddName(buf->tmppath, filename_);
588         outfile = RemoveExtension(temp);
589         lyxerr[Debug::INFO] << "tempname = " << temp << "\n";
590         lyxerr[Debug::INFO] << "buf::tmppath = " << buf->tmppath << "\n";
591         lyxerr[Debug::INFO] << "filename_ = " << filename_ << "\n";
592         lyxerr[Debug::INFO] << "outfile = " << outfile << endl;
593         converters.convert(buf, filename_, outfile, extension, image_target);
594         return outfile;
595 }
596
597
598 int InsetGraphics::latex(Buffer const *buf, ostream & os,
599                          bool /*fragile*/, bool/*fs*/) const
600 {
601         // If there is no file specified, just output a message about it in
602         // the latex output.
603         if (params.filename.empty()) {
604                 os  << "\\fbox{\\rule[-0.5in]{0pt}{1in}"
605                         << _("empty figure path") << "}\n";
606                 return 1; // One end of line marker added to the stream.
607         }
608         // These variables collect all the latex code that should be before and
609         // after the actual includegraphics command.
610         string before;
611         string after;
612         // Do we want subcaptions?
613         if (params.subcaption) {
614                 before += "\\subfigure[" + params.subcaptionText + "]{";
615                 after = '}';
616         }
617         // We never use the starred form, we use the "clip" option instead.
618         before += "\\includegraphics";
619         // Write the options if there are any.
620         string const opts = createLatexOptions();
621         if (!opts.empty()) {
622                 before += ("[%\n" + opts +']');
623         }
624         // Make the filename relative to the lyx file
625         // and remove the extension so the LaTeX will use whatever is
626         // appropriate (when there are several versions in different formats)
627         string const latex_str = before + '{' + prepareFile(buf) + '}' + after;
628         os << latex_str;
629         // Return how many newlines we issued.
630         int const newlines =
631                 int(lyx::count(latex_str.begin(), latex_str.end(),'\n') + 1);
632         // lyxerr << "includegraphics: " << newlines << " lines of text"
633         //        << endl; 
634         return newlines;
635 }
636
637
638 int InsetGraphics::ascii(Buffer const *, ostream & os, int) const
639 {
640         // No graphics in ascii output. Possible to use gifscii to convert
641         // images to ascii approximation.
642         // 1. Convert file to ascii using gifscii
643         // 2. Read ascii output file and add it to the output stream.
644         // at least we send the filename
645         os << '<' << _("Graphicfile:") << params.filename << ">\n";
646         return 0;
647 }
648
649
650 int InsetGraphics::linuxdoc(Buffer const *, ostream &) const
651 {
652         // No graphics in LinuxDoc output. Should check how/what to add.
653         return 0;
654 }
655
656
657 // For explanation on inserting graphics into DocBook checkout:
658 // http://linuxdoc.org/LDP/LDP-Author-Guide/inserting-pictures.html
659 // See also the docbook guide at http://www.docbook.org/
660 int InsetGraphics::docbook(Buffer const *, ostream & os) const
661 {
662         // In DocBook v5.0, the graphic tag will be eliminated from DocBook, will 
663         // need to switch to MediaObject. However, for now this is sufficient and 
664         // easier to use.
665         os << "<graphic fileref=\"&" << graphic_label << ";\">";
666         return 0;
667 }
668
669
670 void InsetGraphics::validate(LaTeXFeatures & features) const
671 {
672         // If we have no image, we should not require anything.
673         if (params.filename.empty())
674                 return ;
675
676         features.includeFile(graphic_label, RemoveExtension(params.filename));
677
678         features.require("graphicx");
679
680         if (params.subcaption)
681                 features.require("subfigure");
682 }
683
684
685 // Update the inset after parameters changed (read from file or changed in
686 // dialog.
687 void InsetGraphics::updateInset() const
688 {
689         GraphicsCache & gc = GraphicsCache::getInstance();
690         boost::shared_ptr<GraphicsCacheItem> temp(0);
691
692         // We do it this way so that in the face of some error, we will still
693         // be in a valid state.
694         InsetGraphicsParams::DisplayType local_display = params.display;
695         if (local_display == InsetGraphicsParams::DEFAULT) {
696                 if (lyxrc.display_graphics == "mono")
697                         local_display = InsetGraphicsParams::MONOCHROME;
698                 else if (lyxrc.display_graphics == "gray")
699                         local_display = InsetGraphicsParams::GRAYSCALE;
700                 else if (lyxrc.display_graphics == "color")
701                         local_display = InsetGraphicsParams::COLOR;
702                 else
703                         local_display = InsetGraphicsParams::NONE;
704         }
705
706         if (!params.filename.empty() && lyxrc.use_gui &&
707             local_display != InsetGraphicsParams::NONE) {
708                 temp = gc.addFile(params.filename);
709         }
710
711         // Mark the image as unloaded so that it gets updated.
712         imageLoaded = false;
713
714         cacheHandle = temp;
715 }
716
717
718 bool InsetGraphics::setParams(InsetGraphicsParams const & p)
719 {
720         // If nothing is changed, just return and say so.
721         if (params == p)
722                 return false;
723
724         // Copy the new parameters.
725         params = p;
726
727         // Update the inset with the new parameters.
728         updateInset();
729
730         // We have changed data, report it.
731         return true;
732 }
733
734
735 InsetGraphicsParams InsetGraphics::getParams() const
736 {
737         return params;
738 }
739
740
741 Inset * InsetGraphics::clone(Buffer const &, bool same_id) const
742 {
743         return new InsetGraphics(*this, same_id);
744 }
745