X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetTOC.cpp;h=29b7540cc277cbb2c690e5f15a2a2e50e4b49b12;hb=2777b51c587cb061b3214c670a3cc4b357528e6c;hp=51234af7cd27c2e47c914fa0c0a82c6c7293707c;hpb=897436efbb9bd641b61467d185a2dfae9839e575;p=lyx.git diff --git a/src/insets/InsetTOC.cpp b/src/insets/InsetTOC.cpp index 51234af7cd..29b7540cc2 100644 --- a/src/insets/InsetTOC.cpp +++ b/src/insets/InsetTOC.cpp @@ -3,7 +3,7 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Lars Gullik Bjønnes + * \author Lars Gullik Bjønnes * * Full author contact details are available in file CREDITS. */ @@ -13,62 +13,122 @@ #include "InsetTOC.h" #include "Buffer.h" +#include "BufferParams.h" +#include "BufferView.h" +#include "Cursor.h" #include "DispatchResult.h" +#include "Font.h" #include "FuncRequest.h" -#include "gettext.h" -#include "MetricsInfo.h" +#include "Language.h" +#include "LaTeXFeatures.h" #include "OutputParams.h" +#include "output_xhtml.h" +#include "Paragraph.h" +#include "ParagraphParameters.h" +#include "TextClass.h" #include "TocBackend.h" -#include "support/std_ostream.h" +#include "support/debug.h" +#include "support/gettext.h" +#include "support/lassert.h" +#include + +using namespace std; namespace lyx { -using std::string; -using std::ostream; +namespace { +string cmd2type(string const & cmd) +{ + if (cmd == "lstlistoflistings") + return "listing"; + return cmd; +} +} // namespace -InsetTOC::InsetTOC(InsetCommandParams const & p) - : InsetCommand(p, "toc") +InsetTOC::InsetTOC(Buffer * buf, InsetCommandParams const & p) + : InsetCommand(buf, p) {} -std::auto_ptr InsetTOC::doClone() const +ParamInfo const & InsetTOC::findInfo(string const & /* cmdName */) +{ + static ParamInfo param_info_; + if (param_info_.empty()) { + param_info_.add("type", ParamInfo::LATEX_REQUIRED); + } + return param_info_; +} + + +bool InsetTOC::isCompatibleCommand(string const & cmd) { - return std::auto_ptr(new InsetTOC(*this)); + return cmd == defaultCommand() || cmd == "lstlistoflistings"; } -docstring const InsetTOC::getScreenLabel(Buffer const & buf) const +docstring InsetTOC::screenLabel() const { if (getCmdName() == "tableofcontents") - return buf.B_("Table of Contents"); + return buffer().B_("Table of Contents"); + if (getCmdName() == "lstlistoflistings") + return buffer().B_("List of Listings"); return _("Unknown TOC type"); } -Inset::Code InsetTOC::lyxCode() const +void InsetTOC::doDispatch(Cursor & cur, FuncRequest & cmd) { + switch (cmd.action()) { + case LFUN_MOUSE_RELEASE: + if (!cur.selection() && cmd.button() == mouse_button::button1) { + cur.bv().showDialog("toc", params2string(params())); + cur.dispatched(); + } + break; + + default: + InsetCommand::doDispatch(cur, cmd); + } +} + + +docstring InsetTOC::layoutName() const { - if (getCmdName() == "tableofcontents") - return Inset::TOC_CODE; - return Inset::NO_CODE; + if (getCmdName() == "lstlistoflistings") { + if (buffer().params().use_minted) + return from_ascii("TOC:MintedListings"); + else + return from_ascii("TOC:Listings"); + } + return from_ascii("TOC"); } -int InsetTOC::plaintext(Buffer const & buffer, odocstream & os, - OutputParams const &) const +void InsetTOC::validate(LaTeXFeatures & features) const { - os << getScreenLabel(buffer) << "\n\n"; + InsetCommand::validate(features); + features.useInsetLayout(getLayout()); + if (getCmdName() == "lstlistoflistings") { + if (buffer().params().use_minted) + features.require("minted"); + else + features.require("listings"); + } +} - buffer.tocBackend().writePlaintextTocList(getCmdName(), os); +int InsetTOC::plaintext(odocstringstream & os, + OutputParams const &, size_t max_length) const +{ + os << screenLabel() << "\n\n"; + buffer().tocBackend().writePlaintextTocList(cmd2type(getCmdName()), os, max_length); return PLAINTEXT_NEWLINE; } -int InsetTOC::docbook(Buffer const &, odocstream & os, - OutputParams const &) const +int InsetTOC::docbook(odocstream & os, OutputParams const &) const { if (getCmdName() == "tableofcontents") os << ""; @@ -76,4 +136,150 @@ int InsetTOC::docbook(Buffer const &, odocstream & os, } +void InsetTOC::makeTOCEntry(XHTMLStream & xs, + Paragraph const & par, OutputParams const & op) const +{ + string const attr = "href='#" + par.magicLabel() + "' class='tocentry'"; + xs << html::StartTag("a", attr); + + // First the label, if there is one + docstring const & label = par.params().labelString(); + if (!label.empty()) + xs << label << " "; + // Now the content of the TOC entry, taken from the paragraph itself + OutputParams ours = op; + ours.for_toc = true; + Font const dummy; + par.simpleLyXHTMLOnePar(buffer(), xs, ours, dummy); + + xs << html::EndTag("a") << html::CR(); +} + + +void InsetTOC::makeTOCWithDepth(XHTMLStream & xs, + Toc const & toc, OutputParams const & op) const +{ + Toc::const_iterator it = toc.begin(); + Toc::const_iterator const en = toc.end(); + int lastdepth = 0; + for (; it != en; ++it) { + // do not output entries that are not actually included in the output, + // e.g., stuff in non-active branches or notes or whatever. + if (!it->isOutput()) + continue; + + // First, we need to manage increases and decreases of depth + // If there's no depth to deal with, we artifically set it to 1. + int const depth = it->depth(); + + // Ignore stuff above the tocdepth + if (depth > buffer().params().tocdepth) + continue; + + if (depth > lastdepth) { + xs << html::CR(); + // open as many tags as we need to open to get to this level + // this includes the tag for the current level + for (int i = lastdepth + 1; i <= depth; ++i) { + stringstream attr; + attr << "class='lyxtoc-" << i << "'"; + xs << html::StartTag("div", attr.str()) << html::CR(); + } + lastdepth = depth; + } + else if (depth < lastdepth) { + // close as many as we have to close to get back to this level + // this includes closing the last tag at this level + for (int i = lastdepth; i >= depth; --i) + xs << html::EndTag("div") << html::CR(); + // now open our tag + stringstream attr; + attr << "class='lyxtoc-" << depth << "'"; + xs << html::StartTag("div", attr.str()) << html::CR(); + lastdepth = depth; + } else { + // no change of level, so close and open + xs << html::EndTag("div") << html::CR(); + stringstream attr; + attr << "class='lyxtoc-" << depth << "'"; + xs << html::StartTag("div", attr.str()) << html::CR(); + } + + // Now output TOC info for this entry + Paragraph const & par = it->dit().innerParagraph(); + makeTOCEntry(xs, par, op); + } + for (int i = lastdepth; i > 0; --i) + xs << html::EndTag("div") << html::CR(); +} + + +void InsetTOC::makeTOCNoDepth(XHTMLStream & xs, + Toc const & toc, const OutputParams & op) const +{ + Toc::const_iterator it = toc.begin(); + Toc::const_iterator const en = toc.end(); + for (; it != en; ++it) { + // do not output entries that are not actually included in the output, + // e.g., stuff in non-active branches or notes or whatever. + if (!it->isOutput()) + continue; + + xs << html::StartTag("div", "class='lyxtoc-flat'") << html::CR(); + + Paragraph const & par = it->dit().innerParagraph(); + makeTOCEntry(xs, par, op); + + xs << html::EndTag("div"); + } +} + + +docstring InsetTOC::xhtml(XHTMLStream &, OutputParams const & op) const +{ + string const & command = getCmdName(); + if (command != "tableofcontents" && command != "lstlistoflistings") { + LYXERR0("TOC type " << command << " not yet implemented."); + LASSERT(false, return docstring()); + } + + shared_ptr toc = + buffer().masterBuffer()->tocBackend().toc(cmd2type(command)); + if (toc->empty()) + return docstring(); + + // we'll use our own stream, because we are going to defer everything. + // that's how we deal with the fact that we're probably inside a standard + // paragraph, and we don't want to be. + odocstringstream ods; + XHTMLStream xs(ods); + + xs << html::StartTag("div", "class='toc'"); + + // Title of TOC + InsetLayout const & il = getLayout(); + string const & tag = il.htmltag(); + docstring title = screenLabel(); + Layout const & lay = buffer().params().documentClass().htmlTOCLayout(); + string const & tocclass = lay.defaultCSSClass(); + string const tocattr = "class='tochead " + tocclass + "'"; + xs << html::StartTag(tag, tocattr) + << title + << html::EndTag(tag); + + // with lists of listings, at least, there is no depth + // to worry about. so the code can be simpler. + bool const use_depth = (command == "tableofcontents"); + + // Output of TOC + if (use_depth) + makeTOCWithDepth(xs, *toc, op); + else + makeTOCNoDepth(xs, *toc, op); + + xs << html::EndTag("div") << html::CR(); + return ods.str(); +} + + } // namespace lyx