2 * \file InsetInclude.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
7 * \author Richard Heck (conversion to InsetCommand)
9 * Full author contact details are available in file CREDITS.
14 #include "InsetInclude.h"
17 #include "buffer_funcs.h"
18 #include "BufferList.h"
19 #include "BufferParams.h"
20 #include "BufferView.h"
22 #include "DispatchResult.h"
23 #include "ErrorList.h"
26 #include "FuncRequest.h"
27 #include "FuncStatus.h"
28 #include "LaTeXFeatures.h"
29 #include "LayoutFile.h"
30 #include "LayoutModuleList.h"
35 #include "MetricsInfo.h"
36 #include "OutputParams.h"
37 #include "TextClass.h"
38 #include "TocBackend.h"
40 #include "frontends/alert.h"
41 #include "frontends/Painter.h"
43 #include "graphics/PreviewImage.h"
44 #include "graphics/PreviewLoader.h"
46 #include "insets/InsetLabel.h"
47 #include "insets/InsetListingsParams.h"
48 #include "insets/RenderPreview.h"
50 #include "support/convert.h"
51 #include "support/debug.h"
52 #include "support/docstream.h"
53 #include "support/FileNameList.h"
54 #include "support/filetools.h"
55 #include "support/gettext.h"
56 #include "support/lassert.h"
57 #include "support/lstrings.h" // contains
58 #include "support/lyxalgo.h"
60 #include <boost/bind.hpp>
63 using namespace lyx::support
;
67 namespace Alert
= frontend::Alert
;
72 docstring
const uniqueID()
74 static unsigned int seed
= 1000;
75 return "file" + convert
<docstring
>(++seed
);
79 /// the type of inclusion
81 INCLUDE
, VERB
, INPUT
, VERBAST
, LISTINGS
, NONE
85 Types
type(string
const & s
)
89 if (s
== "verbatiminput")
91 if (s
== "verbatiminput*")
93 if (s
== "lstinputlisting")
101 Types
type(InsetCommandParams
const & params
)
103 return type(params
.getCmdName());
107 bool isListings(InsetCommandParams
const & params
)
109 return type(params
) == LISTINGS
;
113 bool isVerbatim(InsetCommandParams
const & params
)
115 Types
const t
= type(params
);
116 return t
== VERB
|| t
== VERBAST
;
120 bool isInputOrInclude(InsetCommandParams
const & params
)
122 Types
const t
= type(params
);
123 return t
== INPUT
|| t
== INCLUDE
;
127 FileName
const masterFileName(Buffer
const & buffer
)
129 return buffer
.masterBuffer()->fileName();
133 void add_preview(RenderMonitoredPreview
&, InsetInclude
const &, Buffer
const &);
136 string
const parentFilename(Buffer
const & buffer
)
138 return buffer
.absFileName();
142 FileName
const includedFilename(Buffer
const & buffer
,
143 InsetCommandParams
const & params
)
145 return makeAbsPath(to_utf8(params
["filename"]),
146 onlyPath(parentFilename(buffer
)));
150 InsetLabel
* createLabel(docstring
const & label_str
)
152 if (label_str
.empty())
154 InsetCommandParams
icp(LABEL_CODE
);
155 icp
["name"] = label_str
;
156 return new InsetLabel(icp
);
162 InsetInclude::InsetInclude(InsetCommandParams
const & p
)
163 : InsetCommand(p
, "include"), include_label(uniqueID()),
164 preview_(new RenderMonitoredPreview(this)), failedtoload_(false),
165 set_label_(false), label_(0), child_buffer_(0)
167 preview_
->fileChanged(boost::bind(&InsetInclude::fileChanged
, this));
169 if (isListings(params())) {
170 InsetListingsParams
listing_params(to_utf8(p
["lstparams"]));
171 label_
= createLabel(from_utf8(listing_params
.getParamValue("label")));
176 InsetInclude::InsetInclude(InsetInclude
const & other
)
177 : InsetCommand(other
), include_label(other
.include_label
),
178 preview_(new RenderMonitoredPreview(this)), failedtoload_(false),
179 set_label_(false), label_(0), child_buffer_(0)
181 preview_
->fileChanged(boost::bind(&InsetInclude::fileChanged
, this));
184 label_
= new InsetLabel(*other
.label_
);
188 InsetInclude::~InsetInclude()
194 void InsetInclude::setBuffer(Buffer
& buffer
)
196 InsetCommand::setBuffer(buffer
);
198 label_
->setBuffer(buffer
);
202 ParamInfo
const & InsetInclude::findInfo(string
const & /* cmdName */)
205 // This is only correct for the case of listings, but it'll do for now.
206 // In the other cases, this second parameter should just be empty.
207 static ParamInfo param_info_
;
208 if (param_info_
.empty()) {
209 param_info_
.add("filename", ParamInfo::LATEX_REQUIRED
);
210 param_info_
.add("lstparams", ParamInfo::LATEX_OPTIONAL
);
216 bool InsetInclude::isCompatibleCommand(string
const & s
)
218 return type(s
) != NONE
;
222 void InsetInclude::doDispatch(Cursor
& cur
, FuncRequest
& cmd
)
224 LASSERT(cur
.buffer() == &buffer(), return);
225 switch (cmd
.action
) {
227 case LFUN_INSET_EDIT
: {
228 editIncluded(to_utf8(params()["filename"]));
232 case LFUN_INSET_MODIFY
: {
233 // It should be OK just to invalidate the cache is setParams()
235 // child_buffer_ = 0;
236 InsetCommandParams
p(INCLUDE_CODE
);
237 if (cmd
.getArg(0) == "changetype") {
238 InsetCommand::doDispatch(cur
, cmd
);
241 InsetCommand::string2params("include", to_utf8(cmd
.argument()), p
);
242 if (!p
.getCmdName().empty()) {
244 InsetListingsParams
new_params(to_utf8(p
["lstparams"]));
245 docstring
const new_label
=
246 from_utf8(new_params
.getParamValue("label"));
248 if (new_label
.empty()) {
254 old_label
= label_
->getParam("name");
256 label_
= createLabel(new_label
);
257 label_
->setBuffer(buffer());
260 if (new_label
!= old_label
) {
261 label_
->updateCommand(new_label
);
262 // the label might have been adapted (duplicate)
263 if (new_label
!= label_
->getParam("name")) {
264 new_params
.addParam("label", "{" +
265 to_utf8(label_
->getParam("name")) + "}", true);
266 p
["lstparams"] = from_utf8(new_params
.params());
277 //pass everything else up the chain
279 InsetCommand::doDispatch(cur
, cmd
);
285 void InsetInclude::editIncluded(string
const & file
)
287 string
const ext
= support::getExtension(file
);
289 FuncRequest
fr(LFUN_BUFFER_CHILD_OPEN
, file
);
292 // tex file or other text file in verbatim mode
293 formats
.edit(buffer(),
294 support::makeAbsPath(file
, support::onlyPath(buffer().absFileName())),
299 bool InsetInclude::getStatus(Cursor
& cur
, FuncRequest
const & cmd
,
300 FuncStatus
& flag
) const
302 switch (cmd
.action
) {
304 case LFUN_INSET_EDIT
:
305 case LFUN_INSET_MODIFY
:
306 flag
.setEnabled(true);
310 return InsetCommand::getStatus(cur
, cmd
, flag
);
315 void InsetInclude::setParams(InsetCommandParams
const & p
)
317 // invalidate the cache
320 InsetCommand::setParams(p
);
323 if (preview_
->monitoring())
324 preview_
->stopMonitoring();
326 if (type(params()) == INPUT
)
327 add_preview(*preview_
, *this, buffer());
329 buffer().updateBibfilesCache();
333 docstring
InsetInclude::screenLabel() const
337 switch (type(params())) {
339 temp
= buffer().B_("Input");
342 temp
= buffer().B_("Verbatim Input");
345 temp
= buffer().B_("Verbatim Input*");
348 temp
= buffer().B_("Include");
351 temp
= listings_label_
;
354 LASSERT(false, /**/);
359 if (params()["filename"].empty())
362 temp
+= from_utf8(onlyFilename(to_utf8(params()["filename"])));
368 Buffer
* InsetInclude::getChildBuffer() const
370 Buffer
* childBuffer
= loadIfNeeded();
372 // FIXME: recursive includes
373 return (childBuffer
== &buffer()) ? 0 : childBuffer
;
377 Buffer
* InsetInclude::loadIfNeeded() const
379 // Don't try to load it again if we failed before.
380 if (failedtoload_
|| isVerbatim(params()) || isListings(params()))
383 // Use cached Buffer if possible.
384 if (child_buffer_
!= 0) {
385 if (theBufferList().isLoaded(child_buffer_
))
386 return child_buffer_
;
387 // Buffer vanished, so invalidate cache and try to reload.
391 string
const parent_filename
= buffer().absFileName();
392 FileName
const included_file
=
393 makeAbsPath(to_utf8(params()["filename"]), onlyPath(parent_filename
));
395 if (!isLyXFilename(included_file
.absFilename()))
398 Buffer
* child
= theBufferList().getBuffer(included_file
);
400 // the readonly flag can/will be wrong, not anymore I think.
401 if (!included_file
.exists())
404 child
= theBufferList().newBuffer(included_file
.absFilename());
406 // Buffer creation is not possible.
409 if (!child
->loadLyXFile(included_file
)) {
410 failedtoload_
= true;
411 //close the buffer we just opened
412 theBufferList().release(child
);
416 if (!child
->errorList("Parse").empty()) {
417 // FIXME: Do something.
420 child
->setParent(&buffer());
421 // Cache the child buffer.
422 child_buffer_
= child
;
427 int InsetInclude::latex(odocstream
& os
, OutputParams
const & runparams
) const
429 string incfile
= to_utf8(params()["filename"]);
431 // Do nothing if no file name has been specified
435 FileName
const included_file
= includedFilename(buffer(), params());
437 // Check we're not trying to include ourselves.
438 // FIXME RECURSIVE INCLUDE
439 // This isn't sufficient, as the inclusion could be downstream.
440 // But it'll have to do for now.
441 if (isInputOrInclude(params()) &&
442 buffer().absFileName() == included_file
.absFilename())
444 Alert::error(_("Recursive input"),
445 bformat(_("Attempted to include file %1$s in itself! "
446 "Ignoring inclusion."), from_utf8(incfile
)));
450 Buffer
const * const masterBuffer
= buffer().masterBuffer();
452 // if incfile is relative, make it relative to the master
454 if (!FileName::isAbsolute(incfile
)) {
456 incfile
= to_utf8(makeRelPath(from_utf8(included_file
.absFilename()),
457 from_utf8(masterBuffer
->filePath())));
460 // write it to a file (so far the complete file)
464 if (type(params()) == LISTINGS
) {
465 exportfile
= incfile
;
466 mangled
= DocFileName(included_file
).mangledFilename();
468 exportfile
= changeExtension(incfile
, ".tex");
469 mangled
= DocFileName(changeExtension(included_file
.absFilename(), ".tex")).
473 FileName
const writefile(makeAbsPath(mangled
, masterBuffer
->temppath()));
477 else if (!isValidLaTeXFilename(incfile
)) {
478 frontend::Alert::warning(_("Invalid filename"),
479 _("The following filename is likely to cause trouble "
480 "when running the exported file through LaTeX: ") +
483 LYXERR(Debug::LATEX
, "incfile:" << incfile
);
484 LYXERR(Debug::LATEX
, "exportfile:" << exportfile
);
485 LYXERR(Debug::LATEX
, "writefile:" << writefile
);
487 if (runparams
.inComment
|| runparams
.dryrun
) {
488 //Don't try to load or copy the file if we're
489 //in a comment or doing a dryrun
490 } else if (isInputOrInclude(params()) &&
491 isLyXFilename(included_file
.absFilename())) {
492 //if it's a LyX file and we're inputting or including,
493 //try to load it so we can write the associated latex
497 Buffer
* tmp
= theBufferList().getBuffer(included_file
);
499 if (tmp
->params().baseClass() != masterBuffer
->params().baseClass()) {
501 docstring text
= bformat(_("Included file `%1$s'\n"
502 "has textclass `%2$s'\n"
503 "while parent file has textclass `%3$s'."),
504 included_file
.displayName(),
505 from_utf8(tmp
->params().documentClass().name()),
506 from_utf8(masterBuffer
->params().documentClass().name()));
507 Alert::warning(_("Different textclasses"), text
, true);
510 // Make sure modules used in child are all included in master
511 // FIXME It might be worth loading the children's modules into the master
512 // over in BufferParams rather than doing this check.
513 LayoutModuleList
const masterModules
= masterBuffer
->params().getModules();
514 LayoutModuleList
const childModules
= tmp
->params().getModules();
515 LayoutModuleList::const_iterator it
= childModules
.begin();
516 LayoutModuleList::const_iterator end
= childModules
.end();
517 for (; it
!= end
; ++it
) {
518 string
const module
= *it
;
519 LayoutModuleList::const_iterator found
=
520 find(masterModules
.begin(), masterModules
.end(), module
);
521 if (found
== masterModules
.end()) {
522 docstring text
= bformat(_("Included file `%1$s'\n"
523 "uses module `%2$s'\n"
524 "which is not used in parent file."),
525 included_file
.displayName(), from_utf8(module
));
526 Alert::warning(_("Module not found"), text
);
530 tmp
->markDepClean(masterBuffer
->temppath());
532 // FIXME: handle non existing files
533 // FIXME: Second argument is irrelevant!
534 // since only_body is true, makeLaTeXFile will not look at second
535 // argument. Should we set it to string(), or should makeLaTeXFile
536 // make use of it somehow? (JMarc 20031002)
537 // The included file might be written in a different encoding
538 Encoding
const * const oldEnc
= runparams
.encoding
;
539 runparams
.encoding
= &tmp
->params().encoding();
540 tmp
->makeLaTeXFile(writefile
,
541 masterFileName(buffer()).onlyPath().absFilename(),
543 runparams
.encoding
= oldEnc
;
545 // In this case, it's not a LyX file, so we copy the file
546 // to the temp dir, so that .aux files etc. are not created
547 // in the original dir. Files included by this file will be
548 // found via input@path, see ../Buffer.cpp.
549 unsigned long const checksum_in
= included_file
.checksum();
550 unsigned long const checksum_out
= writefile
.checksum();
552 if (checksum_in
!= checksum_out
) {
553 if (!included_file
.copyTo(writefile
)) {
556 to_utf8(bformat(_("Could not copy the file\n%1$s\n"
557 "into the temporary directory."),
558 from_utf8(included_file
.absFilename()))));
564 string
const tex_format
= (runparams
.flavor
== OutputParams::LATEX
) ?
565 "latex" : "pdflatex";
566 switch (type(params())) {
569 incfile
= latex_path(incfile
);
571 os
<< '\\' << from_ascii(params().getCmdName()) << '{'
572 << from_utf8(incfile
) << '}';
576 runparams
.exportdata
->addExternalFile(tex_format
, writefile
,
579 // \input wants file with extension (default is .tex)
580 if (!isLyXFilename(included_file
.absFilename())) {
581 incfile
= latex_path(incfile
);
583 os
<< '\\' << from_ascii(params().getCmdName())
584 << '{' << from_utf8(incfile
) << '}';
586 incfile
= changeExtension(incfile
, ".tex");
587 incfile
= latex_path(incfile
);
589 os
<< '\\' << from_ascii(params().getCmdName())
590 << '{' << from_utf8(incfile
) << '}';
595 os
<< '\\' << from_ascii(params().getCmdName());
596 string
const opt
= to_utf8(params()["lstparams"]);
597 // opt is set in QInclude dialog and should have passed validation.
598 InsetListingsParams
params(opt
);
599 if (!params
.params().empty())
600 os
<< "[" << from_utf8(params
.params()) << "]";
601 os
<< '{' << from_utf8(incfile
) << '}';
605 runparams
.exportdata
->addExternalFile(tex_format
, writefile
,
608 // \include don't want extension and demands that the
609 // file really have .tex
610 incfile
= changeExtension(incfile
, string());
611 incfile
= latex_path(incfile
);
613 os
<< '\\' << from_ascii(params().getCmdName()) << '{'
614 << from_utf8(incfile
) << '}';
625 docstring
InsetInclude::xhtml(odocstream
& os
, OutputParams
const &rp
) const
630 // For verbatim and listings, we just include the contents of the file as-is.
631 // In the case of listings, we wrap it in <pre>.
632 bool const listing
= isListings(params());
633 if (listing
|| isVerbatim(params())) {
636 // FIXME: We don't know the encoding of the file, default to UTF-8.
637 os
<< includedFilename(buffer(), params()).fileContents("UTF-8");
643 // We don't (yet) know how to Input or Include non-LyX files.
644 // (If we wanted to get really arcane, we could run some tex2html
645 // converter on the included file. But that's just masochistic.)
646 string
const parent_filename
= buffer().absFileName();
647 FileName
const included_file
=
648 makeAbsPath(to_utf8(params()["filename"]), onlyPath(parent_filename
));
649 if (!isLyXFilename(included_file
.absFilename())) {
650 frontend::Alert::warning(_("Unsupported Inclusion"),
651 _("LyX does not know how to include non-LyX files when"
652 "generating HTML output. Offending file: ") +
653 params()["filename"]);
657 // In the other cases, we will generate the HTML and include it.
659 // Check we're not trying to include ourselves.
660 // FIXME RECURSIVE INCLUDE
661 if (buffer().absFileName() == included_file
.absFilename()) {
662 Alert::error(_("Recursive input"),
663 bformat(_("Attempted to include file %1$s in itself! "
664 "Ignoring inclusion."), params()["filename"]));
668 Buffer
const * const ibuf
= loadIfNeeded();
671 ibuf
->writeLyXHTMLSource(os
, rp
, true);
676 int InsetInclude::plaintext(odocstream
& os
, OutputParams
const &) const
678 if (isVerbatim(params()) || isListings(params())) {
679 os
<< '[' << screenLabel() << '\n';
680 // FIXME: We don't know the encoding of the file, default to UTF-8.
681 os
<< includedFilename(buffer(), params()).fileContents("UTF-8");
683 return PLAINTEXT_NEWLINE
+ 1; // one char on a separate line
685 docstring
const str
= '[' + screenLabel() + ']';
692 int InsetInclude::docbook(odocstream
& os
, OutputParams
const & runparams
) const
694 string incfile
= to_utf8(params()["filename"]);
696 // Do nothing if no file name has been specified
700 string
const included_file
= includedFilename(buffer(), params()).absFilename();
702 // Check we're not trying to include ourselves.
703 // FIXME RECURSIVE INCLUDE
704 // This isn't sufficient, as the inclusion could be downstream.
705 // But it'll have to do for now.
706 if (buffer().absFileName() == included_file
) {
707 Alert::error(_("Recursive input"),
708 bformat(_("Attempted to include file %1$s in itself! "
709 "Ignoring inclusion."), from_utf8(incfile
)));
713 // write it to a file (so far the complete file)
714 string
const exportfile
= changeExtension(incfile
, ".sgml");
715 DocFileName
writefile(changeExtension(included_file
, ".sgml"));
717 if (loadIfNeeded()) {
718 Buffer
* tmp
= theBufferList().getBuffer(FileName(included_file
));
720 string
const mangled
= writefile
.mangledFilename();
721 writefile
= makeAbsPath(mangled
,
722 buffer().masterBuffer()->temppath());
726 LYXERR(Debug::LATEX
, "incfile:" << incfile
);
727 LYXERR(Debug::LATEX
, "exportfile:" << exportfile
);
728 LYXERR(Debug::LATEX
, "writefile:" << writefile
);
730 tmp
->makeDocBookFile(writefile
, runparams
, true);
733 runparams
.exportdata
->addExternalFile("docbook", writefile
,
735 runparams
.exportdata
->addExternalFile("docbook-xml", writefile
,
738 if (isVerbatim(params()) || isListings(params())) {
739 os
<< "<inlinegraphic fileref=\""
740 << '&' << include_label
<< ';'
741 << "\" format=\"linespecific\">";
743 os
<< '&' << include_label
<< ';';
749 void InsetInclude::validate(LaTeXFeatures
& features
) const
751 string incfile
= to_utf8(params()["filename"]);
754 LASSERT(&buffer() == &features
.buffer(), /**/);
756 string
const included_file
=
757 includedFilename(buffer(), params()).absFilename();
759 if (isLyXFilename(included_file
))
760 writefile
= changeExtension(included_file
, ".sgml");
762 writefile
= included_file
;
764 if (!features
.runparams().nice
&& !isVerbatim(params()) && !isListings(params())) {
765 incfile
= DocFileName(writefile
).mangledFilename();
766 writefile
= makeAbsPath(incfile
,
767 buffer().masterBuffer()->temppath()).absFilename();
770 features
.includeFile(include_label
, writefile
);
772 if (isVerbatim(params()))
773 features
.require("verbatim");
774 else if (isListings(params()))
775 features
.require("listings");
777 // Here we must do the fun stuff...
778 // Load the file in the include if it needs
780 if (loadIfNeeded()) {
782 Buffer
* const tmp
= theBufferList().getBuffer(FileName(included_file
));
783 // make sure the buffer isn't us
784 // FIXME RECURSIVE INCLUDES
785 // This is not sufficient, as recursive includes could be
786 // more than a file away. But it will do for now.
787 if (tmp
&& tmp
!= &buffer()) {
788 // We must temporarily change features.buffer,
789 // otherwise it would always be the master buffer,
790 // and nested includes would not work.
791 features
.setBuffer(*tmp
);
792 tmp
->validate(features
);
793 features
.setBuffer(buffer());
799 void InsetInclude::fillWithBibKeys(BiblioInfo
& keys
,
800 InsetIterator
const & /*di*/) const
802 if (loadIfNeeded()) {
803 string
const included_file
= includedFilename(buffer(), params()).absFilename();
804 Buffer
* tmp
= theBufferList().getBuffer(FileName(included_file
));
805 BiblioInfo
const & newkeys
= tmp
->localBibInfo();
806 keys
.mergeBiblioInfo(newkeys
);
811 void InsetInclude::updateBibfilesCache()
813 Buffer
const * const child
= getChildBuffer();
815 child
->updateBibfilesCache(Buffer::UpdateChildOnly
);
819 support::FileNameList
const &
820 InsetInclude::getBibfilesCache() const
822 Buffer
const * const child
= getChildBuffer();
824 return child
->getBibfilesCache(Buffer::UpdateChildOnly
);
826 static support::FileNameList
const empty
;
831 void InsetInclude::metrics(MetricsInfo
& mi
, Dimension
& dim
) const
833 LASSERT(mi
.base
.bv
, /**/);
835 bool use_preview
= false;
836 if (RenderPreview::status() != LyXRC::PREVIEW_OFF
) {
837 graphics::PreviewImage
const * pimage
=
838 preview_
->getPreviewImage(mi
.base
.bv
->buffer());
839 use_preview
= pimage
&& pimage
->image();
843 preview_
->metrics(mi
, dim
);
847 button_
.update(screenLabel(), true);
849 button_
.metrics(mi
, dim
);
852 Box
b(0, dim
.wid
, -dim
.asc
, dim
.des
);
857 void InsetInclude::draw(PainterInfo
& pi
, int x
, int y
) const
859 LASSERT(pi
.base
.bv
, /**/);
861 bool use_preview
= false;
862 if (RenderPreview::status() != LyXRC::PREVIEW_OFF
) {
863 graphics::PreviewImage
const * pimage
=
864 preview_
->getPreviewImage(pi
.base
.bv
->buffer());
865 use_preview
= pimage
&& pimage
->image();
869 preview_
->draw(pi
, x
, y
);
871 button_
.draw(pi
, x
, y
);
875 docstring
InsetInclude::contextMenu(BufferView
const &, int, int) const
877 return from_ascii("context-include");
881 Inset::DisplayType
InsetInclude::display() const
883 return type(params()) == INPUT
? Inline
: AlignCenter
;
892 void InsetInclude::fileChanged() const
894 Buffer
const * const buffer
= updateFrontend();
898 preview_
->removePreview(*buffer
);
899 add_preview(*preview_
.get(), *this, *buffer
);
900 preview_
->startLoading(*buffer
);
906 bool preview_wanted(InsetCommandParams
const & params
, Buffer
const & buffer
)
908 FileName
const included_file
= includedFilename(buffer
, params
);
910 return type(params
) == INPUT
&& params
.preview() &&
911 included_file
.isReadableFile();
915 docstring
latexString(InsetInclude
const & inset
)
918 // We don't need to set runparams.encoding since this will be done
919 // by latex() anyway.
920 OutputParams
runparams(0);
921 runparams
.flavor
= OutputParams::LATEX
;
922 inset
.latex(os
, runparams
);
928 void add_preview(RenderMonitoredPreview
& renderer
, InsetInclude
const & inset
,
929 Buffer
const & buffer
)
931 InsetCommandParams
const & params
= inset
.params();
932 if (RenderPreview::status() != LyXRC::PREVIEW_OFF
&&
933 preview_wanted(params
, buffer
)) {
934 renderer
.setAbsFile(includedFilename(buffer
, params
));
935 docstring
const snippet
= latexString(inset
);
936 renderer
.addPreview(snippet
, buffer
);
943 void InsetInclude::addPreview(graphics::PreviewLoader
& ploader
) const
945 Buffer
const & buffer
= ploader
.buffer();
946 if (!preview_wanted(params(), buffer
))
948 preview_
->setAbsFile(includedFilename(buffer
, params()));
949 docstring
const snippet
= latexString(*this);
950 preview_
->addPreview(snippet
, ploader
);
954 void InsetInclude::addToToc(DocIterator
const & cpit
)
956 TocBackend
& backend
= buffer().tocBackend();
958 if (isListings(params())) {
960 label_
->addToToc(cpit
);
962 InsetListingsParams
p(to_utf8(params()["lstparams"]));
963 string caption
= p
.getParamValue("caption");
966 Toc
& toc
= backend
.toc("listing");
967 docstring str
= convert
<docstring
>(toc
.size() + 1)
968 + ". " + from_utf8(caption
);
969 DocIterator pit
= cpit
;
970 toc
.push_back(TocItem(pit
, 0, str
));
973 Buffer
const * const childbuffer
= getChildBuffer();
977 Toc
& toc
= backend
.toc("child");
978 docstring str
= childbuffer
->fileName().displayName();
979 toc
.push_back(TocItem(cpit
, 0, str
));
981 TocList
& toclist
= backend
.tocs();
982 childbuffer
->tocBackend().update();
983 TocList
const & childtoclist
= childbuffer
->tocBackend().tocs();
984 TocList::const_iterator it
= childtoclist
.begin();
985 TocList::const_iterator
const end
= childtoclist
.end();
986 for(; it
!= end
; ++it
)
987 toclist
[it
->first
].insert(toclist
[it
->first
].end(),
988 it
->second
.begin(), it
->second
.end());
992 void InsetInclude::updateCommand()
997 docstring old_label
= label_
->getParam("name");
998 label_
->updateCommand(old_label
, false);
999 // the label might have been adapted (duplicate)
1000 docstring new_label
= label_
->getParam("name");
1001 if (old_label
== new_label
)
1004 // update listings parameters...
1005 InsetCommandParams
p(INCLUDE_CODE
);
1007 InsetListingsParams
par(to_utf8(params()["lstparams"]));
1008 par
.addParam("label", "{" + to_utf8(new_label
) + "}", true);
1009 p
["lstparams"] = from_utf8(par
.params());
1013 void InsetInclude::updateLabels(ParIterator
const & it
)
1015 Buffer
const * const childbuffer
= getChildBuffer();
1017 childbuffer
->updateLabels(Buffer::UpdateChildOnly
);
1020 if (!isListings(params()))
1024 label_
->updateLabels(it
);
1026 InsetListingsParams
const par(to_utf8(params()["lstparams"]));
1027 if (par
.getParamValue("caption").empty()) {
1028 listings_label_
= buffer().B_("Program Listing");
1031 Buffer
const & master
= *buffer().masterBuffer();
1032 Counters
& counters
= master
.params().documentClass().counters();
1033 docstring
const cnt
= from_ascii("listing");
1034 listings_label_
= master
.B_("Program Listing");
1035 if (counters
.hasCounter(cnt
)) {
1037 listings_label_
+= " " + convert
<docstring
>(counters
.value(cnt
));