From 95d8934808225f9d30a372ac9ad8d9b76b1bb2a1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Matox?= Date: Thu, 30 Oct 2003 08:47:16 +0000 Subject: [PATCH] factorise linuxdoc and docbook output code git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8005 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/ChangeLog | 9 + src/buffer.C | 662 +---------------------------------------- src/buffer.h | 9 - src/insets/ChangeLog | 4 + src/insets/insettext.C | 149 +--------- src/paragraph.C | 348 ++++++++++++++++++++++ src/paragraph.h | 13 + src/paragraph_funcs.C | 347 ++++++++++++++++++++- src/paragraph_funcs.h | 8 + 9 files changed, 733 insertions(+), 816 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index c8a6f8be5a..459a3fa9b0 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2003-10-30 José Matos + + * buffer.C (makeLinuxDocFile, makeDocBookFile): + * paragraph_funcs.[Ch] (linuxdocParagraphs, docbookParagraphs): + factorise code for paragraph output. + * buffer.[Ch]: + * paragraph.[Ch] (simpleLinuxDocOnePar, simpleDocBookOnePar): + move functions. + 2003-10-29 Lars Gullik Bjønnes * text3.C (dispatch): diff --git a/src/buffer.C b/src/buffer.C index 3e903d4a8f..a901e24e57 100644 --- a/src/buffer.C +++ b/src/buffer.C @@ -60,7 +60,6 @@ #include "support/tostr.h" #include -#include #include "support/std_sstream.h" @@ -115,7 +114,6 @@ using std::for_each; using std::make_pair; using std::ifstream; -using std::list; using std::ios; using std::ostream; using std::ostringstream; @@ -1309,127 +1307,7 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only) << " created this file. For more info see http://www.lyx.org/" << " -->\n"; - Paragraph::depth_type depth = 0; // paragraph depth - string item_name; - vector environment_stack(5); - - ParagraphList::iterator pit = paragraphs().begin(); - ParagraphList::iterator pend = paragraphs().end(); - for (; pit != pend; ++pit) { - LyXLayout_ptr const & style = pit->layout(); - // treat as a special case for compatibility with old code - if (pit->isInset(0)) { - InsetOld * inset = pit->getInset(0); - InsetOld::Code lyx_code = inset->lyxCode(); - if (lyx_code == InsetOld::TOC_CODE) { - string const temp = "toc"; - sgml::openTag(ofs, depth, false, temp); - continue; - } - } - - // environment tag closing - for (; depth > pit->params().depth(); --depth) { - sgml::closeTag(ofs, depth, false, environment_stack[depth]); - environment_stack[depth].erase(); - } - - // write opening SGML tags - switch (style->latextype) { - case LATEX_PARAGRAPH: - if (depth == pit->params().depth() - && !environment_stack[depth].empty()) { - sgml::closeTag(ofs, depth, false, environment_stack[depth]); - environment_stack[depth].erase(); - if (depth) - --depth; - else - ofs << "

"; - } - sgml::openTag(ofs, depth, false, style->latexname()); - break; - - case LATEX_COMMAND: - if (depth != 0) - error(ErrorItem(_("Error:"), _("Wrong depth for LatexType Command.\n"), pit->id(), 0, pit->size())); - - if (!environment_stack[depth].empty()) { - sgml::closeTag(ofs, depth, false, environment_stack[depth]); - ofs << "

