X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetInclude.cpp;h=89f304db7ea84cb79243da885e46448ecbaee30c;hb=2c357c1d23b7b83839a9beb8225d4f1ae4f793b4;hp=6ab2324a2b3151ed2ef87858a6bb9ec52638be38;hpb=601a8e0192b60274ab316c0bfa31811d236c972e;p=lyx.git diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp index 6ab2324a2b..89f304db7e 100644 --- a/src/insets/InsetInclude.cpp +++ b/src/insets/InsetInclude.cpp @@ -4,6 +4,7 @@ * Licence details can be found in the file COPYING. * * \author Lars Gullik Bjønnes + * \author Richard Heck (conversion to InsetCommand) * * Full author contact details are available in file CREDITS. */ @@ -18,18 +19,17 @@ #include "BufferParams.h" #include "BufferView.h" #include "Cursor.h" -#include "debug.h" #include "DispatchResult.h" #include "Exporter.h" #include "FuncRequest.h" #include "FuncStatus.h" -#include "gettext.h" #include "LaTeXFeatures.h" #include "LyX.h" #include "LyXRC.h" #include "Lexer.h" #include "MetricsInfo.h" #include "OutputParams.h" +#include "TextClass.h" #include "TocBackend.h" #include "frontends/alert.h" @@ -41,54 +41,24 @@ #include "insets/RenderPreview.h" #include "insets/InsetListingsParams.h" +#include "support/debug.h" +#include "support/docstream.h" +#include "support/ExceptionMessage.h" +#include "support/FileNameList.h" #include "support/filetools.h" +#include "support/gettext.h" #include "support/lstrings.h" // contains #include "support/lyxalgo.h" -#include "support/lyxlib.h" #include "support/convert.h" #include -#include +using namespace std; +using namespace lyx::support; namespace lyx { - -// Implementation is in LyX.cpp -extern void dispatch(FuncRequest const & action); - -using support::addName; -using support::absolutePath; -using support::bformat; -using support::changeExtension; -using support::contains; -using support::copy; -using support::DocFileName; -using support::FileName; -using support::getFileContents; -using support::getVectorFromString; -using support::isFileReadable; -using support::isLyXFilename; -using support::isValidLaTeXFilename; -using support::latex_path; -using support::makeAbsPath; -using support::makeDisplayPath; -using support::makeRelPath; -using support::onlyFilename; -using support::onlyPath; -using support::prefixIs; -using support::subst; -using support::sum; - -using std::endl; -using std::string; -using std::auto_ptr; -using std::istringstream; -using std::ostream; -using std::ostringstream; -using std::vector; namespace Alert = frontend::Alert; -namespace fs = boost::filesystem; namespace { @@ -100,233 +70,183 @@ docstring const uniqueID() } -bool isListings(InsetCommandParams const & params) -{ - return params.getCmdName() == "lstinputlisting"; -} - -} // namespace anon +/// the type of inclusion +enum Types { + INCLUDE, VERB, INPUT, VERBAST, LISTINGS, NONE +}; -InsetInclude::InsetInclude(InsetCommandParams const & p) - : params_(p), include_label(uniqueID()), - preview_(new RenderMonitoredPreview(this)), - set_label_(false) +Types type(string const & s) { - preview_->fileChanged(boost::bind(&InsetInclude::fileChanged, this)); + if (s == "input") + return INPUT; + if (s == "verbatiminput") + return VERB; + if (s == "verbatiminput*") + return VERBAST; + if (s == "lstinputlisting") + return LISTINGS; + if (s == "include") + return INCLUDE; + return NONE; } -InsetInclude::InsetInclude(InsetInclude const & other) - : Inset(other), - params_(other.params_), - include_label(other.include_label), - preview_(new RenderMonitoredPreview(this)), - set_label_(false) +Types type(InsetCommandParams const & params) { - preview_->fileChanged(boost::bind(&InsetInclude::fileChanged, this)); + return type(params.getCmdName()); } -InsetInclude::~InsetInclude() +bool isListings(InsetCommandParams const & params) { - InsetIncludeMailer(*this).hideDialog(); + return type(params) == LISTINGS; } -void InsetInclude::doDispatch(Cursor & cur, FuncRequest & cmd) +bool isVerbatim(InsetCommandParams const & params) { - switch (cmd.action) { - - case LFUN_INSET_MODIFY: { - InsetCommandParams p("include"); - InsetIncludeMailer::string2params(to_utf8(cmd.argument()), p); - if (!p.getCmdName().empty()) { - if (isListings(p)){ - InsetListingsParams par_old(params().getOptions()); - InsetListingsParams par_new(p.getOptions()); - if (par_old.getParamValue("label") != - par_new.getParamValue("label") - && !par_new.getParamValue("label").empty()) - cur.bv().buffer()->changeRefsIfUnique( - from_utf8(par_old.getParamValue("label")), - from_utf8(par_new.getParamValue("label")), - Inset::REF_CODE); - } - set(p, cur.buffer()); - cur.buffer().updateBibfilesCache(); - } else - cur.noUpdate(); - break; - } - - case LFUN_INSET_DIALOG_UPDATE: - InsetIncludeMailer(*this).updateDialog(&cur.bv()); - break; - - case LFUN_MOUSE_RELEASE: - if (!cur.selection()) - InsetIncludeMailer(*this).showDialog(&cur.bv()); - break; - - default: - Inset::doDispatch(cur, cmd); - break; - } + Types const t = type(params); + return t == VERB || t == VERBAST; } -bool InsetInclude::getStatus(Cursor & cur, FuncRequest const & cmd, - FuncStatus & flag) const +bool isInputOrInclude(InsetCommandParams const & params) { - switch (cmd.action) { - - case LFUN_INSET_MODIFY: - case LFUN_INSET_DIALOG_UPDATE: - flag.enabled(true); - return true; - - default: - return Inset::getStatus(cur, cmd, flag); - } + Types const t = type(params); + return t == INPUT || t == INCLUDE; } -InsetCommandParams const & InsetInclude::params() const +FileName const masterFileName(Buffer const & buffer) { - return params_; + return buffer.masterBuffer()->fileName(); } -namespace { - -/// the type of inclusion -enum Types { - INCLUDE = 0, - VERB = 1, - INPUT = 2, - VERBAST = 3, - LISTINGS = 4, -}; +void add_preview(RenderMonitoredPreview &, InsetInclude const &, Buffer const &); -Types type(InsetCommandParams const & params) +string const parentFilename(Buffer const & buffer) { - string const command_name = params.getCmdName(); - - if (command_name == "input") - return INPUT; - if (command_name == "verbatiminput") - return VERB; - if (command_name == "verbatiminput*") - return VERBAST; - if (command_name == "lstinputlisting") - return LISTINGS; - return INCLUDE; + return buffer.absFileName(); } -bool isVerbatim(InsetCommandParams const & params) +EmbeddedFile const includedFilename(Buffer const & buffer, + InsetCommandParams const & params) { - string const command_name = params.getCmdName(); - return command_name == "verbatiminput" || - command_name == "verbatiminput*"; + // it is not a good idea to create this EmbeddedFile object + // each time, but there seems to be no easy way around. + EmbeddedFile file(to_utf8(params["filename"]), + onlyPath(parentFilename(buffer))); + file.setEmbed(!params["embed"].empty()); + file.enable(buffer.embedded(), &buffer); + return file; } +} // namespace anon -bool isInputOrInclude(InsetCommandParams const & params) + +InsetInclude::InsetInclude(InsetCommandParams const & p) + : InsetCommand(p, "include"), include_label(uniqueID()), + preview_(new RenderMonitoredPreview(this)), set_label_(false) { - Types const t = type(params); - return (t == INPUT) || (t == INCLUDE); + preview_->fileChanged(boost::bind(&InsetInclude::fileChanged, this)); } -string const masterFilename(Buffer const & buffer) +InsetInclude::InsetInclude(InsetInclude const & other) + : InsetCommand(other), include_label(other.include_label), + preview_(new RenderMonitoredPreview(this)), set_label_(false) { - return buffer.getMasterBuffer()->fileName(); + preview_->fileChanged(boost::bind(&InsetInclude::fileChanged, this)); } -string const parentFilename(Buffer const & buffer) +CommandInfo const * InsetInclude::findInfo(string const & /* cmdName */) { - return buffer.fileName(); + // FIXME + // This is only correct for the case of listings, but it'll do for now. + // In the other cases, this second parameter should just be empty. + static const char * const paramnames[] = {"filename", "embed", "lstparams", ""}; + static const bool isoptional[] = {false, false, true}; + static const CommandInfo info = {3, paramnames, isoptional}; + return &info; } -FileName const includedFilename(Buffer const & buffer, - InsetCommandParams const & params) +bool InsetInclude::isCompatibleCommand(string const & s) { - return makeAbsPath(to_utf8(params["filename"]), - onlyPath(parentFilename(buffer))); + return type(s) != NONE; } -void add_preview(RenderMonitoredPreview &, InsetInclude const &, Buffer const &); +void InsetInclude::doDispatch(Cursor & cur, FuncRequest & cmd) +{ + switch (cmd.action) { -} // namespace anon + case LFUN_INSET_MODIFY: { + InsetCommandParams p(INCLUDE_CODE); + InsetCommandMailer::string2params("include", to_utf8(cmd.argument()), p); + if (!p.getCmdName().empty()) { + if (isListings(p)){ + InsetListingsParams par_old(to_utf8(params()["lstparams"])); + InsetListingsParams par_new(to_utf8(p["lstparams"])); + if (par_old.getParamValue("label") != + par_new.getParamValue("label") + && !par_new.getParamValue("label").empty()) + cur.bv().buffer().changeRefsIfUnique( + from_utf8(par_old.getParamValue("label")), + from_utf8(par_new.getParamValue("label")), + REF_CODE); + } + try { + // the embed parameter passed back from the dialog + // is "true" or "false", we need to change it. + if (p["embed"] == _("false")) + p["embed"].clear(); + else + p["embed"] = from_utf8(EmbeddedFile(to_utf8(p["filename"]), + onlyPath(parentFilename(cur.buffer()))).inzipName()); + // test parameter + includedFilename(cur.buffer(), p); + } catch (ExceptionMessage const & message) { + Alert::error(message.title_, message.details_); + // do not set parameter if an error happens + break; + } + set(p, cur.buffer()); + cur.buffer().updateBibfilesCache(); + } else + cur.noUpdate(); + break; + } + + //pass everything else up the chain + default: + InsetCommand::doDispatch(cur, cmd); + break; + } +} void InsetInclude::set(InsetCommandParams const & p, Buffer const & buffer) { - params_ = p; + setParams(p); set_label_ = false; if (preview_->monitoring()) preview_->stopMonitoring(); - if (type(params_) == INPUT) + if (type(params()) == INPUT) add_preview(*preview_, *this, buffer); } -auto_ptr InsetInclude::doClone() const -{ - return auto_ptr(new InsetInclude(*this)); -} - - -void InsetInclude::write(Buffer const &, ostream & os) const -{ - write(os); -} - - -void InsetInclude::write(ostream & os) const -{ - os << "Include " << to_utf8(params_.getCommand()) << '\n' - << "preview " << convert(params_.preview()) << '\n'; -} - - -void InsetInclude::read(Buffer const &, Lexer & lex) -{ - read(lex); -} - - -void InsetInclude::read(Lexer & lex) +Inset * InsetInclude::clone() const { - if (lex.isOK()) { - lex.eatLine(); - string const command = lex.getString(); - params_.scanCommand(command); - } - string token; - while (lex.isOK()) { - lex.next(); - token = lex.getString(); - if (token == "\\end_inset") - break; - if (token == "preview") { - lex.next(); - params_.preview(lex.getBool()); - } else - lex.printError("Unknown parameter name `$$Token' for command " + params_.getCmdName()); - } - if (token != "\\end_inset") { - lex.printError("Missing \\end_inset at this point. " - "Read: `$$Token'"); - } + return new InsetInclude(*this); } @@ -334,7 +254,7 @@ docstring const InsetInclude::getScreenLabel(Buffer const & buf) const { docstring temp; - switch (type(params_)) { + switch (type(params())) { case INPUT: temp = buf.B_("Input"); break; @@ -347,25 +267,27 @@ docstring const InsetInclude::getScreenLabel(Buffer const & buf) const case INCLUDE: temp = buf.B_("Include"); break; - case LISTINGS: { + case LISTINGS: temp = listings_label_; - } + break; + case NONE: + BOOST_ASSERT(false); } temp += ": "; - if (params_["filename"].empty()) + if (params()["filename"].empty()) temp += "???"; else - temp += from_utf8(onlyFilename(to_utf8(params_["filename"]))); + temp += from_utf8(onlyFilename(to_utf8(params()["filename"]))); + if (!params()["embed"].empty()) + temp += _(" (embedded)"); return temp; } -namespace { - -/// return the child buffer if the file is a LyX doc and is loaded + /// return the child buffer if the file is a LyX doc and is loaded Buffer * getChildBuffer(Buffer const & buffer, InsetCommandParams const & params) { if (isVerbatim(params) || isListings(params)) @@ -384,62 +306,89 @@ Buffer * getChildBuffer(Buffer const & buffer, InsetCommandParams const & params return childBuffer; } - /// return true if the file is or got loaded. -bool loadIfNeeded(Buffer const & buffer, InsetCommandParams const & params) +Buffer * loadIfNeeded(Buffer const & parent, InsetCommandParams const & params) { if (isVerbatim(params) || isListings(params)) - return false; + return 0; + + string const parent_filename = parent.absFileName(); + FileName const included_file = makeAbsPath(to_utf8(params["filename"]), + onlyPath(parent_filename)); - FileName const included_file = includedFilename(buffer, params); if (!isLyXFilename(included_file.absFilename())) - return false; + return 0; - Buffer * buf = theBufferList().getBuffer(included_file.absFilename()); - if (!buf) { + Buffer * child = theBufferList().getBuffer(included_file.absFilename()); + if (!child) { // the readonly flag can/will be wrong, not anymore I think. - if (!fs::exists(included_file.toFilesystemEncoding())) - return false; - if (use_gui) { - lyx::dispatch(FuncRequest(LFUN_BUFFER_CHILD_OPEN, - included_file.absFilename() + "|true")); - buf = theBufferList().getBuffer(included_file.absFilename()); - } - else { - buf = theBufferList().newBuffer(included_file.absFilename()); - if (!loadLyXFile(buf, included_file)) { - //close the buffer we just opened - theBufferList().close(buf, false); - return false; - } + if (!included_file.exists()) + return 0; + + child = theBufferList().newBuffer(included_file.absFilename()); + if (!child) + // Buffer creation is not possible. + return 0; + + if (!child->loadLyXFile(included_file)) { + //close the buffer we just opened + theBufferList().release(child); + return 0; } - return buf; } - buf->setParentName(parentFilename(buffer)); - return true; + child->setParent(&parent); + return child; } -} // namespace anon +void resetParentBuffer(Buffer const * parent, InsetCommandParams const & params, + bool close_it) +{ + if (isVerbatim(params) || isListings(params)) + return; + + string const parent_filename = parent->absFileName(); + FileName const included_file = makeAbsPath(to_utf8(params["filename"]), + onlyPath(parent_filename)); + + if (!isLyXFilename(included_file.absFilename())) + return; + + Buffer * child = theBufferList().getBuffer(included_file.absFilename()); + // File not opened, nothing to close. + if (!child) + return; + + // Child document has a different parent, don't close it. + if (child->parent() != parent) + return; + + //close the buffer. + child->setParent(0); + if (close_it) + theBufferList().release(child); + else + updateLabels(*child); +} int InsetInclude::latex(Buffer const & buffer, odocstream & os, OutputParams const & runparams) const { - string incfile(to_utf8(params_["filename"])); + string incfile(to_utf8(params()["filename"])); // Do nothing if no file name has been specified if (incfile.empty()) return 0; - FileName const included_file(includedFilename(buffer, params_)); + FileName const included_file = includedFilename(buffer, params()).availableFile(); //Check we're not trying to include ourselves. //FIXME RECURSIVE INCLUDE //This isn't sufficient, as the inclusion could be downstream. //But it'll have to do for now. - if (isInputOrInclude(params_) && - buffer.fileName() == included_file.absFilename()) + if (isInputOrInclude(params()) && + buffer.absFileName() == included_file.absFilename()) { Alert::error(_("Recursive input"), bformat(_("Attempted to include file %1$s in itself! " @@ -447,14 +396,14 @@ int InsetInclude::latex(Buffer const & buffer, odocstream & os, return 0; } - Buffer const * const m_buffer = buffer.getMasterBuffer(); + Buffer const * const masterBuffer = buffer.masterBuffer(); // if incfile is relative, make it relative to the master // buffer directory. - if (!absolutePath(incfile)) { + if (!FileName(incfile).isAbsolute()) { // FIXME UNICODE incfile = to_utf8(makeRelPath(from_utf8(included_file.absFilename()), - from_utf8(m_buffer->filePath()))); + from_utf8(masterBuffer->filePath()))); } // write it to a file (so far the complete file) @@ -462,45 +411,65 @@ int InsetInclude::latex(Buffer const & buffer, odocstream & os, string const mangled = DocFileName(changeExtension(included_file.absFilename(),".tex")). mangledFilename(); - FileName const writefile(makeAbsPath(mangled, m_buffer->temppath())); + FileName const writefile(makeAbsPath(mangled, masterBuffer->temppath())); if (!runparams.nice) incfile = mangled; else if (!isValidLaTeXFilename(incfile)) { frontend::Alert::warning(_("Invalid filename"), - _("The following filename is likely to cause trouble " + _("The following filename is likely to cause trouble " "when running the exported file through LaTeX: ") + from_utf8(incfile)); } - LYXERR(Debug::LATEX) << "incfile:" << incfile << endl; - LYXERR(Debug::LATEX) << "exportfile:" << exportfile << endl; - LYXERR(Debug::LATEX) << "writefile:" << writefile << endl; + LYXERR(Debug::LATEX, "incfile:" << incfile); + LYXERR(Debug::LATEX, "exportfile:" << exportfile); + LYXERR(Debug::LATEX, "writefile:" << writefile); if (runparams.inComment || runparams.dryrun) { //Don't try to load or copy the file if we're //in a comment or doing a dryrun - } else if (isInputOrInclude(params_) && + } else if (isInputOrInclude(params()) && 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, params_)) + if (!loadIfNeeded(buffer, params())) return false; Buffer * tmp = theBufferList().getBuffer(included_file.absFilename()); - if (tmp->params().textclass != m_buffer->params().textclass) { + if (tmp->params().getBaseClass() != masterBuffer->params().getBaseClass()) { // FIXME UNICODE docstring text = bformat(_("Included file `%1$s'\n" "has textclass `%2$s'\n" "while parent file has textclass `%3$s'."), - makeDisplayPath(included_file.absFilename()), + included_file.displayName(), from_utf8(tmp->params().getTextClass().name()), - from_utf8(m_buffer->params().getTextClass().name())); + from_utf8(masterBuffer->params().getTextClass().name())); Alert::warning(_("Different textclasses"), text); //return 0; } - tmp->markDepClean(m_buffer->temppath()); + // 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. + vector const masterModules = masterBuffer->params().getModules(); + vector const childModules = tmp->params().getModules(); + vector::const_iterator it = childModules.begin(); + vector::const_iterator end = childModules.end(); + for (; it != end; ++it) { + string const module = *it; + vector::const_iterator found = + find(masterModules.begin(), masterModules.end(), module); + if (found != masterModules.end()) { + docstring text = bformat(_("Included file `%1$s'\n" + "uses module `%2$s'\n" + "which is not used in parent file."), + included_file.displayName(), from_utf8(module)); + Alert::warning(_("Module not found"), text); + } + } + + tmp->markDepClean(masterBuffer->temppath()); // FIXME: handle non existing files // FIXME: Second argument is irrelevant! @@ -511,7 +480,7 @@ int InsetInclude::latex(Buffer const & buffer, odocstream & os, Encoding const * const oldEnc = runparams.encoding; runparams.encoding = &tmp->params().encoding(); tmp->makeLaTeXFile(writefile, - onlyPath(masterFilename(buffer)), + masterFileName(buffer).onlyPath().absFilename(), runparams, false); runparams.encoding = oldEnc; } else { @@ -519,17 +488,16 @@ int InsetInclude::latex(Buffer const & buffer, odocstream & os, // to the temp dir, so that .aux files etc. are not created // in the original dir. Files included by this file will be // found via input@path, see ../Buffer.cpp. - unsigned long const checksum_in = sum(included_file); - unsigned long const checksum_out = sum(writefile); + unsigned long const checksum_in = included_file.checksum(); + unsigned long const checksum_out = writefile.checksum(); if (checksum_in != checksum_out) { - if (!copy(included_file, writefile)) { + if (!included_file.copyTo(writefile)) { // FIXME UNICODE - LYXERR(Debug::LATEX) - << to_utf8(bformat(_("Could not copy the file\n%1$s\n" + LYXERR(Debug::LATEX, + to_utf8(bformat(_("Could not copy the file\n%1$s\n" "into the temporary directory."), - from_utf8(included_file.absFilename()))) - << endl; + from_utf8(included_file.absFilename())))); return 0; } } @@ -537,12 +505,12 @@ int InsetInclude::latex(Buffer const & buffer, odocstream & os, string const tex_format = (runparams.flavor == OutputParams::LATEX) ? "latex" : "pdflatex"; - if (isVerbatim(params_)) { + if (isVerbatim(params())) { incfile = latex_path(incfile); // FIXME UNICODE - os << '\\' << from_ascii(params_.getCmdName()) << '{' + os << '\\' << from_ascii(params().getCmdName()) << '{' << from_utf8(incfile) << '}'; - } else if (type(params_) == INPUT) { + } else if (type(params()) == INPUT) { runparams.exportdata->addExternalFile(tex_format, writefile, exportfile); @@ -550,18 +518,18 @@ int InsetInclude::latex(Buffer const & buffer, odocstream & os, if (!isLyXFilename(included_file.absFilename())) { incfile = latex_path(incfile); // FIXME UNICODE - os << '\\' << from_ascii(params_.getCmdName()) + os << '\\' << from_ascii(params().getCmdName()) << '{' << from_utf8(incfile) << '}'; } else { incfile = changeExtension(incfile, ".tex"); incfile = latex_path(incfile); // FIXME UNICODE - os << '\\' << from_ascii(params_.getCmdName()) + os << '\\' << from_ascii(params().getCmdName()) << '{' << from_utf8(incfile) << '}'; } - } else if (type(params_) == LISTINGS) { - os << '\\' << from_ascii(params_.getCmdName()); - string opt = params_.getOptions(); + } else if (type(params()) == LISTINGS) { + os << '\\' << from_ascii(params().getCmdName()); + string const opt = to_utf8(params()["lstparams"]); // opt is set in QInclude dialog and should have passed validation. InsetListingsParams params(opt); if (!params.params().empty()) @@ -576,7 +544,7 @@ int InsetInclude::latex(Buffer const & buffer, odocstream & os, incfile = changeExtension(incfile, string()); incfile = latex_path(incfile); // FIXME UNICODE - os << '\\' << from_ascii(params_.getCmdName()) << '{' + os << '\\' << from_ascii(params().getCmdName()) << '{' << from_utf8(incfile) << '}'; } @@ -587,12 +555,10 @@ int InsetInclude::latex(Buffer const & buffer, odocstream & os, int InsetInclude::plaintext(Buffer const & buffer, odocstream & os, OutputParams const &) const { - if (isVerbatim(params_) || isListings(params_)) { + if (isVerbatim(params()) || isListings(params())) { os << '[' << getScreenLabel(buffer) << '\n'; - // FIXME: We don't know the encoding of the file - docstring const str = - from_utf8(getFileContents(includedFilename(buffer, params_))); - os << str; + // FIXME: We don't know the encoding of the file, default to UTF-8. + os << includedFilename(buffer, params()).fileContents("UTF-8"); os << "\n]"; return PLAINTEXT_NEWLINE + 1; // one char on a separate line } else { @@ -606,19 +572,19 @@ int InsetInclude::plaintext(Buffer const & buffer, odocstream & os, int InsetInclude::docbook(Buffer const & buffer, odocstream & os, OutputParams const & runparams) const { - string incfile = to_utf8(params_["filename"]); + string incfile = to_utf8(params()["filename"]); // Do nothing if no file name has been specified 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 //This isn't sufficient, as the inclusion could be downstream. //But it'll have to do for now. - if (buffer.fileName() == included_file) { + if (buffer.absFileName() == included_file) { Alert::error(_("Recursive input"), bformat(_("Attempted to include file %1$s in itself! " "Ignoring inclusion."), from_utf8(incfile))); @@ -629,18 +595,18 @@ int InsetInclude::docbook(Buffer const & buffer, odocstream & os, string const exportfile = changeExtension(incfile, ".sgml"); DocFileName writefile(changeExtension(included_file, ".sgml")); - if (loadIfNeeded(buffer, params_)) { + if (loadIfNeeded(buffer, params())) { Buffer * tmp = theBufferList().getBuffer(included_file); string const mangled = writefile.mangledFilename(); writefile = makeAbsPath(mangled, - buffer.getMasterBuffer()->temppath()); + buffer.masterBuffer()->temppath()); if (!runparams.nice) incfile = mangled; - LYXERR(Debug::LATEX) << "incfile:" << incfile << endl; - LYXERR(Debug::LATEX) << "exportfile:" << exportfile << endl; - LYXERR(Debug::LATEX) << "writefile:" << writefile << endl; + LYXERR(Debug::LATEX, "incfile:" << incfile); + LYXERR(Debug::LATEX, "exportfile:" << exportfile); + LYXERR(Debug::LATEX, "writefile:" << writefile); tmp->makeDocBookFile(writefile, runparams, true); } @@ -650,7 +616,7 @@ int InsetInclude::docbook(Buffer const & buffer, odocstream & os, runparams.exportdata->addExternalFile("docbook-xml", writefile, exportfile); - if (isVerbatim(params_) || isListings(params_)) { + if (isVerbatim(params()) || isListings(params())) { os << ""; @@ -663,35 +629,35 @@ int InsetInclude::docbook(Buffer const & buffer, odocstream & os, void InsetInclude::validate(LaTeXFeatures & features) const { - string incfile(to_utf8(params_["filename"])); + string incfile = to_utf8(params()["filename"]); string writefile; Buffer const & buffer = features.buffer(); - string const included_file = includedFilename(buffer, params_).absFilename(); + string const included_file = includedFilename(buffer, params()).availableFile().absFilename(); if (isLyXFilename(included_file)) writefile = changeExtension(included_file, ".sgml"); else writefile = included_file; - if (!features.runparams().nice && !isVerbatim(params_) && !isListings(params_)) { + if (!features.runparams().nice && !isVerbatim(params()) && !isListings(params())) { incfile = DocFileName(writefile).mangledFilename(); writefile = makeAbsPath(incfile, - buffer.getMasterBuffer()->temppath()).absFilename(); + buffer.masterBuffer()->temppath()).absFilename(); } features.includeFile(include_label, writefile); - if (isVerbatim(params_)) + if (isVerbatim(params())) features.require("verbatim"); - else if (isListings(params_)) + else if (isListings(params())) features.require("listings"); // Here we must do the fun stuff... // Load the file in the include if it needs // to be loaded: - if (loadIfNeeded(buffer, params_)) { + if (loadIfNeeded(buffer, params())) { // a file got loaded Buffer * const tmp = theBufferList().getBuffer(included_file); // make sure the buffer isn't us @@ -711,71 +677,72 @@ void InsetInclude::validate(LaTeXFeatures & features) const void InsetInclude::getLabelList(Buffer const & buffer, - std::vector & list) const + vector & list) const { - if (isListings(params_)) { - InsetListingsParams params(params_.getOptions()); - string label = params.getParamValue("label"); + if (isListings(params())) { + InsetListingsParams p(to_utf8(params()["lstparams"])); + string label = p.getParamValue("label"); if (!label.empty()) list.push_back(from_utf8(label)); } - else if (loadIfNeeded(buffer, params_)) { - string const included_file = includedFilename(buffer, params_).absFilename(); + else if (loadIfNeeded(buffer, params())) { + string const included_file = includedFilename(buffer, params()).absFilename(); Buffer * tmp = theBufferList().getBuffer(included_file); - tmp->setParentName(""); + tmp->setParent(0); tmp->getLabelList(list); - tmp->setParentName(parentFilename(buffer)); + tmp->setParent(const_cast(&buffer)); } } void InsetInclude::fillWithBibKeys(Buffer const & buffer, - std::vector > & keys) const + BiblioInfo & keys, InsetIterator const & /*di*/) const { - if (loadIfNeeded(buffer, params_)) { - string const included_file = includedFilename(buffer, params_).absFilename(); + if (loadIfNeeded(buffer, params())) { + string const included_file = includedFilename(buffer, params()).absFilename(); Buffer * tmp = theBufferList().getBuffer(included_file); - tmp->setParentName(""); - tmp->fillWithBibKeys(keys); - tmp->setParentName(parentFilename(buffer)); + //FIXME This is kind of a dirty hack and should be made reasonable. + tmp->setParent(0); + keys.fillWithBibKeys(tmp); + tmp->setParent(&buffer); } } void InsetInclude::updateBibfilesCache(Buffer const & buffer) { - Buffer * const tmp = getChildBuffer(buffer, params_); + Buffer * const tmp = getChildBuffer(buffer, params()); if (tmp) { - tmp->setParentName(""); + tmp->setParent(0); tmp->updateBibfilesCache(); - tmp->setParentName(parentFilename(buffer)); + tmp->setParent(&buffer); } } -std::vector const & +EmbeddedFileList const & InsetInclude::getBibfilesCache(Buffer const & buffer) const { - Buffer * const tmp = getChildBuffer(buffer, params_); + Buffer * const tmp = getChildBuffer(buffer, params()); if (tmp) { - tmp->setParentName(""); - std::vector const & cache = tmp->getBibfilesCache(); - tmp->setParentName(parentFilename(buffer)); + tmp->setParent(0); + EmbeddedFileList const & cache = tmp->getBibfilesCache(); + tmp->setParent(&buffer); return cache; } - static std::vector const empty; + static EmbeddedFileList const empty; return empty; } -bool InsetInclude::metrics(MetricsInfo & mi, Dimension & dim) const +void InsetInclude::metrics(MetricsInfo & mi, Dimension & dim) const { - BOOST_ASSERT(mi.base.bv && mi.base.bv->buffer()); + BOOST_ASSERT(mi.base.bv); bool use_preview = false; if (RenderPreview::status() != LyXRC::PREVIEW_OFF) { graphics::PreviewImage const * pimage = - preview_->getPreviewImage(*mi.base.bv->buffer()); + preview_->getPreviewImage(mi.base.bv->buffer()); use_preview = pimage && pimage->image(); } @@ -784,7 +751,7 @@ bool InsetInclude::metrics(MetricsInfo & mi, Dimension & dim) const } else { if (!set_label_) { set_label_ = true; - button_.update(getScreenLabel(*mi.base.bv->buffer()), + button_.update(getScreenLabel(mi.base.bv->buffer()), true); } button_.metrics(mi, dim); @@ -792,23 +759,17 @@ bool InsetInclude::metrics(MetricsInfo & mi, Dimension & dim) const Box b(0, dim.wid, -dim.asc, dim.des); button_.setBox(b); - - bool const changed = dim_ != dim; - dim_ = dim; - return changed; } void InsetInclude::draw(PainterInfo & pi, int x, int y) const { - setPosCache(pi, x, y); - - BOOST_ASSERT(pi.base.bv && pi.base.bv->buffer()); + BOOST_ASSERT(pi.base.bv); bool use_preview = false; if (RenderPreview::status() != LyXRC::PREVIEW_OFF) { graphics::PreviewImage const * pimage = - preview_->getPreviewImage(*pi.base.bv->buffer()); + preview_->getPreviewImage(pi.base.bv->buffer()); use_preview = pimage && pimage->image(); } @@ -821,7 +782,7 @@ void InsetInclude::draw(PainterInfo & pi, int x, int y) const Inset::DisplayType InsetInclude::display() const { - return type(params_) == INPUT ? Inline : AlignCenter; + return type(params()) == INPUT ? Inline : AlignCenter; } @@ -832,14 +793,13 @@ Inset::DisplayType InsetInclude::display() const void InsetInclude::fileChanged() const { - Buffer const * const buffer_ptr = LyX::cref().updateInset(this); - if (!buffer_ptr) + Buffer const * const buffer = updateFrontend(); + if (!buffer) return; - Buffer const & buffer = *buffer_ptr; - preview_->removePreview(buffer); - add_preview(*preview_.get(), *this, buffer); - preview_->startLoading(buffer); + preview_->removePreview(*buffer); + add_preview(*preview_.get(), *this, *buffer); + preview_->startLoading(*buffer); } @@ -850,7 +810,7 @@ bool preview_wanted(InsetCommandParams const & params, Buffer const & buffer) FileName const included_file = includedFilename(buffer, params); return type(params) == INPUT && params.preview() && - isFileReadable(included_file); + included_file.isReadableFile(); } @@ -885,33 +845,35 @@ void add_preview(RenderMonitoredPreview & renderer, InsetInclude const & inset, void InsetInclude::addPreview(graphics::PreviewLoader & ploader) const { Buffer const & buffer = ploader.buffer(); - if (preview_wanted(params(), buffer)) { - preview_->setAbsFile(includedFilename(buffer, params())); - docstring const snippet = latex_string(*this, buffer); - preview_->addPreview(snippet, ploader); - } -} - - -void InsetInclude::addToToc(TocList & toclist, Buffer const & buffer, ParConstIterator const & pit) const -{ - if (isListings(params_)) { - InsetListingsParams params(params_.getOptions()); - string caption = params.getParamValue("caption"); - if (!caption.empty()) { - Toc & toc = toclist["listing"]; - docstring const str = convert(toc.size() + 1) - + ". " + from_utf8(caption); - // This inset does not have a valid ParConstIterator - // so it has to use the iterator of its parent paragraph - toc.push_back(TocItem(pit, 0, str)); - } + if (!preview_wanted(params(), buffer)) + return; + preview_->setAbsFile(includedFilename(buffer, params())); + docstring const snippet = latex_string(*this, buffer); + preview_->addPreview(snippet, ploader); +} + + +void InsetInclude::addToToc(Buffer const & buffer, + ParConstIterator const & cpit) const +{ + if (isListings(params())) { + InsetListingsParams p(to_utf8(params()["lstparams"])); + string caption = p.getParamValue("caption"); + if (caption.empty()) + return; + Toc & toc = buffer.tocBackend().toc("listing"); + docstring const str = convert(toc.size() + 1) + + ". " + from_utf8(caption); + ParConstIterator pit = cpit; + pit.push_back(*this); + toc.push_back(TocItem(pit, 0, str)); return; } - Buffer const * const childbuffer = getChildBuffer(buffer, params_); + Buffer const * const childbuffer = getChildBuffer(buffer, params()); if (!childbuffer) return; + TocList & toclist = buffer.tocBackend().tocs(); TocList const & childtoclist = childbuffer->tocBackend().tocs(); TocList::const_iterator it = childtoclist.begin(); TocList::const_iterator const end = childtoclist.end(); @@ -921,80 +883,45 @@ void InsetInclude::addToToc(TocList & toclist, Buffer const & buffer, ParConstIt } -void InsetInclude::updateLabels(Buffer const & buffer, - ParIterator const &) const +void InsetInclude::updateLabels(Buffer const & buffer, ParIterator const &) { - Buffer const * const childbuffer = getChildBuffer(buffer, params_); - if (childbuffer) + Buffer const * const childbuffer = getChildBuffer(buffer, params()); + if (childbuffer) { lyx::updateLabels(*childbuffer, true); - else if (isListings(params_)) { - InsetListingsParams const par = params_.getOptions(); - if (par.getParamValue("caption").empty()) - listings_label_.clear(); - else { - Counters & counters = buffer.params().getTextClass().counters(); - docstring const cnt = from_ascii("listing"); - if (counters.hasCounter(cnt)) { - counters.step(cnt); - listings_label_ = buffer.B_("Program Listing ") + convert(counters.value(cnt)); - } else - listings_label_ = buffer.B_("Program Listing"); - } + return; } -} - - -string const InsetIncludeMailer::name_("include"); - -InsetIncludeMailer::InsetIncludeMailer(InsetInclude & inset) - : inset_(inset) -{} - + if (!isListings(params())) + return; -string const InsetIncludeMailer::inset2string(Buffer const &) const -{ - return params2string(inset_.params()); + InsetListingsParams const par(to_utf8(params()["lstparams"])); + if (par.getParamValue("caption").empty()) { + listings_label_.clear(); + return; + } + Counters & counters = buffer.params().getTextClass().counters(); + docstring const cnt = from_ascii("listing"); + listings_label_ = buffer.B_("Program Listing"); + if (counters.hasCounter(cnt)) { + counters.step(cnt); + listings_label_ += " " + convert(counters.value(cnt)); + } } -void InsetIncludeMailer::string2params(string const & in, - InsetCommandParams & params) +void InsetInclude::registerEmbeddedFiles(Buffer const & buffer, + EmbeddedFileList & files) const { - params.clear(); - if (in.empty()) - return; - - istringstream data(in); - Lexer lex(0,0); - lex.setStream(data); - - string name; - lex >> name; - if (!lex || name != name_) - return print_mailer_error("InsetIncludeMailer", in, 1, name_); - - // This is part of the inset proper that is usually swallowed - // by Text::readInset - string id; - lex >> id; - if (!lex || id != "Include") - return print_mailer_error("InsetIncludeMailer", in, 2, "Include"); - - InsetInclude inset(params); - inset.read(lex); - params = inset.params(); + files.registerFile(includedFilename(buffer, params()), this, buffer); } -string const -InsetIncludeMailer::params2string(InsetCommandParams const & params) +void InsetInclude::updateEmbeddedFile(Buffer const & buf, + EmbeddedFile const & file) { - InsetInclude inset(params); - ostringstream data; - data << name_ << ' '; - inset.write(data); - data << "\\end_inset\n"; - return data.str(); + InsetCommandParams p = params(); + p["filename"] = from_utf8(file.outputFilename()); + p["embed"] = file.embedded() ? from_utf8(file.inzipName()) : docstring(); + set(p, buf); }