X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Foutput_docbook.C;h=2778dde86e67a77fc57fe57bb959ead634675c51;hb=e5a46922e916a06ad1b958d5895cc3cfb4f13d2c;hp=c57bb0d32127c754a9ec7d7f5b695a3cafde0be0;hpb=1eaa3eb913b16f4e6f5991b9c53b0b9ab3f84948;p=lyx.git diff --git a/src/output_docbook.C b/src/output_docbook.C index c57bb0d321..2778dde86e 100644 --- a/src/output_docbook.C +++ b/src/output_docbook.C @@ -14,12 +14,14 @@ #include "output_docbook.h" #include "buffer.h" +#include "buffer_funcs.h" #include "bufferparams.h" +#include "outputparams.h" #include "counters.h" #include "debug.h" -#include "lyxtext.h" #include "paragraph.h" #include "paragraph_funcs.h" +#include "ParagraphList.h" #include "ParagraphParameters.h" #include "sgml.h" @@ -27,248 +29,326 @@ #include "support/lstrings.h" #include "support/lyxlib.h" -#include "support/tostr.h" +#include "support/convert.h" +#include "support/types.h" -#include -#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 environment_stack(10); - vector environment_inner(10); - vector 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(paragraphs).begin(); - ParagraphList::iterator pend = const_cast(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 = 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().find('#') != string::npos) { - counters.step(style->counter); - } - // 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)) { - InsetBase * inset = par->getInset(0); - if (inset->lyxCode() == InsetOld::LABEL_CODE) { - command_name += " id=\""; - command_name += (static_cast(inset))->getContents(); - command_name += '"'; - labelid = true; - } +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 << "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); } - if (!labelid && !style->latexparam().empty()) { - ls = style->latexparam(); - if (ls.find('#') != string::npos) { - string el = expandLabel(buf.params().getLyXTextClass(), - style, false); - ls = subst(ls, "#", el); - } + 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. 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