"; - } - - environment_stack[depth].erase(); - sgml::openTag(ofs, depth, false, style->latexname()); - break; - - case LATEX_ENVIRONMENT: - case LATEX_ITEM_ENVIRONMENT: - case LATEX_BIB_ENVIRONMENT: - { - string const & latexname = style->latexname(); - - if (depth == pit->params().depth() - && environment_stack[depth] != latexname) { - sgml::closeTag(ofs, depth, false, - environment_stack[depth]); - environment_stack[depth].erase(); - } - if (depth < pit->params().depth()) { - depth = pit->params().depth(); - environment_stack[depth].erase(); - } - if (environment_stack[depth] != latexname) { - if (depth == 0) { - sgml::openTag(ofs, depth, false, "p"); - } - sgml::openTag(ofs, depth, false, latexname); - - if (environment_stack.size() == depth + 1) - environment_stack.push_back("!-- --"); - environment_stack[depth] = latexname; - } - - if (style->latexparam() == "CDATA") - ofs << "latextype == LATEX_ENVIRONMENT) break; - - if (style->labeltype == LABEL_MANUAL) - item_name = "tag"; - else - item_name = "item"; - - sgml::openTag(ofs, depth + 1, false, item_name); - } - break; - - default: - sgml::openTag(ofs, depth, false, style->latexname()); - break; - } - - simpleLinuxDocOnePar(ofs, pit, depth); - - ofs << "\n"; - // write closing SGML tags - switch (style->latextype) { - case LATEX_COMMAND: - break; - case LATEX_ENVIRONMENT: - case LATEX_ITEM_ENVIRONMENT: - case LATEX_BIB_ENVIRONMENT: - if (style->latexparam() == "CDATA") - ofs << "]]>"; - break; - default: - sgml::closeTag(ofs, depth, false, style->latexname()); - break; - } - } - - // Close open tags - for (int i = depth; i >= 0; --i) - sgml::closeTag(ofs, depth, false, environment_stack[i]); + linuxdocParagraphs(*this, paragraphs(), ofs); if (!body_only) { ofs << "\n\n"; @@ -1444,255 +1322,6 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only) } -// checks, if newcol chars should be put into this line -// writes newline, if necessary. -namespace { - -void sgmlLineBreak(ostream & os, string::size_type & colcount, - string::size_type newcol) -{ - colcount += newcol; - if (colcount > lyxrc.ascii_linelen) { - os << "\n"; - colcount = newcol; // assume write after this call - } -} - -enum PAR_TAG { - NONE=0, - TT = 1, - SF = 2, - BF = 4, - IT = 8, - SL = 16, - EM = 32 -}; - - -string tag_name(PAR_TAG const & pt) { - switch (pt) { - case NONE: return "!-- --"; - case TT: return "tt"; - case SF: return "sf"; - case BF: return "bf"; - case IT: return "it"; - case SL: return "sl"; - case EM: return "em"; - } - return ""; -} - - -inline -void operator|=(PAR_TAG & p1, PAR_TAG const & p2) -{ - p1 = static_cast(p1 | p2); -} - - -inline -void reset(PAR_TAG & p1, PAR_TAG const & p2) -{ - p1 = static_cast(p1 & ~p2); -} - -} // anon - - -// Handle internal paragraph parsing -- layout already processed. -void Buffer::simpleLinuxDocOnePar(ostream & os, - ParagraphList::iterator par, - lyx::depth_type /*depth*/) const -{ - LyXLayout_ptr const & style = par->layout(); - - string::size_type char_line_count = 5; // Heuristic choice ;-) - - // gets paragraph main font - LyXFont font_old; - bool desc_on; - if (style->labeltype == LABEL_MANUAL) { - font_old = style->labelfont; - desc_on = true; - } else { - font_old = style->font; - desc_on = false; - } - - LyXFont::FONT_FAMILY family_type = LyXFont::ROMAN_FAMILY; - LyXFont::FONT_SERIES series_type = LyXFont::MEDIUM_SERIES; - LyXFont::FONT_SHAPE shape_type = LyXFont::UP_SHAPE; - bool is_em = false; - - stack tag_state; - // parsing main loop - for (pos_type i = 0; i < par->size(); ++i) { - - PAR_TAG tag_close = NONE; - list < PAR_TAG > tag_open; - - LyXFont const font = par->getFont(params(), i, outerFont(par, paragraphs())); - - if (font_old.family() != font.family()) { - switch (family_type) { - case LyXFont::SANS_FAMILY: - tag_close |= SF; - break; - case LyXFont::TYPEWRITER_FAMILY: - tag_close |= TT; - break; - default: - break; - } - - family_type = font.family(); - - switch (family_type) { - case LyXFont::SANS_FAMILY: - tag_open.push_back(SF); - break; - case LyXFont::TYPEWRITER_FAMILY: - tag_open.push_back(TT); - break; - default: - break; - } - } - - if (font_old.series() != font.series()) { - switch (series_type) { - case LyXFont::BOLD_SERIES: - tag_close |= BF; - break; - default: - break; - } - - series_type = font.series(); - - switch (series_type) { - case LyXFont::BOLD_SERIES: - tag_open.push_back(BF); - break; - default: - break; - } - - } - - if (font_old.shape() != font.shape()) { - switch (shape_type) { - case LyXFont::ITALIC_SHAPE: - tag_close |= IT; - break; - case LyXFont::SLANTED_SHAPE: - tag_close |= SL; - break; - default: - break; - } - - shape_type = font.shape(); - - switch (shape_type) { - case LyXFont::ITALIC_SHAPE: - tag_open.push_back(IT); - break; - case LyXFont::SLANTED_SHAPE: - tag_open.push_back(SL); - break; - default: - break; - } - } - // handle tag - if (font_old.emph() != font.emph()) { - if (font.emph() == LyXFont::ON) { - tag_open.push_back(EM); - is_em = true; - } - else if (is_em) { - tag_close |= EM; - is_em = false; - } - } - - list < PAR_TAG > temp; - while (!tag_state.empty() && tag_close) { - PAR_TAG k = tag_state.top(); - tag_state.pop(); - os << "'; - if (tag_close & k) - reset(tag_close,k); - else - temp.push_back(k); - } - - for(list< PAR_TAG >::const_iterator j = temp.begin(); - j != temp.end(); ++j) { - tag_state.push(*j); - os << '<' << tag_name(*j) << '>'; - } - - for(list< PAR_TAG >::const_iterator j = tag_open.begin(); - j != tag_open.end(); ++j) { - tag_state.push(*j); - os << '<' << tag_name(*j) << '>'; - } - - char c = par->getChar(i); - - if (c == Paragraph::META_INSET) { - InsetOld * inset = par->getInset(i); - inset->linuxdoc(*this, os); - font_old = font; - continue; - } - - if (style->latexparam() == "CDATA") { - // "TeX"-Mode on == > SGML-Mode on. - if (c != '\0') - os << c; - ++char_line_count; - } else { - bool ws; - string str; - boost::tie(ws, str) = sgml::escapeChar(c); - if (ws && !par->isFreeSpacing()) { - // in freespacing mode, spaces are - // non-breaking characters - if (desc_on) {// if char is ' ' then... - - ++char_line_count; - sgmlLineBreak(os, char_line_count, 6); - os << ""; - desc_on = false; - } else { - sgmlLineBreak(os, char_line_count, 1); - os << c; - } - } else { - os << str; - char_line_count += str.length(); - } - } - font_old = font; - } - - while (!tag_state.empty()) { - os << "'; - tag_state.pop(); - } - - // resets description flag correctly - if (desc_on) { - // not closed... - sgmlLineBreak(os, char_line_count, 6); - os << ""; - } -} - - void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body) { ofstream ofs; @@ -1739,207 +1368,7 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body) ofs << "\n"; - 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 - - string item_name; - string command_name; - - ParagraphList::iterator par = paragraphs().begin(); - ParagraphList::iterator pend = paragraphs().end(); - - for (; par != pend; ++par) { - string sgmlparam; - string c_depth; - string c_params; - int desc_on = 0; // description mode - - LyXLayout_ptr const & style = par->layout(); - - // environment tag closing - for (; depth > par->params().depth(); --depth) { - if (!environment_inner[depth].empty()) - sgml::closeEnvTags(ofs, false, environment_inner[depth], - command_depth + depth); - sgml::closeTag(ofs, depth + command_depth, false, environment_stack[depth]); - environment_stack[depth].erase(); - environment_inner[depth].erase(); - } - - if (depth == par->params().depth() - && environment_stack[depth] != style->latexname() - && !environment_stack[depth].empty()) { - sgml::closeEnvTags(ofs, false, environment_inner[depth], - command_depth + depth); - sgml::closeTag(ofs, depth + command_depth, false, environment_stack[depth]); - - environment_stack[depth].erase(); - environment_inner[depth].erase(); - } - - // Write opening SGML tags. - switch (style->latextype) { - case LATEX_PARAGRAPH: - sgml::openTag(ofs, depth + command_depth, - false, style->latexname()); - break; - - case LATEX_COMMAND: - if (depth != 0) - error(ErrorItem(_("Error"), _("Wrong depth for LatexType Command."), par->id(), 0, par->size())); - - command_name = style->latexname(); - - sgmlparam = style->latexparam(); - c_params = split(sgmlparam, c_depth,'|'); - - cmd_depth = atoi(c_depth); - - if (command_flag) { - if (cmd_depth < command_base) { - for (Paragraph::depth_type j = command_depth; - j >= command_base; --j) { - sgml::closeTag(ofs, j, false, command_stack[j]); - ofs << 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(ofs, j, false, command_stack[j]); - ofs << 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; - - // 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->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(inset))->getContents(); - command_name += '"'; - desc_on = 3; - } - } - - sgml::openTag(ofs, depth + command_depth, false, command_name); - - item_name = c_params.empty() ? "title" : c_params; - sgml::openTag(ofs, depth + 1 + command_depth, false, item_name); - break; - - case LATEX_ENVIRONMENT: - case LATEX_ITEM_ENVIRONMENT: - if (depth < par->params().depth()) { - depth = par->params().depth(); - environment_stack[depth].erase(); - } - - 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] = "!-- --"; - sgml::openTag(ofs, depth + command_depth, false, environment_stack[depth]); - } else { - sgml::closeEnvTags(ofs, false, environment_inner[depth], - command_depth + depth); - } - - if (style->latextype == LATEX_ENVIRONMENT) { - if (!style->latexparam().empty()) { - if (style->latexparam() == "CDATA") - ofs << "latexparam()); - } - break; - } - - desc_on = (style->labeltype == LABEL_MANUAL); - - environment_inner[depth] = desc_on ? "varlistentry" : "listitem"; - sgml::openTag(ofs, depth + 1 + command_depth, - false, environment_inner[depth]); - - item_name = desc_on ? "term" : "para"; - sgml::openTag(ofs, depth + 1 + command_depth, - false, item_name); - break; - default: - sgml::openTag(ofs, depth + command_depth, - false, style->latexname()); - break; - } - - simpleDocBookOnePar(ofs, par, desc_on, - depth + 1 + command_depth); - - string end_tag; - // write closing SGML tags - switch (style->latextype) { - case LATEX_COMMAND: - end_tag = c_params.empty() ? "title" : c_params; - sgml::closeTag(ofs, depth + command_depth, - false, end_tag); - break; - case LATEX_ENVIRONMENT: - if (!style->latexparam().empty()) { - if (style->latexparam() == "CDATA") - ofs << "]]>"; - else - sgml::closeTag(ofs, depth + command_depth, false, style->latexparam()); - } - break; - case LATEX_ITEM_ENVIRONMENT: - if (desc_on == 1) break; - end_tag = "para"; - sgml::closeTag(ofs, depth + 1 + command_depth, false, end_tag); - break; - case LATEX_PARAGRAPH: - sgml::closeTag(ofs, depth + command_depth, false, style->latexname()); - break; - default: - sgml::closeTag(ofs, depth + command_depth, false, style->latexname()); - break; - } - } - - // Close open tags - for (int d = depth; d >= 0; --d) { - if (!environment_stack[depth].empty()) { - sgml::closeEnvTags(ofs, false, environment_inner[depth], - command_depth + depth); - } - } - - for (int j = command_depth; j >= 0 ; --j) - if (!command_stack[j].empty()) { - sgml::closeTag(ofs, j, false, command_stack[j]); - ofs << endl; - } + docbookParagraphs(*this, paragraphs(), ofs); ofs << "\n\n"; sgml::closeTag(ofs, 0, false, top_element); @@ -1952,93 +1381,6 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body) } -void Buffer::simpleDocBookOnePar(ostream & os, - ParagraphList::iterator par, int & desc_on, - lyx::depth_type depth) const -{ - bool emph_flag = false; - - LyXLayout_ptr const & style = par->layout(); - - LyXFont font_old = (style->labeltype == LABEL_MANUAL ? style->labelfont : style->font); - - int char_line_count = depth; - //if (!style.free_spacing) - // os << string(depth,' '); - - // parsing main loop - for (pos_type i = 0; i < par->size(); ++i) { - LyXFont font = par->getFont(params(), i, outerFont(par, paragraphs())); - - // handle tag - if (font_old.emph() != font.emph()) { - if (font.emph() == LyXFont::ON) { - if (style->latexparam() == "CDATA") - os << "]]>"; - os << ""; - if (style->latexparam() == "CDATA") - os << "latexparam() == "CDATA") - os << "]]>"; - os << ""; - if (style->latexparam() == "CDATA") - os << "isInset(i)) { - InsetOld * inset = par->getInset(i); - // don't print the inset in position 0 if desc_on == 3 (label) - if (i || desc_on != 3) { - if (style->latexparam() == "CDATA") - os << "]]>"; - inset->docbook(*this, os, false); - if (style->latexparam() == "CDATA") - os << "getChar(i); - bool ws; - string str; - boost::tie(ws, str) = sgml::escapeChar(c); - - if (style->pass_thru) { - os << c; - } else if (par->isFreeSpacing() || c != ' ') { - os << str; - } else if (desc_on == 1) { - ++char_line_count; - os << "\n"; - desc_on = 2; - } else { - os << ' '; - } - } - font_old = font; - } - - if (emph_flag) { - if (style->latexparam() == "CDATA") - os << "]]>"; - os << ""; - if (style->latexparam() == "CDATA") - os << " not closed... - os << "\n "; - } - if (style->free_spacing) - os << '\n'; -} - - // chktex should be run with these flags disabled: 3, 22, 25, 30, 38(?) // Other flags: -wall -v0 -x int Buffer::runChktex() diff --git a/src/buffer.h b/src/buffer.h index ed55785301..27690c0ad8 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -153,15 +153,6 @@ public: bool output_preamble = true, bool output_body = true); /// - void simpleDocBookOnePar(std::ostream &, - ParagraphList::iterator par, - int & desc_on, - lyx::depth_type depth) const; - /// - void simpleLinuxDocOnePar(std::ostream & os, - ParagraphList::iterator par, - lyx::depth_type depth) const; - /// void makeLinuxDocFile(std::string const & filename, bool nice, bool only_body = false); /// diff --git a/src/insets/ChangeLog b/src/insets/ChangeLog index 1b063edbac..5f30c10f5a 100644 --- a/src/insets/ChangeLog +++ b/src/insets/ChangeLog @@ -1,3 +1,7 @@ +2003-10-30 José Matos + + * insettext.C (linuxdoc, docbook): use new pagraph generation code. + 2003-10-29 Lars Gullik Bjønnes * updatableinset.C (priv_dispatch): diff --git a/src/insets/insettext.C b/src/insets/insettext.C index 570bfd30c3..ab439668f0 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -952,158 +952,15 @@ int InsetText::ascii(Buffer const & buf, ostream & os, int linelen) const int InsetText::linuxdoc(Buffer const & buf, ostream & os) const { - ParagraphList::iterator pit = const_cast(paragraphs).begin(); - ParagraphList::iterator pend = const_cast(paragraphs).end(); - - // There is a confusion between the empty paragraph and the default paragraph - // The default paragraph is

