]> git.lyx.org Git - lyx.git/blob - src/insets/InsetExternal.cpp
getting rid of superfluous std:: statements.
[lyx.git] / src / insets / InsetExternal.cpp
1 /**
2  * \file InsetExternal.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup Nielsen
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "InsetExternal.h"
14 #include "insets/ExternalSupport.h"
15 #include "insets/ExternalTemplate.h"
16 #include "insets/RenderButton.h"
17 #include "insets/RenderGraphic.h"
18 #include "insets/RenderPreview.h"
19
20 #include "Buffer.h"
21 #include "Cursor.h"
22 #include "support/debug.h"
23 #include "DispatchResult.h"
24 #include "Exporter.h"
25 #include "FuncStatus.h"
26 #include "FuncRequest.h"
27 #include "support/gettext.h"
28 #include "LaTeXFeatures.h"
29 #include "Lexer.h"
30 #include "LyXRC.h"
31 #include "MetricsInfo.h"
32 #include "OutputParams.h"
33
34 #include "graphics/PreviewLoader.h"
35
36 #include "support/filetools.h"
37 #include "support/lstrings.h"
38 #include "support/lyxlib.h"
39 #include "support/convert.h"
40 #include "support/Translator.h"
41
42 #include <boost/bind.hpp>
43
44 #include <sstream>
45
46 using namespace std;
47 using namespace lyx::support;
48
49 namespace {
50
51 lyx::external::DisplayType const defaultDisplayType = lyx::external::NoDisplay;
52
53 unsigned int const defaultLyxScale = 100;
54
55 string defaultTemplateName;
56
57 } // namespace anon
58
59
60 namespace lyx {
61
62 extern bool use_gui;
63
64 namespace external {
65
66 TempName::TempName()
67 {
68         support::FileName const tempname(support::tempName(support::FileName(), "lyxext"));
69         // FIXME: This is unsafe
70         tempname.removeFile();
71         // must have an extension for the converter code to work correctly.
72         tempname_ = support::FileName(tempname.absFilename() + ".tmp");
73 }
74
75
76 TempName::TempName(TempName const &)
77 {
78         tempname_ = TempName()();
79 }
80
81
82 TempName::~TempName()
83 {
84         tempname_.removeFile();
85 }
86
87
88 TempName & TempName::operator=(TempName const & other)
89 {
90         if (this != &other)
91                 tempname_ = TempName()();
92         return *this;
93 }
94
95
96 namespace {
97
98 /// The translator between the Display enum and corresponding lyx string.
99 Translator<DisplayType, string> const initTranslator()
100 {
101         Translator<DisplayType, string> translator(DefaultDisplay, "default");
102
103         // Fill the display translator
104         translator.addPair(MonochromeDisplay, "monochrome");
105         translator.addPair(GrayscaleDisplay, "grayscale");
106         translator.addPair(ColorDisplay, "color");
107         translator.addPair(PreviewDisplay, "preview");
108         translator.addPair(NoDisplay, "none");
109
110         return translator;
111 }
112
113 } // namespace anon
114
115
116 Translator<DisplayType, string> const & displayTranslator()
117 {
118         static Translator<DisplayType, string> const translator =
119                 initTranslator();
120         return translator;
121 }
122
123 } // namespace external
124
125
126 InsetExternalParams::InsetExternalParams()
127         : display(defaultDisplayType),
128           lyxscale(defaultLyxScale),
129           draft(false)
130 {
131         if (defaultTemplateName.empty()) {
132                 external::TemplateManager const & etm =
133                         external::TemplateManager::get();
134                 templatename_ = etm.getTemplates().begin()->first;
135         } else
136                 templatename_ = defaultTemplateName;
137 }
138
139
140 namespace {
141
142 template <typename T>
143 void clearIfNotFound(T & data, external::TransformID value,
144                      vector<external::TransformID> const & ids)
145 {
146         typedef vector<external::TransformID>::const_iterator
147                 const_iterator;
148
149         const_iterator it  = ids.begin();
150         const_iterator end = ids.end();
151         it = find(it, end, value);
152         if (it == end)
153                 data = T();
154 }
155
156 } // namespace anon
157
158
159 void InsetExternalParams::settemplate(string const & name)
160 {
161         templatename_ = name;
162
163         external::TemplateManager const & etm =
164                 external::TemplateManager::get();
165         external::Template const * const et = etm.getTemplateByName(name);
166         if (!et)
167                 // Be safe. Don't lose data.
168                 return;
169
170         // Ascertain which transforms the template supports.
171         // Empty all those that it doesn't.
172         vector<external::TransformID> const & ids = et->transformIds;
173         clearIfNotFound(clipdata,     external::Clip,   ids);
174         clearIfNotFound(extradata,    external::Extra,  ids);
175         clearIfNotFound(resizedata,   external::Resize, ids);
176         clearIfNotFound(rotationdata, external::Rotate, ids);
177 }
178
179
180 void InsetExternalParams::write(Buffer const & buffer, ostream & os) const
181 {
182         os << "External\n"
183            << "\ttemplate " << templatename() << '\n';
184
185         if (!filename.empty()) {
186                 // when we save, we still use the original filename
187                 EmbeddedFiles::EmbeddedFileList::const_iterator it = 
188                         buffer.embeddedFiles().find(filename.toFilesystemEncoding());
189                 if (it != buffer.embeddedFiles().end())
190                         os << "\tfilename " << DocFileName(it->absFilename()).outputFilename(buffer.filePath()) << '\n';
191                 else
192                         os << "\tfilename " << filename.outputFilename(buffer.filePath()) << '\n';
193         }
194
195         if (display != defaultDisplayType)
196                 os << "\tdisplay "
197                    << external::displayTranslator().find(display)
198                    << '\n';
199
200         if (lyxscale != defaultLyxScale)
201                 os << "\tlyxscale " << convert<string>(lyxscale) << '\n';
202
203         if (draft)
204                 os << "\tdraft\n";
205
206         if (!clipdata.bbox.empty())
207                 os << "\tboundingBox " << clipdata.bbox << '\n';
208         if (clipdata.clip)
209                 os << "\tclip\n";
210
211         external::ExtraData::const_iterator it  = extradata.begin();
212         external::ExtraData::const_iterator end = extradata.end();
213         for (; it != end; ++it) {
214                 if (!it->second.empty())
215                         os << "\textra " << it->first << " \""
216                            << it->second << "\"\n";
217         }
218
219         if (!rotationdata.no_rotation()) {
220                 os << "\trotateAngle " << rotationdata.adjAngle() << '\n';
221                 if (rotationdata.origin() != external::RotationData::DEFAULT)
222                         os << "\trotateOrigin "
223                            << rotationdata.originString() << '\n';
224         }
225
226         if (!resizedata.no_resize()) {
227                 using support::float_equal;
228                 double const scl = convert<double>(resizedata.scale);
229                 if (!float_equal(scl, 0.0, 0.05)) {
230                         if (!float_equal(scl, 100.0, 0.05))
231                                 os << "\tscale "
232                                    << resizedata.scale << '\n';
233                 } else {
234                         if (!resizedata.width.zero())
235                                 os << "\twidth "
236                                    << resizedata.width.asString() << '\n';
237                         if (!resizedata.height.zero())
238                                 os << "\theight "
239                                    << resizedata.height.asString() << '\n';
240                 }
241                 if (resizedata.keepAspectRatio)
242                         os << "\tkeepAspectRatio\n";
243         }
244 }
245
246
247 bool InsetExternalParams::read(Buffer const & buffer, Lexer & lex)
248 {
249         enum ExternalTags {
250                 EX_TEMPLATE = 1,
251                 EX_FILENAME,
252                 EX_DISPLAY,
253                 EX_LYXSCALE,
254                 EX_DRAFT,
255                 EX_BOUNDINGBOX,
256                 EX_CLIP,
257                 EX_EXTRA,
258                 EX_HEIGHT,
259                 EX_KEEPASPECTRATIO,
260                 EX_ROTATEANGLE,
261                 EX_ROTATEORIGIN,
262                 EX_SCALE,
263                 EX_WIDTH,
264                 EX_END
265         };
266
267         keyword_item external_tags[] = {
268                 { "\\end_inset",     EX_END },
269                 { "boundingBox",     EX_BOUNDINGBOX },
270                 { "clip",            EX_CLIP },
271                 { "display",         EX_DISPLAY},
272                 { "draft",           EX_DRAFT},
273                 { "extra",           EX_EXTRA },
274                 { "filename",        EX_FILENAME},
275                 { "height",          EX_HEIGHT },
276                 { "keepAspectRatio", EX_KEEPASPECTRATIO },
277                 { "lyxscale",        EX_LYXSCALE},
278                 { "rotateAngle",     EX_ROTATEANGLE },
279                 { "rotateOrigin",    EX_ROTATEORIGIN },
280                 { "scale",           EX_SCALE },
281                 { "template",        EX_TEMPLATE },
282                 { "width",           EX_WIDTH }
283         };
284
285         PushPopHelper pph(lex, external_tags, EX_END);
286
287         bool found_end  = false;
288         bool read_error = false;
289
290         while (lex.isOK()) {
291                 switch (lex.lex()) {
292                 case EX_TEMPLATE:
293                         lex.next();
294                         templatename_ = lex.getString();
295                         break;
296
297                 case EX_FILENAME: {
298                         lex.eatLine();
299                         string const name = lex.getString();
300                         filename.set(name, buffer.filePath());
301                         // maybe this file is embedded
302                         EmbeddedFiles::EmbeddedFileList::const_iterator it = buffer.embeddedFiles().find(filename.toFilesystemEncoding());
303                         if (it != buffer.embeddedFiles().end())
304                                 // using available file, embedded or external, depending on file availability and
305                                 // embedding status.
306                                 filename = DocFileName(it->availableFile(&buffer));
307                         break;
308                 }
309
310                 case EX_DISPLAY: {
311                         lex.next();
312                         string const name = lex.getString();
313                         display = external::displayTranslator().find(name);
314                         break;
315                 }
316
317                 case EX_LYXSCALE:
318                         lex.next();
319                         lyxscale = lex.getInteger();
320                         break;
321
322                 case EX_DRAFT:
323                         draft = true;
324                         break;
325
326                 case EX_BOUNDINGBOX:
327                         lex.next();
328                         clipdata.bbox.xl = lex.getInteger();
329                         lex.next();
330                         clipdata.bbox.yb = lex.getInteger();
331                         lex.next();
332                         clipdata.bbox.xr = lex.getInteger();
333                         lex.next();
334                         clipdata.bbox.yt = lex.getInteger();
335                         break;
336
337                 case EX_CLIP:
338                         clipdata.clip = true;
339                         break;
340
341                 case EX_EXTRA: {
342                         lex.next();
343                         string const name = lex.getString();
344                         lex.next();
345                         extradata.set(name, lex.getString());
346                         break;
347                 }
348
349                 case EX_HEIGHT:
350                         lex.next();
351                         resizedata.height = Length(lex.getString());
352                         break;
353
354                 case EX_KEEPASPECTRATIO:
355                         resizedata.keepAspectRatio = true;
356                         break;
357
358                 case EX_ROTATEANGLE:
359                         lex.next();
360                         rotationdata.angle = lex.getString();
361                         break;
362
363                 case EX_ROTATEORIGIN:
364                         lex.next();
365                         rotationdata.origin(lex.getString());
366                         break;
367
368                 case EX_SCALE:
369                         lex.next();
370                         resizedata.scale = lex.getString();
371                         break;
372
373                 case EX_WIDTH:
374                         lex.next();
375                         resizedata.width = Length(lex.getString());
376                         break;
377
378                 case EX_END:
379                         found_end = true;
380                         break;
381
382                 default:
383                         lex.printError("ExternalInset::read: Wrong tag: $$Token");
384                         read_error = true;
385                         break;
386                 }
387
388                 if (found_end || read_error)
389                         break;
390         }
391
392         if (!found_end)
393                 lex.printError("ExternalInsetParams::read: Missing \\end_inset.");
394
395         // This is a trick to make sure that the data are self-consistent.
396         settemplate(templatename_);
397
398         if (lyxerr.debugging(Debug::EXTERNAL)) {
399                 lyxerr  << "InsetExternalParams::read:\n";
400                 write(buffer, lyxerr);
401         }
402
403         return !read_error;
404 }
405
406
407 InsetExternal::InsetExternal()
408         : renderer_(new RenderButton)
409 {}
410
411
412 InsetExternal::InsetExternal(InsetExternal const & other)
413         : Inset(other),
414           boost::signals::trackable(),
415           params_(other.params_),
416           renderer_(other.renderer_->clone(this))
417 {}
418
419
420 Inset * InsetExternal::clone() const
421 {
422         return new InsetExternal(*this);
423 }
424
425
426 InsetExternal::~InsetExternal()
427 {
428         InsetExternalMailer(*this).hideDialog();
429 }
430
431
432 void InsetExternal::statusChanged() const
433 {
434         updateFrontend();
435 }
436
437
438 void InsetExternal::doDispatch(Cursor & cur, FuncRequest & cmd)
439 {
440         switch (cmd.action) {
441
442         case LFUN_EXTERNAL_EDIT: {
443                 Buffer const & buffer = cur.buffer();
444                 InsetExternalParams p;
445                 InsetExternalMailer::string2params(to_utf8(cmd.argument()), buffer, p);
446                 external::editExternal(p, buffer);
447                 break;
448         }
449
450         case LFUN_INSET_MODIFY: {
451                 Buffer const & buffer = cur.buffer();
452                 InsetExternalParams p;
453                 InsetExternalMailer::string2params(to_utf8(cmd.argument()), buffer, p);
454                 setParams(p, buffer);
455                 break;
456         }
457
458         case LFUN_INSET_DIALOG_UPDATE:
459                 InsetExternalMailer(*this).updateDialog(&cur.bv());
460                 break;
461
462         case LFUN_MOUSE_RELEASE:
463                 if (!cur.selection())
464                         InsetExternalMailer(*this).showDialog(&cur.bv());
465                 break;
466
467         default:
468                 Inset::doDispatch(cur, cmd);
469         }
470 }
471
472
473 bool InsetExternal::getStatus(Cursor & cur, FuncRequest const & cmd,
474                 FuncStatus & flag) const
475 {
476         switch (cmd.action) {
477
478         case LFUN_EXTERNAL_EDIT:
479         case LFUN_INSET_MODIFY:
480         case LFUN_INSET_DIALOG_UPDATE:
481                 flag.enabled(true);
482                 return true;
483
484         default:
485                 return Inset::getStatus(cur, cmd, flag);
486         }
487 }
488
489
490 void InsetExternal::registerEmbeddedFiles(Buffer const &,
491         EmbeddedFiles & files) const
492 {
493         files.registerFile(params_.filename.absFilename(), false, this);
494 }
495
496
497 void InsetExternal::edit(Cursor & cur, bool)
498 {
499         InsetExternalMailer(*this).showDialog(&cur.bv());
500 }
501
502
503 void InsetExternal::metrics(MetricsInfo & mi, Dimension & dim) const
504 {
505         renderer_->metrics(mi, dim);
506 }
507
508
509 void InsetExternal::draw(PainterInfo & pi, int x, int y) const
510 {
511         renderer_->draw(pi, x, y);
512 }
513
514
515 namespace {
516
517 enum RenderType {
518         RENDERBUTTON,
519         RENDERGRAPHIC,
520         RENDERPREVIEW
521 };
522
523
524 RenderType getRenderType(InsetExternalParams const & p)
525 {
526         if (!external::getTemplatePtr(p) ||
527             p.filename.empty() ||
528             p.display == external::NoDisplay)
529                 return RENDERBUTTON;
530
531         if (p.display == external::PreviewDisplay) {
532                 if (RenderPreview::status() != LyXRC::PREVIEW_OFF)
533                         return RENDERPREVIEW;
534                 return RENDERBUTTON;
535         }
536
537         if (p.display == external::DefaultDisplay &&
538             lyxrc.display_graphics == graphics::NoDisplay)
539                 return RENDERBUTTON;
540         return RENDERGRAPHIC;
541 }
542
543
544 graphics::Params get_grfx_params(InsetExternalParams const & eparams)
545 {
546         graphics::Params gparams;
547
548         gparams.filename = eparams.filename;
549         gparams.scale = eparams.lyxscale;
550         if (eparams.clipdata.clip)
551                 gparams.bb = eparams.clipdata.bbox;
552         gparams.angle = convert<double>(eparams.rotationdata.adjAngle());
553
554         switch (eparams.display) {
555         case external::DefaultDisplay:
556                 gparams.display = graphics::DefaultDisplay;
557                 break;
558         case external::MonochromeDisplay:
559                 gparams.display = graphics::MonochromeDisplay;
560                 break;
561         case external::GrayscaleDisplay:
562                 gparams.display = graphics::GrayscaleDisplay;
563                 break;
564         case external::ColorDisplay:
565                 gparams.display = graphics::ColorDisplay;
566                 break;
567         case external::NoDisplay:
568                 gparams.display = graphics::NoDisplay;
569                 break;
570         default:
571                 BOOST_ASSERT(false);
572         }
573         if (gparams.display == graphics::DefaultDisplay)
574                 gparams.display = graphics::DisplayType(lyxrc.display_graphics);
575         // Override the above if we're not using a gui
576         if (!use_gui)
577                 gparams.display = graphics::NoDisplay;
578
579         return gparams;
580 }
581
582
583 docstring const getScreenLabel(InsetExternalParams const & params,
584                             Buffer const & buffer)
585 {
586         external::Template const * const ptr =
587                 external::getTemplatePtr(params);
588         if (!ptr)
589                 // FIXME UNICODE
590                 return support::bformat((_("External template %1$s is not installed")),
591                                         from_utf8(params.templatename()));
592         // FIXME UNICODE
593         docstring gui = _(ptr->guiName);
594         return from_utf8(external::doSubstitution(params, buffer,
595                                 to_utf8(gui), false));
596 }
597
598 void add_preview_and_start_loading(RenderMonitoredPreview &,
599                                    InsetExternal const &,
600                                    Buffer const &);
601
602 } // namespace anon
603
604
605 InsetExternalParams const & InsetExternal::params() const
606 {
607         return params_;
608 }
609
610
611 void InsetExternal::setParams(InsetExternalParams const & p,
612                               Buffer const & buffer)
613 {
614         params_ = p;
615
616         // Subsequent calls to the InsetExternal::Params default constructor
617         // will use this.
618         defaultTemplateName = params_.templatename();
619
620         switch (getRenderType(params_)) {
621         case RENDERBUTTON: {
622                 RenderButton * button_ptr = renderer_->asButton();
623                 if (!button_ptr) {
624                         renderer_.reset(new RenderButton);
625                         button_ptr = renderer_->asButton();
626                 }
627
628                 button_ptr->update(getScreenLabel(params_, buffer), true);
629                 break;
630         }
631
632         case RENDERGRAPHIC: {
633                 RenderGraphic * graphic_ptr = renderer_->asGraphic();
634                 if (!graphic_ptr) {
635                         renderer_.reset(new RenderGraphic(this));
636                         graphic_ptr = renderer_->asGraphic();
637                 }
638
639                 graphic_ptr->update(get_grfx_params(params_));
640
641                 break;
642         }
643
644         case RENDERPREVIEW: {
645                 RenderMonitoredPreview * preview_ptr =
646                         renderer_->asMonitoredPreview();
647                 if (!preview_ptr) {
648                         renderer_.reset(new RenderMonitoredPreview(this));
649                         preview_ptr = renderer_->asMonitoredPreview();
650                         preview_ptr->fileChanged(
651                                 boost::bind(&InsetExternal::fileChanged, this));
652                 }
653
654                 if (preview_ptr->monitoring())
655                         preview_ptr->stopMonitoring();
656                 add_preview_and_start_loading(*preview_ptr, *this, buffer);
657
658                 break;
659         }
660         }
661 }
662
663
664 void InsetExternal::fileChanged() const
665 {
666         Buffer const * const buffer = updateFrontend();
667         if (!buffer)
668                 return;
669
670         RenderMonitoredPreview * const ptr = renderer_->asMonitoredPreview();
671         BOOST_ASSERT(ptr);
672
673         ptr->removePreview(*buffer);
674         add_preview_and_start_loading(*ptr, *this, *buffer);
675 }
676
677
678 void InsetExternal::write(Buffer const & buffer, ostream & os) const
679 {
680         params_.write(buffer, os);
681 }
682
683
684 void InsetExternal::read(Buffer const & buffer, Lexer & lex)
685 {
686         InsetExternalParams params;
687         if (params.read(buffer, lex))
688                 setParams(params, buffer);
689 }
690
691
692 int InsetExternal::latex(Buffer const & buf, odocstream & os,
693                          OutputParams const & runparams) const
694 {
695         if (params_.draft) {
696                 // FIXME UNICODE
697                 os << "\\fbox{\\ttfamily{}"
698                    << from_utf8(params_.filename.outputFilename(buf.filePath()))
699                    << "}\n";
700                 return 1;
701         }
702
703         // "nice" means that the buffer is exported to LaTeX format but not
704         // run through the LaTeX compiler.
705         // If we're running through the LaTeX compiler, we should write the
706         // generated files in the buffer's temporary directory.
707         bool const external_in_tmpdir = !runparams.nice;
708         bool const dryrun = runparams.dryrun || runparams.inComment;
709
710         // If the template has specified a PDFLaTeX output, then we try and
711         // use that.
712         if (runparams.flavor == OutputParams::PDFLATEX) {
713                 external::Template const * const et_ptr =
714                         external::getTemplatePtr(params_);
715                 if (!et_ptr)
716                         return 0;
717                 external::Template const & et = *et_ptr;
718
719                 external::Template::Formats::const_iterator cit =
720                         et.formats.find("PDFLaTeX");
721
722                 if (cit != et.formats.end()) {
723                         return external::writeExternal(params_, "PDFLaTeX",
724                                                        buf, os,
725                                                        *(runparams.exportdata),
726                                                        external_in_tmpdir,
727                                                        dryrun);
728                 }
729         }
730
731         return external::writeExternal(params_, "LaTeX", buf, os,
732                                        *(runparams.exportdata),
733                                        external_in_tmpdir,
734                                        dryrun);
735 }
736
737
738 int InsetExternal::plaintext(Buffer const & buf, odocstream & os,
739                              OutputParams const & runparams) const
740 {
741         os << '\n'; // output external material on a new line
742         external::writeExternal(params_, "Ascii", buf, os,
743                                 *(runparams.exportdata), false,
744                                 runparams.dryrun || runparams.inComment);
745         return PLAINTEXT_NEWLINE;
746 }
747
748
749 int InsetExternal::docbook(Buffer const & buf, odocstream & os,
750                            OutputParams const & runparams) const
751 {
752         return external::writeExternal(params_, "DocBook", buf, os,
753                                        *(runparams.exportdata), false,
754                                        runparams.dryrun || runparams.inComment);
755 }
756
757
758 void InsetExternal::validate(LaTeXFeatures & features) const
759 {
760         if (params_.draft)
761                 return;
762
763         external::Template const * const et_ptr =
764                 external::getTemplatePtr(params_);
765         if (!et_ptr)
766                 return;
767         external::Template const & et = *et_ptr;
768
769         string format;
770         switch (features.runparams().flavor) {
771         case OutputParams::LATEX:
772                 format = "LaTeX";
773                 break;
774         case OutputParams::PDFLATEX:
775                 format = "PDFLaTeX";
776                 break;
777         case OutputParams::XML:
778                 format = "DocBook";
779                 break;
780         }
781         external::Template::Formats::const_iterator cit =
782                 et.formats.find(format);
783         if (cit == et.formats.end())
784                 return;
785
786         // FIXME: We don't need that always
787         features.require("lyxdot");
788
789         vector<string>::const_iterator it  = cit->second.requirements.begin();
790         vector<string>::const_iterator end = cit->second.requirements.end();
791         for (; it != end; ++it)
792                 features.require(*it);
793
794         external::TemplateManager & etm = external::TemplateManager::get();
795
796         it  = cit->second.preambleNames.begin();
797         end = cit->second.preambleNames.end();
798         for (; it != end; ++it) {
799                 string const preamble = etm.getPreambleDefByName(*it);
800                 if (!preamble.empty())
801                         features.addPreambleSnippet(preamble);
802         }
803 }
804
805
806 //
807 // preview stuff
808 //
809
810 namespace {
811
812 bool preview_wanted(InsetExternalParams const & params)
813 {
814         return params.display == external::PreviewDisplay &&
815                 params.filename.isReadableFile();
816 }
817
818
819 docstring const latex_string(InsetExternal const & inset, Buffer const & buffer)
820 {
821         odocstringstream os;
822         // We don't need to set runparams.encoding since it is not used by
823         // latex().
824         OutputParams runparams(0);
825         runparams.flavor = OutputParams::LATEX;
826         inset.latex(buffer, os, runparams);
827         return os.str();
828 }
829
830
831 void add_preview_and_start_loading(RenderMonitoredPreview & renderer,
832                                    InsetExternal const & inset,
833                                    Buffer const & buffer)
834 {
835         InsetExternalParams const & params = inset.params();
836
837         if (RenderPreview::status() != LyXRC::PREVIEW_OFF &&
838             preview_wanted(params)) {
839                 renderer.setAbsFile(params.filename);
840                 docstring const snippet = latex_string(inset, buffer);
841                 renderer.addPreview(snippet, buffer);
842                 renderer.startLoading(buffer);
843         }
844 }
845
846 } // namespace anon
847
848
849 void InsetExternal::addPreview(graphics::PreviewLoader & ploader) const
850 {
851         RenderMonitoredPreview * const ptr = renderer_->asMonitoredPreview();
852         if (!ptr)
853                 return;
854
855         if (preview_wanted(params())) {
856                 ptr->setAbsFile(params_.filename);
857                 docstring const snippet = latex_string(*this, ploader.buffer());
858                 ptr->addPreview(snippet, ploader);
859         }
860 }
861
862
863 /// Mailer stuff
864
865 string const InsetExternalMailer::name_("external");
866
867 InsetExternalMailer::InsetExternalMailer(InsetExternal & inset)
868         : inset_(inset)
869 {}
870
871
872 string const InsetExternalMailer::inset2string(Buffer const & buffer) const
873 {
874         return params2string(inset_.params(), buffer);
875 }
876
877
878 void InsetExternalMailer::string2params(string const & in,
879                                         Buffer const & buffer,
880                                         InsetExternalParams & params)
881 {
882         params = InsetExternalParams();
883         if (in.empty())
884                 return;
885
886         istringstream data(in);
887         Lexer lex(0,0);
888         lex.setStream(data);
889
890         string name;
891         lex >> name;
892         if (!lex || name != name_)
893                 return print_mailer_error("InsetExternalMailer", in, 1, name_);
894
895         // This is part of the inset proper that is usually swallowed
896         // by Text::readInset
897         string id;
898         lex >> id;
899         if (!lex || id != "External")
900                 return print_mailer_error("InsetBoxMailer", in, 2, "External");
901
902         params.read(buffer, lex);
903 }
904
905
906 string const
907 InsetExternalMailer::params2string(InsetExternalParams const & params,
908                                    Buffer const & buffer)
909 {
910         ostringstream data;
911         data << name_ << ' ';
912         params.write(buffer, data);
913         data << "\\end_inset\n";
914         return data.str();
915 }
916
917 } // namespace lyx