#include "output_docbook.h"
#include "buffer.h"
+#include "buffer_funcs.h"
#include "bufferparams.h"
+#include "outputparams.h"
#include "counters.h"
-#include "lyxtext.h"
+#include "debug.h"
#include "paragraph.h"
#include "paragraph_funcs.h"
+#include "ParagraphList.h"
#include "ParagraphParameters.h"
#include "sgml.h"
#include "support/lstrings.h"
#include "support/lyxlib.h"
-#include "support/tostr.h"
+#include "support/convert.h"
+#include "support/types.h"
-#include <stack>
-#ifdef HAVE_LOCALE
-#endif
+namespace lyx {
-using lyx::support::atoi;
-using lyx::support::split;
-using lyx::support::subst;
+using support::subst;
using std::endl;
using std::ostream;
-using std::stack;
using std::vector;
using std::string;
+namespace {
-void docbookParagraphs(Buffer const & buf,
- ParagraphList const & paragraphs,
- ostream & os,
- OutputParams const & runparams)
+ParagraphList::const_iterator searchParagraph(
+ ParagraphList::const_iterator const & par,
+ ParagraphList::const_iterator const & pend)
{
- vector<string> environment_stack(10);
- vector<string> environment_inner(10);
- vector<string> command_stack(10);
-
- bool command_flag = false;
- Paragraph::depth_type command_depth = 0;
- Paragraph::depth_type command_base = 0;
- Paragraph::depth_type cmd_depth = 0;
- Paragraph::depth_type depth = 0; // paragraph depth
+ ParagraphList::const_iterator p = boost::next(par);
- string command_name;
+ for (; p != pend && p->layout()->latextype == LATEX_PARAGRAPH; ++p)
+ ;
- string item_tag;
+ return p;
+}
- ParagraphList::iterator par = const_cast<ParagraphList&>(paragraphs).begin();
- ParagraphList::iterator pend = const_cast<ParagraphList&>(paragraphs).end();
- Counters & counters = buf.params().getLyXTextClass().counters();
-
- for (; par != pend; ++par) {
+ParagraphList::const_iterator searchCommand(
+ ParagraphList::const_iterator const & par,
+ ParagraphList::const_iterator const & pend)
+{
+ LyXLayout_ptr const & bstyle = par->layout();
+ ParagraphList::const_iterator p = boost::next(par);
+
+ for ( ; p != pend; ++p) {
+ LyXLayout_ptr const & style = p->layout();
+ if (style->latextype == LATEX_COMMAND
+ && style->commanddepth <= bstyle->commanddepth)
+ return p;
+ }
+ return pend;
+}
- LyXLayout_ptr const & style = par->layout();
- // environment tag closing
- for (; depth > par->params().depth(); --depth) {
- sgml::closeEnvTags(os, false, environment_inner[depth],
- item_tag, command_depth + depth);
- sgml::closeTag(os, depth + command_depth, false, environment_stack[depth]);
- environment_stack[depth].erase();
- environment_inner[depth].erase();
+ParagraphList::const_iterator searchEnvironment(
+ ParagraphList::const_iterator const & par,
+ ParagraphList::const_iterator const & pend)
+{
+ LyXLayout_ptr const & bstyle = par->layout();
+ ParagraphList::const_iterator p = boost::next(par);
+ for (; p != pend; ++p) {
+ LyXLayout_ptr const & style = p->layout();
+ if (style->latextype == LATEX_COMMAND)
+ return p;
+
+ if (style->latextype == LATEX_PARAGRAPH) {
+ if (p->params().depth() > par->params().depth())
+ continue;
+ return p;
}
- if (depth == par->params().depth()
- && environment_stack[depth] != style->latexname()
- && !environment_stack[depth].empty()) {
- sgml::closeEnvTags(os, false, environment_inner[depth],
- item_tag, command_depth + depth);
- sgml::closeTag(os, depth + command_depth, false, environment_stack[depth]);
+ if (p->params().depth() < par->params().depth())
+ return p;
- environment_stack[depth].erase();
- environment_inner[depth].erase();
+ if (style->latexname() != bstyle->latexname()
+ && p->params().depth() == par->params().depth() )
+ return p;
+ }
+ return pend;
+}
+
+
+ParagraphList::const_iterator makeParagraph(Buffer const & buf,
+ odocstream & os,
+ OutputParams const & runparams,
+ ParagraphList const & paragraphs,
+ ParagraphList::const_iterator const & pbegin,
+ ParagraphList::const_iterator const & pend)
+{
+ LyXLayout_ptr const & defaultstyle =
+ buf.params().getLyXTextClass().defaultLayout();
+ for (ParagraphList::const_iterator par = pbegin; par != pend; ++par) {
+ if (par != pbegin)
+ os << '\n';
+ if (par->layout() == defaultstyle && par->emptyTag()) {
+ par->simpleDocBookOnePar(buf, os, runparams, outerFont(std::distance(paragraphs.begin(), par), paragraphs));
+ } else {
+ sgml::openTag(buf, os, runparams, *par);
+ par->simpleDocBookOnePar(buf, os, runparams, outerFont(std::distance(paragraphs.begin(), par), paragraphs));
+ sgml::closeTag(os, *par);
}
-
- string ls = "";
- bool labelid = false;
- // Write opening SGML tags.
- switch (style->latextype) {
- case LATEX_PARAGRAPH:
- if (!style->latexparam().empty()) {
- counters.step("para");
- int i = counters.value("para");
- ls = "id=\"" + subst(style->latexparam(), "#", tostr(i)) + '"';
- }
- sgml::openTag(os, depth + command_depth,
- false, style->latexname(), ls);
- break;
+ }
+ return pend;
+}
- case LATEX_COMMAND:
- if (depth != 0)
- //error(ErrorItem(_("Error"), _("Wrong depth for LatexType Command."), par->id(), 0, par->size()));
- ;
-
- command_name = style->latexname();
-
- cmd_depth = style->commanddepth;
-
- if (command_flag) {
- if (cmd_depth < command_base) {
- for (Paragraph::depth_type j = command_depth;
- j >= command_base; --j) {
- sgml::closeTag(os, j, false, command_stack[j]);
- os << endl;
- }
- command_depth = command_base = cmd_depth;
- } else if (cmd_depth <= command_depth) {
- for (int j = command_depth;
- j >= int(cmd_depth); --j) {
- sgml::closeTag(os, j, false, command_stack[j]);
- os << endl;
- }
- command_depth = cmd_depth;
- } else
- command_depth = cmd_depth;
- } else {
- command_depth = command_base = cmd_depth;
- command_flag = true;
- }
- if (command_stack.size() == command_depth + 1)
- command_stack.push_back(string());
- command_stack[command_depth] = command_name;
- if (!style->latexparam().empty()) {
- counters.step(style->counter);
+ParagraphList::const_iterator makeEnvironment(Buffer const & buf,
+ odocstream & os,
+ OutputParams const & runparams,
+ ParagraphList const & paragraphs,
+ ParagraphList::const_iterator const & pbegin,
+ ParagraphList::const_iterator const & pend) {
+ ParagraphList::const_iterator par = pbegin;
+
+ LyXLayout_ptr const & defaultstyle = buf.params().getLyXTextClass().defaultLayout();
+ LyXLayout_ptr const & bstyle = par->layout();
+ string item_tag;
+
+ // Opening outter tag
+ sgml::openTag(buf, os, runparams, *pbegin);
+ os << '\n';
+ if (bstyle->latextype == LATEX_ENVIRONMENT && bstyle->pass_thru)
+ os << "<![CDATA[";
+
+ while (par != pend) {
+ LyXLayout_ptr const & style = par->layout();
+ ParagraphList::const_iterator send;
+ string id = par->getID(buf, runparams);
+ string wrapper = "";
+ pos_type sep = 0;
+
+ // Opening inner tag
+ switch (bstyle->latextype) {
+ case LATEX_ENVIRONMENT:
+ if (!bstyle->innertag().empty()) {
+ sgml::openTag(os, bstyle->innertag(), id);
}
- // treat label as a special case for
- // more WYSIWYM handling.
- // This is a hack while paragraphs can't have
- // attributes, like id in this case.
- if (par->size() && par->isInset(0)) {
- InsetOld * inset = par->getInset(0);
- InsetOld::Code lyx_code = inset->lyxCode();
- if (lyx_code == InsetOld::LABEL_CODE) {
- command_name += " id=\"";
- command_name += (static_cast<InsetCommand *>(inset))->getContents();
- command_name += '"';
- labelid = true;
- }
- } else {
- if (!style->latexparam().empty()) {
- ls = expandLabel(buf.params().getLyXTextClass(), style, false);
- ls = "id=\"" + subst(style->latexparam(), "#", ls) + '"';
- }
+ break;
+
+ case LATEX_ITEM_ENVIRONMENT:
+ if (!bstyle->labeltag().empty()) {
+ sgml::openTag(os, bstyle->innertag(), id);
+ sgml::openTag(os, bstyle->labeltag());
+ sep = par->getFirstWord(buf, os, runparams) + 1;
+ sgml::closeTag(os, bstyle->labeltag());
}
-
- sgml::openTag(os, depth + command_depth, false, command_name, ls);
-
- // Label around sectioning number:
- if (!style->labeltag().empty()) {
- sgml::openTag(os, depth + 1 + command_depth, false,
- style->labeltag());
- os << expandLabel(buf.params().getLyXTextClass(), style, false);
- sgml::closeTag(os, depth + 1 + command_depth, false,
- style->labeltag());
+ wrapper = defaultstyle->latexname();
+ // If a sub list (embedded list) appears next with a
+ // different depth, then there is no need to open
+ // another tag at the current depth.
+ if(par->params().depth() == pbegin->params().depth()) {
+ sgml::openTag(os, bstyle->itemtag());
}
-
- // Inner tagged header text, e.g. <title> for sectioning:
- sgml::openTag(os, depth + 1 + command_depth, false,
- style->innertag());
break;
+ default:
+ break;
+ }
+ switch (style->latextype) {
case LATEX_ENVIRONMENT:
- case LATEX_ITEM_ENVIRONMENT:
- if (depth < par->params().depth()) {
- depth = par->params().depth();
- environment_stack[depth].erase();
+ case LATEX_ITEM_ENVIRONMENT: {
+ if (par->params().depth() == pbegin->params().depth()) {
+ sgml::openTag(os, wrapper);
+ par->simpleDocBookOnePar(buf, os, runparams, outerFont(std::distance(paragraphs.begin(), par), paragraphs), sep);
+ sgml::closeTag(os, wrapper);
+ ++par;
}
-
- if (environment_stack[depth] != style->latexname()) {
- if (environment_stack.size() == depth + 1) {
- environment_stack.push_back("!-- --");
- environment_inner.push_back("!-- --");
- }
- environment_stack[depth] = style->latexname();
- environment_inner[depth] = "!-- --";
- // outputs <environment_stack[depth] latexparam()>
- sgml::openTag(os, depth + command_depth, false,
- environment_stack[depth], style->latexparam());
- } else {
- sgml::closeEnvTags(os, false, environment_inner[depth],
- style->itemtag(), command_depth + depth);
+ else {
+ send = searchEnvironment(par, pend);
+ par = makeEnvironment(buf, os, runparams, paragraphs, par,send);
}
+ break;
+ }
+ case LATEX_PARAGRAPH:
+ send = searchParagraph(par, pend);
+ par = makeParagraph(buf, os, runparams, paragraphs, par,send);
+ break;
+ default:
+ break;
+ }
- if (style->latextype == LATEX_ENVIRONMENT) {
- if (!style->innertag().empty()) {
- if (style->innertag() == "CDATA")
- os << "<![CDATA[";
- else
- sgml::openTag(os, depth + command_depth, false,
- style->innertag());
- }
- break;
+ // Closing inner tag
+ switch (bstyle->latextype) {
+ case LATEX_ENVIRONMENT:
+ if (!bstyle->innertag().empty()) {
+ sgml::closeTag(os, bstyle->innertag());
+ os << '\n';
}
-
- environment_inner[depth] = style->innertag();
-
- if (!environment_inner[depth].empty())
- sgml::openTag(os, depth + 1 + command_depth,
- false, environment_inner[depth]);
+ break;
+ case LATEX_ITEM_ENVIRONMENT:
+ // If a sub list (embedded list) appears next, then
+ // there is no need to close the current tag.
+ // par should have already been incremented to the next
+ // element. So we can compare the depth of the next
+ // element with pbegin.
+ // We need to be careful, that we don't dereference par
+ // when par == pend but at the same time that the
+ // current tag is closed.
+ if((par != pend && par->params().depth() == pbegin->params().depth()) || par == pend) {
+ sgml::closeTag(os, bstyle->itemtag());
+ }
+ if (!bstyle->labeltag().empty())
+ sgml::closeTag(os, bstyle->innertag());
break;
default:
- sgml::openTag(os, depth + command_depth,
- false, style->latexname());
break;
}
+ }
+
+ if (bstyle->latextype == LATEX_ENVIRONMENT && bstyle->pass_thru)
+ os << "]]>";
+
+ // Closing outter tag
+ sgml::closeTag(os, *pbegin);
+
+ return pend;
+}
- par->simpleDocBookOnePar(buf, os, outerFont(par, paragraphs),
- runparams, depth + 1 + command_depth, labelid);
- // write closing SGML tags
+ParagraphList::const_iterator makeCommand(Buffer const & buf,
+ odocstream & os,
+ OutputParams const & runparams,
+ ParagraphList const & paragraphs,
+ ParagraphList::const_iterator const & pbegin,
+ ParagraphList::const_iterator const & pend)
+{
+ ParagraphList::const_iterator par = pbegin;
+ LyXLayout_ptr const & bstyle = par->layout();
+
+ //Open outter tag
+ sgml::openTag(buf, os, runparams, *pbegin);
+ os << '\n';
+
+ // Label around sectioning number:
+ if (!bstyle->labeltag().empty()) {
+ sgml::openTag(os, bstyle->labeltag());
+ // We don't care about appendix in DOCBOOK.
+ os << par->expandLabel(bstyle, buf.params(), false);
+ sgml::closeTag(os, bstyle->labeltag());
+ }
+
+ // Opend inner tag and close inner tags
+ sgml::openTag(os, bstyle->innertag());
+ par->simpleDocBookOnePar(buf, os, runparams, outerFont(std::distance(paragraphs.begin(), par), paragraphs));
+ sgml::closeTag(os, bstyle->innertag());
+ os << '\n';
+
+ ++par;
+ while (par != pend) {
+ LyXLayout_ptr const & style = par->layout();
+ ParagraphList::const_iterator send;
+
switch (style->latextype) {
- case LATEX_COMMAND:
- sgml::closeTag(os, depth + command_depth, false,
- style->innertag());
+ case LATEX_COMMAND: {
+ send = searchCommand(par, pend);
+ par = makeCommand(buf, os, runparams, paragraphs, par,send);
break;
+ }
case LATEX_ENVIRONMENT:
- if (!style->innertag().empty()) {
- if (style->innertag() == "CDATA")
- os << "]]>";
- else
- sgml::closeTag(os, depth + command_depth, false,
- style->innertag());
- }
- break;
- case LATEX_ITEM_ENVIRONMENT:
- item_tag = style->itemtag();
+ case LATEX_ITEM_ENVIRONMENT: {
+ send = searchEnvironment(par, pend);
+ par = makeEnvironment(buf, os, runparams, paragraphs, par,send);
break;
+ }
case LATEX_PARAGRAPH:
- sgml::closeTag(os, depth + command_depth, false, style->latexname());
+ send = searchParagraph(par, pend);
+ par = makeParagraph(buf, os, runparams, paragraphs, par,send);
break;
default:
- sgml::closeTag(os, depth + command_depth, false, style->latexname());
break;
}
}
+ // Close outter tag
+ sgml::closeTag(os, *pbegin);
- // Close open tags
- for (int d = depth; d >= 0; --d) {
- if (!environment_stack[depth].empty()) {
- sgml::closeEnvTags(os, false, environment_inner[depth],
- item_tag, command_depth + depth);
- }
+ return pend;
+}
+
+} // end anonym namespace
+
+
+void docbookParagraphs(ParagraphList const & paragraphs,
+ Buffer const & buf,
+ odocstream & os,
+ OutputParams const & runparams)
+{
+ ParagraphList::const_iterator par = paragraphs.begin();
+ ParagraphList::const_iterator pend = paragraphs.end();
+
+ BOOST_ASSERT(runparams.par_begin <= runparams.par_end);
+ // if only part of the paragraphs will be outputed
+ if (runparams.par_begin != runparams.par_end) {
+ par = boost::next(paragraphs.begin(), runparams.par_begin);
+ pend = boost::next(paragraphs.begin(), runparams.par_end);
+ // runparams will be passed to nested paragraphs, so
+ // we have to reset the range parameters.
+ const_cast<OutputParams&>(runparams).par_begin = 0;
+ const_cast<OutputParams&>(runparams).par_end = 0;
}
+
+ while (par != pend) {
+ LyXLayout_ptr const & style = par->layout();
+ ParagraphList::const_iterator lastpar = par;
+ ParagraphList::const_iterator send;
- for (int j = command_depth; j >= 0 ; --j)
- if (!command_stack[j].empty()) {
- sgml::closeTag(os, j, false, command_stack[j]);
- os << endl;
+ switch (style->latextype) {
+ case LATEX_COMMAND: {
+ send = searchCommand(par, pend);
+ par = makeCommand(buf, os, runparams, paragraphs, par,send);
+ break;
}
+ case LATEX_ENVIRONMENT:
+ case LATEX_ITEM_ENVIRONMENT: {
+ send = searchEnvironment(par, pend);
+ par = makeEnvironment(buf, os, runparams, paragraphs, par,send);
+ break;
+ }
+ case LATEX_PARAGRAPH:
+ send = searchParagraph(par, pend);
+ par = makeParagraph(buf, os, runparams, paragraphs, par,send);
+ break;
+ default:
+ break;
+ }
+ // makeEnvironment may process more than one paragraphs and bypass pend
+ if (std::distance(lastpar, par) >= std::distance(lastpar, pend))
+ break;
+ }
}
+
+} // namespace lyx