, the empty paragraph is *empty* - // Since none of the floats of linuxdoc accepts standard paragraphs - // I disable them. I don't expect problems. (jamatos 2003/07/27) - for (; pit != pend; ++pit) { - const string name = pit->layout()->latexname(); - if (name != "p") - sgml::openTag(os, 1, 0, name); - buf.simpleLinuxDocOnePar(os, pit, 0); - if (name != "p") - sgml::closeTag(os, 1, 0, name); - } + linuxdocParagraphs(buf, paragraphs, os); return 0; } int InsetText::docbook(Buffer const & buf, ostream & os, bool mixcont) const { - unsigned int lines = 0; - - vector environment_stack(10); - vector environment_inner(10); - - int const command_depth = 0; - string item_name; - - Paragraph::depth_type depth = 0; // paragraph depth - - ParagraphList::iterator pit = const_cast(paragraphs).begin(); - ParagraphList::iterator pend = const_cast(paragraphs).end(); - - for (; pit != pend; ++pit) { - int desc_on = 0; // description mode - - LyXLayout_ptr const & style = pit->layout(); - - // environment tag closing - for (; depth > pit->params().depth(); --depth) { - lines += sgml::closeEnvTags(os, mixcont, environment_inner[depth], - command_depth + depth); - lines += sgml::closeTag(os, depth + command_depth, mixcont, environment_stack[depth]); - environment_stack[depth].erase(); - environment_inner[depth].erase(); - } - - if (depth == pit->params().depth() - && environment_stack[depth] != style->latexname() - && !environment_stack[depth].empty()) { - lines += sgml::closeEnvTags(os, mixcont, environment_inner[depth], - command_depth + depth); - lines += sgml::closeTag(os, depth + command_depth, mixcont, environment_stack[depth]); - - environment_stack[depth].erase(); - environment_inner[depth].erase(); - } - - // Write opening SGML tags. - switch (style->latextype) { - case LATEX_PARAGRAPH: - lines += sgml::openTag(os, depth + command_depth, mixcont, style->latexname()); - break; - - case LATEX_COMMAND: - buf.error(ErrorItem(_("Error"), _("LatexType Command not allowed here.\n"), pit->id(), 0, pit->size())); - return -1; - break; - - case LATEX_ENVIRONMENT: - case LATEX_ITEM_ENVIRONMENT: - if (depth < pit->params().depth()) { - depth = pit->params().depth(); - environment_stack[depth].erase(); - } - - 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] = "!-- --"; - lines += sgml::openTag(os, depth + command_depth, mixcont, environment_stack[depth]); - } else { - lines += sgml::closeEnvTags(os, mixcont, environment_inner[depth], - command_depth + depth); - } - - if (style->latextype == LATEX_ENVIRONMENT) { - if (!style->latexparam().empty()) { - if (style->latexparam() == "CDATA") - os << "latexparam()); - } - break; - } - - desc_on = (style->labeltype == LABEL_MANUAL); - - environment_inner[depth] = desc_on ? "varlistentry" : "listitem"; - lines += sgml::openTag(os, depth + 1 + command_depth, mixcont, environment_inner[depth]); - - item_name = desc_on ? "term" : "para"; - lines += sgml::openTag(os, depth + 1 + command_depth, mixcont, item_name); - - break; - default: - lines += sgml::openTag(os, depth + command_depth, mixcont, style->latexname()); - break; - } - - buf.simpleDocBookOnePar(os, pit, desc_on, depth + 1 + command_depth); - - string end_tag; - // write closing SGML tags - switch (style->latextype) { - case LATEX_ENVIRONMENT: - if (!style->latexparam().empty()) { - if (style->latexparam() == "CDATA") - os << "]]>"; - else - lines += sgml::closeTag(os, depth + command_depth, mixcont, style->latexparam()); - } - break; - case LATEX_ITEM_ENVIRONMENT: - if (desc_on == 1) - break; - end_tag= "para"; - lines += sgml::closeTag(os, depth + 1 + command_depth, mixcont, end_tag); - break; - case LATEX_PARAGRAPH: - lines += sgml::closeTag(os, depth + command_depth, mixcont, style->latexname()); - break; - default: - lines += sgml::closeTag(os, depth + command_depth, mixcont, style->latexname()); - break; - } - } - - // Close open tags - for (int d = depth; d >= 0; --d) { - if (!environment_stack[depth].empty()) { - lines += sgml::closeEnvTags(os, mixcont, environment_inner[depth], - command_depth + depth); - lines += sgml::closeTag(os, depth + command_depth, mixcont, environment_stack[depth]); - } - } - - return lines; + docbookParagraphs(buf, paragraphs, os); + return 0; } diff --git a/src/paragraph.C b/src/paragraph.C index a680813224..6e5d98b949 100644 --- a/src/paragraph.C +++ b/src/paragraph.C @@ -30,6 +30,8 @@ #include "lyxfont.h" #include "lyxrc.h" #include "lyxrow.h" +#include "paragraph_funcs.h" +#include "sgml.h" #include "texrow.h" #include "vspace.h" @@ -40,12 +42,19 @@ #include "support/textutils.h" #include "support/std_sstream.h" +#include + +#include +#include + using lyx::pos_type; using lyx::support::contains; using lyx::support::subst; using std::endl; +using std::list; +using std::stack; using std::string; using std::ostream; using std::ostringstream; @@ -1056,6 +1065,345 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, } +namespace { + +// checks, if newcol chars should be put into this line +// writes newline, if necessary. +void sgmlLineBreak(ostream & os, string::size_type & colcount, + string::size_type newcol) +{ + colcount += newcol; + if (colcount > lyxrc.ascii_linelen) { + os << "\n"; + colcount = newcol; // assume write after this call + } +} + +enum PAR_TAG { + NONE=0, + TT = 1, + SF = 2, + BF = 4, + IT = 8, + SL = 16, + EM = 32 +}; + + +string tag_name(PAR_TAG const & pt) { + switch (pt) { + case NONE: return "!-- --"; + case TT: return "tt"; + case SF: return "sf"; + case BF: return "bf"; + case IT: return "it"; + case SL: return "sl"; + case EM: return "em"; + } + return ""; +} + + +inline +void operator|=(PAR_TAG & p1, PAR_TAG const & p2) +{ + p1 = static_cast(p1 | p2); +} + + +inline +void reset(PAR_TAG & p1, PAR_TAG const & p2) +{ + p1 = static_cast(p1 & ~p2); +} + +} // anon + + +// Handle internal paragraph parsing -- layout already processed. +void Paragraph::simpleLinuxDocOnePar(Buffer const & buf, + ostream & os, + LyXFont const & outerfont, + lyx::depth_type /*depth*/) const +{ + LyXLayout_ptr const & style = layout(); + + string::size_type char_line_count = 5; // Heuristic choice ;-) + + // gets paragraph main font + LyXFont font_old; + bool desc_on; + if (style->labeltype == LABEL_MANUAL) { + font_old = style->labelfont; + desc_on = true; + } else { + font_old = style->font; + desc_on = false; + } + + LyXFont::FONT_FAMILY family_type = LyXFont::ROMAN_FAMILY; + LyXFont::FONT_SERIES series_type = LyXFont::MEDIUM_SERIES; + LyXFont::FONT_SHAPE shape_type = LyXFont::UP_SHAPE; + bool is_em = false; + + stack tag_state; + // parsing main loop + for (pos_type i = 0; i < size(); ++i) { + + PAR_TAG tag_close = NONE; + list < PAR_TAG > tag_open; + + LyXFont const font = getFont(buf.params(), i, outerfont); + + if (font_old.family() != font.family()) { + switch (family_type) { + case LyXFont::SANS_FAMILY: + tag_close |= SF; + break; + case LyXFont::TYPEWRITER_FAMILY: + tag_close |= TT; + break; + default: + break; + } + + family_type = font.family(); + + switch (family_type) { + case LyXFont::SANS_FAMILY: + tag_open.push_back(SF); + break; + case LyXFont::TYPEWRITER_FAMILY: + tag_open.push_back(TT); + break; + default: + break; + } + } + + if (font_old.series() != font.series()) { + switch (series_type) { + case LyXFont::BOLD_SERIES: + tag_close |= BF; + break; + default: + break; + } + + series_type = font.series(); + + switch (series_type) { + case LyXFont::BOLD_SERIES: + tag_open.push_back(BF); + break; + default: + break; + } + + } + + if (font_old.shape() != font.shape()) { + switch (shape_type) { + case LyXFont::ITALIC_SHAPE: + tag_close |= IT; + break; + case LyXFont::SLANTED_SHAPE: + tag_close |= SL; + break; + default: + break; + } + + shape_type = font.shape(); + + switch (shape_type) { + case LyXFont::ITALIC_SHAPE: + tag_open.push_back(IT); + break; + case LyXFont::SLANTED_SHAPE: + tag_open.push_back(SL); + break; + default: + break; + } + } + // handle tag + if (font_old.emph() != font.emph()) { + if (font.emph() == LyXFont::ON) { + tag_open.push_back(EM); + is_em = true; + } + else if (is_em) { + tag_close |= EM; + is_em = false; + } + } + + list < PAR_TAG > temp; + while (!tag_state.empty() && tag_close) { + PAR_TAG k = tag_state.top(); + tag_state.pop(); + os << "'; + if (tag_close & k) + reset(tag_close,k); + else + temp.push_back(k); + } + + for(list< PAR_TAG >::const_iterator j = temp.begin(); + j != temp.end(); ++j) { + tag_state.push(*j); + os << '<' << tag_name(*j) << '>'; + } + + for(list< PAR_TAG >::const_iterator j = tag_open.begin(); + j != tag_open.end(); ++j) { + tag_state.push(*j); + os << '<' << tag_name(*j) << '>'; + } + + char c = getChar(i); + + if (c == Paragraph::META_INSET) { + InsetOld const * inset = getInset(i); + inset->linuxdoc(buf, os); + font_old = font; + continue; + } + + if (style->latexparam() == "CDATA") { + // "TeX"-Mode on == > SGML-Mode on. + if (c != '\0') + os << c; + ++char_line_count; + } else { + bool ws; + string str; + boost::tie(ws, str) = sgml::escapeChar(c); + if (ws && !isFreeSpacing()) { + // in freespacing mode, spaces are + // non-breaking characters + if (desc_on) {// if char is ' ' then... + + ++char_line_count; + sgmlLineBreak(os, char_line_count, 6); + os << ""; + desc_on = false; + } else { + sgmlLineBreak(os, char_line_count, 1); + os << c; + } + } else { + os << str; + char_line_count += str.length(); + } + } + font_old = font; + } + + while (!tag_state.empty()) { + os << "'; + tag_state.pop(); + } + + // resets description flag correctly + if (desc_on) { + // not closed... + sgmlLineBreak(os, char_line_count, 6); + os << ""; + } +} + + +void Paragraph::simpleDocBookOnePar(Buffer const & buf, + ostream & os, + LyXFont const & outerfont, + int & desc_on, + lyx::depth_type depth) const +{ + bool emph_flag = false; + + LyXLayout_ptr const & style = layout(); + + LyXFont font_old = (style->labeltype == LABEL_MANUAL ? style->labelfont : style->font); + + int char_line_count = depth; + //if (!style.free_spacing) + // os << string(depth,' '); + + // parsing main loop + for (pos_type i = 0; i < size(); ++i) { + LyXFont font = getFont(buf.params(), i, outerfont); + + // handle tag + if (font_old.emph() != font.emph()) { + if (font.emph() == LyXFont::ON) { + if (style->latexparam() == "CDATA") + os << "]]>"; + os << ""; + if (style->latexparam() == "CDATA") + os << "latexparam() == "CDATA") + os << "]]>"; + os << ""; + if (style->latexparam() == "CDATA") + os << "latexparam() == "CDATA") + os << "]]>"; + inset->docbook(buf, os, false); + if (style->latexparam() == "CDATA") + os << "pass_thru) { + os << c; + } else if (isFreeSpacing() || c != ' ') { + os << str; + } else if (desc_on == 1) { + ++char_line_count; + os << "\n"; + desc_on = 2; + } else { + os << ' '; + } + } + font_old = font; + } + + if (emph_flag) { + if (style->latexparam() == "CDATA") + os << "]]>"; + os << ""; + if (style->latexparam() == "CDATA") + os << " not closed... + os << "\n "; + } + if (style->free_spacing) + os << '\n'; +} + + namespace { /// return true if the char is a meta-character for an inset diff --git a/src/paragraph.h b/src/paragraph.h index c2a02b29fb..c35b5f75b0 100644 --- a/src/paragraph.h +++ b/src/paragraph.h @@ -106,6 +106,19 @@ public: LyXFont const & outerfont, std::ostream &, TexRow & texrow, LatexRunParams const &); + /// + void simpleLinuxDocOnePar(Buffer const & buf, + std::ostream & os, + LyXFont const & outerfont, + lyx::depth_type depth) const; + + /// + void simpleDocBookOnePar(Buffer const & buf, + std::ostream &, + LyXFont const & outerfont, + int & desc_on, + lyx::depth_type depth) const; + /// bool hasSameLayout(Paragraph const & par) const; diff --git a/src/paragraph_funcs.C b/src/paragraph_funcs.C index eb80ac50fb..5048bfa063 100644 --- a/src/paragraph_funcs.C +++ b/src/paragraph_funcs.C @@ -25,6 +25,7 @@ #include "lyxlex.h" #include "lyxrc.h" #include "paragraph_pimpl.h" +#include "sgml.h" #include "texrow.h" #include "vspace.h" @@ -39,20 +40,26 @@ #include "insets/insetspecialchar.h" #include "insets/insettabular.h" +#include "support/filetools.h" #include "support/lstrings.h" +#include "support/lyxlib.h" #include "support/std_sstream.h" +#include + using lyx::pos_type; +using lyx::support::atoi; using lyx::support::bformat; +using lyx::support::split; using lyx::support::subst; using std::endl; using std::string; +using std::vector; using std::istringstream; using std::ostream; - extern string bibitemWidest(Buffer const &); @@ -787,6 +794,344 @@ void latexParagraphs(Buffer const & buf, } +void linuxdocParagraphs(Buffer const & buf, + ParagraphList const & paragraphs, + ostream & os) +{ + + Paragraph::depth_type depth = 0; // paragraph depth + string item_name; + vector environment_stack(5); + + ParagraphList::iterator pit = const_cast(paragraphs).begin(); + ParagraphList::iterator pend = const_cast(paragraphs).end(); + for (; pit != pend; ++pit) { + LyXLayout_ptr const & style = pit->layout(); + // treat as a special case for compatibility with old code + if (pit->isInset(0)) { + InsetOld * inset = pit->getInset(0); + InsetOld::Code lyx_code = inset->lyxCode(); + if (lyx_code == InsetOld::TOC_CODE) { + string const temp = "toc"; + sgml::openTag(os, depth, false, temp); + continue; + } + } + + // environment tag closing + for (; depth > pit->params().depth(); --depth) { + sgml::closeTag(os, depth, false, environment_stack[depth]); + environment_stack[depth].erase(); + } + + // write opening SGML tags + switch (style->latextype) { + case LATEX_PARAGRAPH: + if (depth == pit->params().depth() + && !environment_stack[depth].empty()) { + sgml::closeTag(os, depth, false, environment_stack[depth]); + environment_stack[depth].erase(); + if (depth) + --depth; + else + os << "

