diff --git a/src/insets/InsetCaptionable.cpp b/src/insets/InsetCaptionable.cpp index a8a2108ce9..474eaf059e 100644 --- a/src/insets/InsetCaptionable.cpp +++ b/src/insets/InsetCaptionable.cpp @@ -13,9 +13,10 @@ #include +#include "InsetBox.h" #include "InsetCaptionable.h" - #include "InsetCaption.h" +#include "InsetLabel.h" #include "Buffer.h" #include "BufferParams.h" @@ -64,14 +65,59 @@ InsetCaption const * InsetCaptionable::getCaptionInset() const } } } - return 0; + return nullptr; +} + + +InsetLabel const * InsetCaptionable::getLabelInset() const +{ + // A wrong hypothesis would be to limit the search to the caption: it is most likely there, but not necessarily! + + // Iterate through the contents of the inset. + auto const end = paragraphs().end(); + for (auto par = paragraphs().begin(); par != end; ++par) { + for (pos_type pos = 0; pos < par->size(); ++pos) { + const Inset * inset = par->getInset(pos); + + // If this inset is a subfigure, skip it. Otherwise, you would return the label for the subfigure. + if (dynamic_cast(inset)) { + continue; + } + + // Maybe an inset is directly a label, in which case no more work is needed. + if (inset && dynamic_cast(inset)) + return dynamic_cast(inset); + + // More likely, the label is hidden in an inset of a paragraph (only if a subtype of InsetText). Thus, + // dig into that text. + if (!dynamic_cast(inset)) + continue; + + auto insetAsText = dynamic_cast(inset); + auto itIn = insetAsText->paragraphs().begin(); + auto endIn = insetAsText->paragraphs().end(); + for (; itIn != endIn; ++itIn) { + for (pos_type posIn = 0; posIn < itIn->size(); ++posIn) { + const Inset *insetIn = itIn->getInset(posIn); + if (insetIn && dynamic_cast(insetIn)) { + return dynamic_cast(insetIn); + } + } + } + + // Obviously, this solution does not scale with more levels of paragraphs and insets, but this should + // be enough: it is only used in captions. + } + } + + return nullptr; } docstring InsetCaptionable::getCaptionText(OutputParams const & runparams) const { InsetCaption const * ins = getCaptionInset(); - if (ins == 0) + if (!ins) return docstring(); odocstringstream ods; diff --git a/src/insets/InsetCaptionable.h b/src/insets/InsetCaptionable.h index aa9a4cc426..ac11f55ca2 100644 --- a/src/insets/InsetCaptionable.h +++ b/src/insets/InsetCaptionable.h @@ -21,6 +21,7 @@ namespace lyx { class InsetCaption; +class InsetLabel; class InsetCaptionable : public InsetCollapsible { @@ -36,6 +37,8 @@ protected: /// InsetCaption const * getCaptionInset() const; /// + InsetLabel const * getLabelInset() const; + /// docstring getCaptionText(OutputParams const &) const; /// docstring getCaptionHTML(OutputParams const &) const; diff --git a/src/insets/InsetFloat.cpp b/src/insets/InsetFloat.cpp index 86e3f9b338..f486fc7980 100644 --- a/src/insets/InsetFloat.cpp +++ b/src/insets/InsetFloat.cpp @@ -514,63 +514,6 @@ std::vector findSubfiguresInParagraph(const Paragraph } -namespace { - -const InsetLabel* findLabelInParagraph(const Paragraph &par) -{ - for (pos_type pos = 0; pos < par.size(); ++pos) { - // If this inset is a subfigure, skip it. - const Inset *inset = par.getInset(pos); - if (dynamic_cast(inset)) { - continue; - } - - // Maybe an inset is directly a label, in which case no more work is needed. - if (inset && dynamic_cast(inset)) - return dynamic_cast(inset); - - // More likely, the label is hidden in an inset of a paragraph (only if a subtype of InsetText). - if (!dynamic_cast(inset)) - continue; - - auto insetAsText = dynamic_cast(inset); - auto itIn = insetAsText->paragraphs().begin(); - auto endIn = insetAsText->paragraphs().end(); - for (; itIn != endIn; ++itIn) { - for (pos_type posIn = 0; posIn < itIn->size(); ++posIn) { - const Inset *insetIn = itIn->getInset(posIn); - if (insetIn && dynamic_cast(insetIn)) { - return dynamic_cast(insetIn); - } - } - } - - // Obviously, this solution does not scale with more levels of paragraphs-insets, but this should be enough. - } - - return nullptr; -} - -} // anonymous namespace - - -const InsetCaption* findCaptionInParagraph(const Paragraph &par) -{ - // Don't dive too deep, otherwise, this could be a subfigure caption. - for (pos_type pos = 0; pos < par.size(); ++pos) { - // If this inset is a subfigure, skip it. - const Inset *inset = par.getInset(pos); - if (dynamic_cast(inset)) - continue; - - if (inset && dynamic_cast(inset)) - return dynamic_cast(inset); - } - - return nullptr; -} - - /// Takes an unstructured subfigure container (typically, an InsetBox) and find the elements within: /// actual content (image or table), maybe a caption, maybe a label. std::tuple docbookParseHopelessSubfigure(const InsetText * subfigure) @@ -814,13 +757,11 @@ void docbookNoSubfigures(XMLStream & xs, OutputParams const & runparams, const I void InsetFloat::docbook(XMLStream & xs, OutputParams const & runparams) const { - // Determine whether the float has a title or not. For this, iterate through the paragraphs and look - // for an InsetCaption. Do the same for labels and subfigures. - // The caption and the label for each subfigure is handled by recursive calls. - const InsetCaption* caption = nullptr; - const InsetLabel* label = nullptr; - std::vector subfigures; + const InsetCaption* caption = getCaptionInset(); + const InsetLabel* label = getLabelInset(); + // Determine whether the float has subfigures. + std::vector subfigures; auto end = paragraphs().end(); for (auto it = paragraphs().begin(); it != end; ++it) { std::vector foundSubfigures = findSubfiguresInParagraph(*it); @@ -828,11 +769,6 @@ void InsetFloat::docbook(XMLStream & xs, OutputParams const & runparams) const subfigures.reserve(subfigures.size() + foundSubfigures.size()); subfigures.insert(subfigures.end(), foundSubfigures.begin(), foundSubfigures.end()); } - - if (!caption) - caption = findCaptionInParagraph(*it); - if (!label) - label = findLabelInParagraph(*it); } // Gather a few things from global environment that are shared between all following cases. diff --git a/src/insets/InsetListings.cpp b/src/insets/InsetListings.cpp index cff7bcc9c1..7ac940d742 100644 --- a/src/insets/InsetListings.cpp +++ b/src/insets/InsetListings.cpp @@ -482,42 +482,6 @@ docstring InsetListings::xhtml(XMLStream & os, OutputParams const & rp) const } -namespace { - -const InsetLabel* findLabelInParagraph(const Paragraph &par) -{ - for (pos_type pos = 0; pos < par.size(); ++pos) { - const Inset *inset = par.getInset(pos); - - // Maybe an inset is directly a label, in which case no more work is needed. - if (inset && dynamic_cast(inset)) - return dynamic_cast(inset); - - // More likely, the label is hidden in an inset of a paragraph (only if a subtype of InsetText). - if (!dynamic_cast(inset)) - continue; - - auto insetAsText = dynamic_cast(inset); - auto itIn = insetAsText->paragraphs().begin(); - auto endIn = insetAsText->paragraphs().end(); - for (; itIn != endIn; ++itIn) { - for (pos_type posIn = 0; posIn < itIn->size(); ++posIn) { - const Inset *insetIn = itIn->getInset(posIn); - if (insetIn && dynamic_cast(insetIn)) { - return dynamic_cast(insetIn); - } - } - } - - // Obviously, this solution does not scale with more levels of paragraphs-insets, but this should be enough. - } - - return nullptr; -} - -} // anonymous namespace - - void InsetListings::docbook(XMLStream & xs, OutputParams const & rp) const { InsetLayout const & il = getLayout(); @@ -531,14 +495,7 @@ void InsetListings::docbook(XMLStream & xs, OutputParams const & rp) const // TODO: parts of this code could be merged with InsetFloat and findLabelInParagraph. InsetCaption const * caption = getCaptionInset(); if (caption) { - // Find the label in the caption, if any. - InsetLabel const * label; - auto const end = caption->paragraphs().end(); - for (auto it = caption->paragraphs().begin(); it != end; ++it) { - label = findLabelInParagraph(*it); - if (label) - break; - } + InsetLabel const * label = getLabelInset(); // Ensure that the label will not be output a second time as an anchor. OutputParams rpNoLabel = rp;