X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetInclude.cpp;h=6d512b4b7d9aefe5180006806f7aae2e3c087a29;hb=62ca7f3ae55ad2e0c395cb554d71afab87de1ee3;hp=c09d272f4745dddb33da6d9842f1623548279b78;hpb=90feb482db6e36f2071a0775f085300b9468f165;p=lyx.git diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp index c09d272f47..6d512b4b7d 100644 --- a/src/insets/InsetInclude.cpp +++ b/src/insets/InsetInclude.cpp @@ -29,10 +29,10 @@ #include "LayoutFile.h" #include "LayoutModuleList.h" #include "LyX.h" -#include "LyXFunc.h" #include "LyXRC.h" #include "Lexer.h" #include "MetricsInfo.h" +#include "output_xhtml.h" #include "OutputParams.h" #include "TextClass.h" #include "TocBackend.h" @@ -147,28 +147,28 @@ FileName const includedFilename(Buffer const & buffer, } -InsetLabel * createLabel(docstring const & label_str) +InsetLabel * createLabel(Buffer * buf, docstring const & label_str) { if (label_str.empty()) return 0; InsetCommandParams icp(LABEL_CODE); icp["name"] = label_str; - return new InsetLabel(icp); + return new InsetLabel(buf, icp); } } // namespace anon -InsetInclude::InsetInclude(InsetCommandParams const & p) - : InsetCommand(p, "include"), include_label(uniqueID()), +InsetInclude::InsetInclude(Buffer * buf, InsetCommandParams const & p) + : InsetCommand(buf, p, "include"), include_label(uniqueID()), preview_(new RenderMonitoredPreview(this)), failedtoload_(false), - set_label_(false), label_(0) + set_label_(false), label_(0), child_buffer_(0) { preview_->fileChanged(boost::bind(&InsetInclude::fileChanged, this)); if (isListings(params())) { InsetListingsParams listing_params(to_utf8(p["lstparams"])); - label_ = createLabel(from_utf8(listing_params.getParamValue("label"))); + label_ = createLabel(buffer_, from_utf8(listing_params.getParamValue("label"))); } } @@ -176,7 +176,7 @@ InsetInclude::InsetInclude(InsetCommandParams const & p) InsetInclude::InsetInclude(InsetInclude const & other) : InsetCommand(other), include_label(other.include_label), preview_(new RenderMonitoredPreview(this)), failedtoload_(false), - set_label_(false), label_(0) + set_label_(false), label_(0), child_buffer_(0) { preview_->fileChanged(boost::bind(&InsetInclude::fileChanged, this)); @@ -199,6 +199,12 @@ void InsetInclude::setBuffer(Buffer & buffer) } +void InsetInclude::setChildBuffer(Buffer * buffer) +{ + child_buffer_ = buffer; +} + + ParamInfo const & InsetInclude::findInfo(string const & /* cmdName */) { // FIXME @@ -221,8 +227,7 @@ bool InsetInclude::isCompatibleCommand(string const & s) void InsetInclude::doDispatch(Cursor & cur, FuncRequest & cmd) { - LASSERT(cur.buffer() == &buffer(), return); - switch (cmd.action) { + switch (cmd.action()) { case LFUN_INSET_EDIT: { editIncluded(to_utf8(params()["filename"])); @@ -230,6 +235,9 @@ void InsetInclude::doDispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_INSET_MODIFY: { + // It should be OK just to invalidate the cache is setParams() + // If not.... + // child_buffer_ = 0; InsetCommandParams p(INCLUDE_CODE); if (cmd.getArg(0) == "changetype") { InsetCommand::doDispatch(cur, cmd); @@ -250,7 +258,7 @@ void InsetInclude::doDispatch(Cursor & cur, FuncRequest & cmd) if (label_) old_label = label_->getParam("name"); else { - label_ = createLabel(new_label); + label_ = createLabel(buffer_, new_label); label_->setBuffer(buffer()); } @@ -296,13 +304,19 @@ void InsetInclude::editIncluded(string const & file) bool InsetInclude::getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus & flag) const { - switch (cmd.action) { + switch (cmd.action()) { case LFUN_INSET_EDIT: - case LFUN_INSET_MODIFY: flag.setEnabled(true); return true; + case LFUN_INSET_MODIFY: + if (cmd.getArg(0) == "changetype") + return InsetCommand::getStatus(cur, cmd, flag); + else + flag.setEnabled(true); + return true; + default: return InsetCommand::getStatus(cur, cmd, flag); } @@ -311,6 +325,9 @@ bool InsetInclude::getStatus(Cursor & cur, FuncRequest const & cmd, void InsetInclude::setParams(InsetCommandParams const & p) { + // invalidate the cache + child_buffer_ = 0; + InsetCommand::setParams(p); set_label_ = false; @@ -324,6 +341,18 @@ void InsetInclude::setParams(InsetCommandParams const & p) } +bool InsetInclude::isChildIncluded() const +{ + std::list includeonlys = + buffer().params().getIncludedChildren(); + if (includeonlys.empty()) + return true; + return (std::find(includeonlys.begin(), + includeonlys.end(), + to_utf8(params()["filename"])) != includeonlys.end()); +} + + docstring InsetInclude::screenLabel() const { docstring temp; @@ -339,7 +368,10 @@ docstring InsetInclude::screenLabel() const temp = buffer().B_("Verbatim Input*"); break; case INCLUDE: - temp = buffer().B_("Include"); + if (isChildIncluded()) + temp = buffer().B_("Include"); + else + temp += buffer().B_("Include (excluded)"); break; case LISTINGS: temp = listings_label_; @@ -359,37 +391,39 @@ docstring InsetInclude::screenLabel() const } -Buffer * InsetInclude::getChildBuffer(Buffer const & buffer) const +Buffer * InsetInclude::getChildBuffer() const { - InsetCommandParams const & p = params(); - if (isVerbatim(p) || isListings(p)) - return 0; - - string const included_file = includedFilename(buffer, p).absFilename(); - if (!isLyXFilename(included_file)) - return 0; - - Buffer * childBuffer = loadIfNeeded(buffer); + Buffer * childBuffer = loadIfNeeded(); // FIXME: recursive includes - return (childBuffer == &buffer) ? 0 : childBuffer; + return (childBuffer == &buffer()) ? 0 : childBuffer; } -Buffer * InsetInclude::loadIfNeeded(Buffer const & parent) const +Buffer * InsetInclude::loadIfNeeded() const { - InsetCommandParams const & p = params(); - if (failedtoload_) - return 0; - - if (isVerbatim(p) || isListings(p)) + // This is for background export and preview. We don't even want to + // try to load the cloned child document again. + if (buffer().isClone()) + return child_buffer_; + + // Don't try to load it again if we failed before. + if (failedtoload_ || isVerbatim(params()) || isListings(params())) return 0; - string const parent_filename = parent.absFileName(); - FileName const included_file = makeAbsPath(to_utf8(p["filename"]), - onlyPath(parent_filename)); + FileName const included_file = includedFilename(buffer(), params()); + // Use cached Buffer if possible. + if (child_buffer_ != 0) { + if (theBufferList().isLoaded(child_buffer_) + // additional sanity check: make sure the Buffer really is + // associated with the file we want. + && child_buffer_ == theBufferList().getBuffer(included_file)) + return child_buffer_; + // Buffer vanished, so invalidate cache and try to reload. + child_buffer_ = 0; + } - if (!isLyXFilename(included_file.absFilename())) + if (!isLyXFilename(included_file.absFileName())) return 0; Buffer * child = theBufferList().getBuffer(included_file); @@ -398,7 +432,7 @@ Buffer * InsetInclude::loadIfNeeded(Buffer const & parent) const if (!included_file.exists()) return 0; - child = theBufferList().newBuffer(included_file.absFilename()); + child = theBufferList().newBuffer(included_file.absFileName()); if (!child) // Buffer creation is not possible. return 0; @@ -414,7 +448,9 @@ Buffer * InsetInclude::loadIfNeeded(Buffer const & parent) const // FIXME: Do something. } } - child->setParent(&parent); + child->setParent(&buffer()); + // Cache the child buffer. + child_buffer_ = child; return child; } @@ -434,7 +470,7 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const // This isn't sufficient, as the inclusion could be downstream. // But it'll have to do for now. if (isInputOrInclude(params()) && - buffer().absFileName() == included_file.absFilename()) + buffer().absFileName() == included_file.absFileName()) { Alert::error(_("Recursive input"), bformat(_("Attempted to include file %1$s in itself! " @@ -446,9 +482,9 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const // if incfile is relative, make it relative to the master // buffer directory. - if (!FileName(incfile).isAbsolute()) { + if (!FileName::isAbsolute(incfile)) { // FIXME UNICODE - incfile = to_utf8(makeRelPath(from_utf8(included_file.absFilename()), + incfile = to_utf8(makeRelPath(from_utf8(included_file.absFileName()), from_utf8(masterBuffer->filePath()))); } @@ -461,7 +497,7 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const mangled = DocFileName(included_file).mangledFilename(); } else { exportfile = changeExtension(incfile, ".tex"); - mangled = DocFileName(changeExtension(included_file.absFilename(), ".tex")). + mangled = DocFileName(changeExtension(included_file.absFileName(), ".tex")). mangledFilename(); } @@ -483,10 +519,10 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const //Don't try to load or copy the file if we're //in a comment or doing a dryrun } else if (isInputOrInclude(params()) && - isLyXFilename(included_file.absFilename())) { + isLyXFilename(included_file.absFileName())) { //if it's a LyX file and we're inputting or including, //try to load it so we can write the associated latex - if (!loadIfNeeded(buffer())) + if (!loadIfNeeded()) return false; Buffer * tmp = theBufferList().getBuffer(included_file); @@ -499,12 +535,12 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const included_file.displayName(), from_utf8(tmp->params().documentClass().name()), from_utf8(masterBuffer->params().documentClass().name())); - Alert::warning(_("Different textclasses"), text); + Alert::warning(_("Different textclasses"), text, true); } // Make sure modules used in child are all included in master - //FIXME It might be worth loading the children's modules into the master - //over in BufferParams rather than doing this check. + // FIXME It might be worth loading the children's modules into the master + // over in BufferParams rather than doing this check. LayoutModuleList const masterModules = masterBuffer->params().getModules(); LayoutModuleList const childModules = tmp->params().getModules(); LayoutModuleList::const_iterator it = childModules.begin(); @@ -524,18 +560,22 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const tmp->markDepClean(masterBuffer->temppath()); -// FIXME: handle non existing files -// FIXME: Second argument is irrelevant! -// since only_body is true, makeLaTeXFile will not look at second -// argument. Should we set it to string(), or should makeLaTeXFile -// make use of it somehow? (JMarc 20031002) + // FIXME: handle non existing files + // FIXME: Second argument is irrelevant! + // since only_body is true, makeLaTeXFile will not look at second + // argument. Should we set it to string(), or should makeLaTeXFile + // make use of it somehow? (JMarc 20031002) // The included file might be written in a different encoding + // and language. Encoding const * const oldEnc = runparams.encoding; + Language const * const oldLang = runparams.master_language; runparams.encoding = &tmp->params().encoding(); + runparams.master_language = buffer().params().language; tmp->makeLaTeXFile(writefile, - masterFileName(buffer()).onlyPath().absFilename(), + masterFileName(buffer()).onlyPath().absFileName(), runparams, false); runparams.encoding = oldEnc; + runparams.master_language = oldLang; } else { // In this case, it's not a LyX file, so we copy the file // to the temp dir, so that .aux files etc. are not created @@ -550,7 +590,7 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const LYXERR(Debug::LATEX, to_utf8(bformat(_("Could not copy the file\n%1$s\n" "into the temporary directory."), - from_utf8(included_file.absFilename())))); + from_utf8(included_file.absFileName())))); return 0; } } @@ -558,17 +598,21 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const string const tex_format = (runparams.flavor == OutputParams::LATEX) ? "latex" : "pdflatex"; - if (isVerbatim(params())) { + switch (type(params())) { + case VERB: + case VERBAST: { incfile = latex_path(incfile); // FIXME UNICODE os << '\\' << from_ascii(params().getCmdName()) << '{' << from_utf8(incfile) << '}'; - } else if (type(params()) == INPUT) { + break; + } + case INPUT: { runparams.exportdata->addExternalFile(tex_format, writefile, exportfile); // \input wants file with extension (default is .tex) - if (!isLyXFilename(included_file.absFilename())) { + if (!isLyXFilename(included_file.absFileName())) { incfile = latex_path(incfile); // FIXME UNICODE os << '\\' << from_ascii(params().getCmdName()) @@ -580,7 +624,9 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const os << '\\' << from_ascii(params().getCmdName()) << '{' << from_utf8(incfile) << '}'; } - } else if (type(params()) == LISTINGS) { + break; + } + case LISTINGS: { os << '\\' << from_ascii(params().getCmdName()); string const opt = to_utf8(params()["lstparams"]); // opt is set in QInclude dialog and should have passed validation. @@ -588,7 +634,9 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const if (!params.params().empty()) os << "[" << from_utf8(params.params()) << "]"; os << '{' << from_utf8(incfile) << '}'; - } else { + break; + } + case INCLUDE: { runparams.exportdata->addExternalFile(tex_format, writefile, exportfile); @@ -599,12 +647,65 @@ int InsetInclude::latex(odocstream & os, OutputParams const & runparams) const // FIXME UNICODE os << '\\' << from_ascii(params().getCmdName()) << '{' << from_utf8(incfile) << '}'; + break; + } + case NONE: + break; } return 0; } +docstring InsetInclude::xhtml(XHTMLStream & xs, OutputParams const &rp) const +{ + if (rp.inComment) + return docstring(); + + // For verbatim and listings, we just include the contents of the file as-is. + // In the case of listings, we wrap it in
.
+	bool const listing = isListings(params());
+	if (listing || isVerbatim(params())) {
+		if (listing)
+			xs << html::StartTag("pre");
+		// FIXME: We don't know the encoding of the file, default to UTF-8.
+		xs << includedFilename(buffer(), params()).fileContents("UTF-8");
+		if (listing)
+			xs << html::EndTag("pre");
+		return docstring();
+	}
+
+	// We don't (yet) know how to Input or Include non-LyX files.
+	// (If we wanted to get really arcane, we could run some tex2html
+	// converter on the included file. But that's just masochistic.)
+	FileName const included_file = includedFilename(buffer(), params());
+	if (!isLyXFilename(included_file.absFileName())) {
+		frontend::Alert::warning(_("Unsupported Inclusion"),
+					 bformat(_("LyX does not know how to include non-LyX files when "
+					           "generating HTML output. Offending file:\n%1$s"),
+					            params()["filename"]));
+		return docstring();
+	}
+
+	// In the other cases, we will generate the HTML and include it.
+
+	// Check we're not trying to include ourselves.
+	// FIXME RECURSIVE INCLUDE
+	if (buffer().absFileName() == included_file.absFileName()) {
+		Alert::error(_("Recursive input"),
+			       bformat(_("Attempted to include file %1$s in itself! "
+			       "Ignoring inclusion."), params()["filename"]));
+		return docstring();
+	}
+
+	Buffer const * const ibuf = loadIfNeeded();
+	if (!ibuf)
+		return docstring();
+	ibuf->writeLyXHTMLSource(xs.os(), rp, true);
+	return docstring();
+}
+
+
 int InsetInclude::plaintext(odocstream & os, OutputParams const &) const
 {
 	if (isVerbatim(params()) || isListings(params())) {
@@ -629,7 +730,7 @@ int InsetInclude::docbook(odocstream & os, OutputParams const & runparams) const
 	if (incfile.empty())
 		return 0;
 
-	string const included_file = includedFilename(buffer(), params()).absFilename();
+	string const included_file = includedFilename(buffer(), params()).absFileName();
 
 	// Check we're not trying to include ourselves.
 	// FIXME RECURSIVE INCLUDE
@@ -646,7 +747,7 @@ int InsetInclude::docbook(odocstream & os, OutputParams const & runparams) const
 	string const exportfile = changeExtension(incfile, ".sgml");
 	DocFileName writefile(changeExtension(included_file, ".sgml"));
 
-	if (loadIfNeeded(buffer())) {
+	if (loadIfNeeded()) {
 		Buffer * tmp = theBufferList().getBuffer(FileName(included_file));
 
 		string const mangled = writefile.mangledFilename();
@@ -686,7 +787,7 @@ void InsetInclude::validate(LaTeXFeatures & features) const
 	LASSERT(&buffer() == &features.buffer(), /**/);
 
 	string const included_file =
-		includedFilename(buffer(), params()).absFilename();
+		includedFilename(buffer(), params()).absFileName();
 
 	if (isLyXFilename(included_file))
 		writefile = changeExtension(included_file, ".sgml");
@@ -696,7 +797,7 @@ void InsetInclude::validate(LaTeXFeatures & features) const
 	if (!features.runparams().nice && !isVerbatim(params()) && !isListings(params())) {
 		incfile = DocFileName(writefile).mangledFilename();
 		writefile = makeAbsPath(incfile,
-					buffer().masterBuffer()->temppath()).absFilename();
+					buffer().masterBuffer()->temppath()).absFileName();
 	}
 
 	features.includeFile(include_label, writefile);
@@ -709,7 +810,7 @@ void InsetInclude::validate(LaTeXFeatures & features) const
 	// Here we must do the fun stuff...
 	// Load the file in the include if it needs
 	// to be loaded:
-	if (loadIfNeeded(buffer())) {
+	if (loadIfNeeded()) {
 		// a file got loaded
 		Buffer * const tmp = theBufferList().getBuffer(FileName(included_file));
 		// make sure the buffer isn't us
@@ -731,8 +832,8 @@ void InsetInclude::validate(LaTeXFeatures & features) const
 void InsetInclude::fillWithBibKeys(BiblioInfo & keys,
 	InsetIterator const & /*di*/) const
 {
-	if (loadIfNeeded(buffer())) {
-		string const included_file = includedFilename(buffer(), params()).absFilename();
+	if (loadIfNeeded()) {
+		string const included_file = includedFilename(buffer(), params()).absFileName();
 		Buffer * tmp = theBufferList().getBuffer(FileName(included_file));
 		BiblioInfo const & newkeys = tmp->localBibInfo();
 		keys.mergeBiblioInfo(newkeys);
@@ -742,25 +843,19 @@ void InsetInclude::fillWithBibKeys(BiblioInfo & keys,
 
 void InsetInclude::updateBibfilesCache()
 {
-	Buffer * const tmp = getChildBuffer(buffer());
-	if (tmp) {
-		tmp->setParent(0);
-		tmp->updateBibfilesCache();
-		tmp->setParent(&buffer());
-	}
+	Buffer const * const child = getChildBuffer();
+	if (child)
+		child->updateBibfilesCache(Buffer::UpdateChildOnly);
 }
 
 
 support::FileNameList const &
-	InsetInclude::getBibfilesCache(Buffer const & buffer) const
+	InsetInclude::getBibfilesCache() const
 {
-	Buffer * const tmp = getChildBuffer(buffer);
-	if (tmp) {
-		tmp->setParent(0);
-		support::FileNameList const & cache = tmp->getBibfilesCache();
-		tmp->setParent(&buffer);
-		return cache;
-	}
+	Buffer const * const child = getChildBuffer();
+	if (child)
+		return child->getBibfilesCache(Buffer::UpdateChildOnly);
+
 	static support::FileNameList const empty;
 	return empty;
 }
@@ -878,7 +973,8 @@ void add_preview(RenderMonitoredPreview & renderer, InsetInclude const & inset,
 } // namespace anon
 
 
-void InsetInclude::addPreview(graphics::PreviewLoader & ploader) const
+void InsetInclude::addPreview(DocIterator const & /*inset_pos*/,
+	graphics::PreviewLoader & ploader) const
 {
 	Buffer const & buffer = ploader.buffer();
 	if (!preview_wanted(params(), buffer))
@@ -908,7 +1004,7 @@ void InsetInclude::addToToc(DocIterator const & cpit)
 		toc.push_back(TocItem(pit, 0, str));
 		return;
 	}
-	Buffer const * const childbuffer = getChildBuffer(buffer());
+	Buffer const * const childbuffer = getChildBuffer();
 	if (!childbuffer)
 		return;
 
@@ -948,18 +1044,18 @@ void InsetInclude::updateCommand()
 	setParams(p);	
 }
 
-void InsetInclude::updateLabels(ParIterator const & it)
+void InsetInclude::updateBuffer(ParIterator const & it, UpdateType utype)
 {
-	Buffer const * const childbuffer = getChildBuffer(buffer());
+	Buffer const * const childbuffer = getChildBuffer();
 	if (childbuffer) {
-		childbuffer->updateLabels(true);
+		childbuffer->updateBuffer(Buffer::UpdateChildOnly, utype);
 		return;
 	}
 	if (!isListings(params()))
 		return;
 
 	if (label_)
-		label_->updateLabels(it);
+		label_->updateBuffer(it, utype);
 
 	InsetListingsParams const par(to_utf8(params()["lstparams"]));
 	if (par.getParamValue("caption").empty()) {
@@ -971,7 +1067,7 @@ void InsetInclude::updateLabels(ParIterator const & it)
 	docstring const cnt = from_ascii("listing");
 	listings_label_ = master.B_("Program Listing");
 	if (counters.hasCounter(cnt)) {
-		counters.step(cnt);
+		counters.step(cnt, utype);
 		listings_label_ += " " + convert(counters.value(cnt));
 	}
 }