"; + } + sgml::openTag(os, depth, false, style->latexname()); + break; + + case LATEX_COMMAND: + if (depth != 0) + //error(ErrorItem(_("Error:"), _("Wrong depth for LatexType Command.\n"), pit->id(), 0, pit->size())); + ; + + if (!environment_stack[depth].empty()) { + sgml::closeTag(os, depth, false, environment_stack[depth]); + os << "

"; + } + + environment_stack[depth].erase(); + sgml::openTag(os, depth, false, style->latexname()); + break; + + case LATEX_ENVIRONMENT: + case LATEX_ITEM_ENVIRONMENT: + case LATEX_BIB_ENVIRONMENT: + { + string const & latexname = style->latexname(); + + if (depth == pit->params().depth() + && environment_stack[depth] != latexname) { + sgml::closeTag(os, depth, false, + environment_stack[depth]); + environment_stack[depth].erase(); + } + if (depth < pit->params().depth()) { + depth = pit->params().depth(); + environment_stack[depth].erase(); + } + if (environment_stack[depth] != latexname) { + if (depth == 0) { + sgml::openTag(os, depth, false, "p"); + } + sgml::openTag(os, depth, false, latexname); + + if (environment_stack.size() == depth + 1) + environment_stack.push_back("!-- --"); + environment_stack[depth] = latexname; + } + + if (style->latexparam() == "CDATA") + os << "latextype == LATEX_ENVIRONMENT) break; + + if (style->labeltype == LABEL_MANUAL) + item_name = "tag"; + else + item_name = "item"; + + sgml::openTag(os, depth + 1, false, item_name); + } + break; + + default: + sgml::openTag(os, depth, false, style->latexname()); + break; + } + + pit->simpleLinuxDocOnePar(buf, os, outerFont(pit, paragraphs), depth); + + os << "\n"; + // write closing SGML tags + switch (style->latextype) { + case LATEX_COMMAND: + break; + case LATEX_ENVIRONMENT: + case LATEX_ITEM_ENVIRONMENT: + case LATEX_BIB_ENVIRONMENT: + if (style->latexparam() == "CDATA") + os << "]]>"; + break; + default: + sgml::closeTag(os, depth, false, style->latexname()); + break; + } + } + + // Close open tags + for (int i = depth; i >= 0; --i) + sgml::closeTag(os, depth, false, environment_stack[i]); +} + + +void docbookParagraphs(Buffer const & buf, + ParagraphList const & paragraphs, + ostream & os) +{ + 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 + + string item_name; + string command_name; + + ParagraphList::iterator par = const_cast(paragraphs).begin(); + ParagraphList::iterator pend = const_cast(paragraphs).end(); + + for (; par != pend; ++par) { + string sgmlparam; + string c_depth; + string c_params; + int desc_on = 0; // description mode + + LyXLayout_ptr const & style = par->layout(); + + // environment tag closing + for (; depth > par->params().depth(); --depth) { + if (!environment_inner[depth].empty()) + sgml::closeEnvTags(os, false, environment_inner[depth], + command_depth + depth); + sgml::closeTag(os, depth + command_depth, false, environment_stack[depth]); + environment_stack[depth].erase(); + environment_inner[depth].erase(); + } + + if (depth == par->params().depth() + && environment_stack[depth] != style->latexname() + && !environment_stack[depth].empty()) { + sgml::closeEnvTags(os, false, environment_inner[depth], + command_depth + depth); + sgml::closeTag(os, depth + command_depth, false, environment_stack[depth]); + + environment_stack[depth].erase(); + environment_inner[depth].erase(); + } + + // Write opening SGML tags. + switch (style->latextype) { + case LATEX_PARAGRAPH: + sgml::openTag(os, depth + command_depth, + false, style->latexname()); + break; + + case LATEX_COMMAND: + if (depth != 0) + //error(ErrorItem(_("Error"), _("Wrong depth for LatexType Command."), par->id(), 0, par->size())); + ; + + command_name = style->latexname(); + + sgmlparam = style->latexparam(); + c_params = split(sgmlparam, c_depth,'|'); + + cmd_depth = atoi(c_depth); + + 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; + + // 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->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(inset))->getContents(); + command_name += '"'; + desc_on = 3; + } + } + + sgml::openTag(os, depth + command_depth, false, command_name); + + item_name = c_params.empty() ? "title" : c_params; + sgml::openTag(os, depth + 1 + command_depth, false, item_name); + break; + + case LATEX_ENVIRONMENT: + case LATEX_ITEM_ENVIRONMENT: + if (depth < par->params().depth()) { + depth = par->params().depth(); + environment_stack[depth].erase(); + } + + 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] = "!-- --"; + sgml::openTag(os, depth + command_depth, false, environment_stack[depth]); + } else { + sgml::closeEnvTags(os, false, environment_inner[depth], + command_depth + depth); + } + + if (style->latextype == LATEX_ENVIRONMENT) { + if (!style->latexparam().empty()) { + if (style->latexparam() == "CDATA") + os << "latexparam()); + } + break; + } + + desc_on = (style->labeltype == LABEL_MANUAL); + + environment_inner[depth] = desc_on ? "varlistentry" : "listitem"; + sgml::openTag(os, depth + 1 + command_depth, + false, environment_inner[depth]); + + item_name = desc_on ? "term" : "para"; + sgml::openTag(os, depth + 1 + command_depth, + false, item_name); + break; + default: + sgml::openTag(os, depth + command_depth, + false, style->latexname()); + break; + } + + par->simpleDocBookOnePar(buf, os, outerFont(par, paragraphs), desc_on, + depth + 1 + command_depth); + + string end_tag; + // write closing SGML tags + switch (style->latextype) { + case LATEX_COMMAND: + end_tag = c_params.empty() ? "title" : c_params; + sgml::closeTag(os, depth + command_depth, + false, end_tag); + break; + case LATEX_ENVIRONMENT: + if (!style->latexparam().empty()) { + if (style->latexparam() == "CDATA") + os << "]]>"; + else + sgml::closeTag(os, depth + command_depth, false, style->latexparam()); + } + break; + case LATEX_ITEM_ENVIRONMENT: + if (desc_on == 1) break; + end_tag = "para"; + sgml::closeTag(os, depth + 1 + command_depth, false, end_tag); + break; + case LATEX_PARAGRAPH: + sgml::closeTag(os, depth + command_depth, false, style->latexname()); + break; + default: + sgml::closeTag(os, depth + command_depth, false, style->latexname()); + break; + } + } + + // Close open tags + for (int d = depth; d >= 0; --d) { + if (!environment_stack[depth].empty()) { + sgml::closeEnvTags(os, false, environment_inner[depth], + command_depth + depth); + } + } + + for (int j = command_depth; j >= 0 ; --j) + if (!command_stack[j].empty()) { + sgml::closeTag(os, j, false, command_stack[j]); + os << endl; + } +} + namespace { int readParToken(Buffer & buf, Paragraph & par, LyXLex & lex, string const & token) diff --git a/src/paragraph_funcs.h b/src/paragraph_funcs.h index a67354d5a9..7f29e39d7d 100644 --- a/src/paragraph_funcs.h +++ b/src/paragraph_funcs.h @@ -73,6 +73,14 @@ void latexParagraphs(Buffer const & buf, LatexRunParams const &, std::string const & everypar = std::string()); +void linuxdocParagraphs(Buffer const & buf, + ParagraphList const & paragraphs, + std::ostream & os); + +void docbookParagraphs(Buffer const & buf, + ParagraphList const & paragraphs, + std::ostream & os); + /// read a paragraph from a .lyx file. Returns number of unrecognised tokens int readParagraph(Buffer & buf, Paragraph & par, LyXLex & lex); -- 2.39.2