]> git.lyx.org Git - lyx.git/blob - src/output_docbook.cpp
simplification
[lyx.git] / src / output_docbook.cpp
1 /**
2  * \file output_docbook.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author José Matos
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "output_docbook.h"
15
16 #include "Buffer.h"
17 #include "buffer_funcs.h"
18 #include "BufferParams.h"
19 #include "Counters.h"
20 #include "debug.h"
21 #include "Layout.h"
22 #include "OutputParams.h"
23 #include "Paragraph.h"
24 #include "paragraph_funcs.h"
25 #include "ParagraphList.h"
26 #include "ParagraphParameters.h"
27 #include "sgml.h"
28 #include "TextClass.h"
29
30 #include "support/lstrings.h"
31 #include "support/lyxlib.h"
32 #include "support/convert.h"
33 #include "support/types.h"
34
35 #include <boost/next_prior.hpp>
36
37
38 namespace lyx {
39
40 using support::subst;
41
42 using std::endl;
43 using std::ostream;
44 using std::vector;
45 using std::string;
46
47 namespace {
48
49 ParagraphList::const_iterator searchParagraph(
50         ParagraphList::const_iterator const & par,
51   ParagraphList::const_iterator const & pend)
52 {
53         ParagraphList::const_iterator p = boost::next(par);
54
55         for (; p != pend && p->layout()->latextype == LATEX_PARAGRAPH; ++p)
56                 ;
57
58         return p;
59 }
60
61
62 ParagraphList::const_iterator searchCommand(
63                 ParagraphList::const_iterator const & par,
64                 ParagraphList::const_iterator const & pend)
65 {
66         LayoutPtr const & bstyle = par->layout();
67         ParagraphList::const_iterator p = boost::next(par);
68
69         for ( ; p != pend; ++p) {
70                 LayoutPtr const & style = p->layout();
71                 if (style->latextype == LATEX_COMMAND
72                                 && style->commanddepth <= bstyle->commanddepth)
73                         return p;
74         }
75         return pend;
76 }
77
78
79 ParagraphList::const_iterator searchEnvironment(
80                 ParagraphList::const_iterator const & par,
81                 ParagraphList::const_iterator const & pend)
82 {
83         LayoutPtr const & bstyle = par->layout();
84         ParagraphList::const_iterator p = boost::next(par);
85         for (; p != pend; ++p) {
86                 LayoutPtr const & style = p->layout();
87                 if (style->latextype == LATEX_COMMAND)
88                         return p;
89
90                 if (style->latextype == LATEX_PARAGRAPH) {
91                         if (p->params().depth() > par->params().depth())
92                                 continue;
93                         return p;
94                 }
95
96                 if (p->params().depth() < par->params().depth())
97                         return p;
98
99                 if (style->latexname() != bstyle->latexname()
100                                 && p->params().depth() == par->params().depth() )
101                         return p;
102         }
103         return pend;
104 }
105
106
107 ParagraphList::const_iterator makeParagraph(Buffer const & buf,
108                                             odocstream & os,
109                                             OutputParams const & runparams,
110                                             ParagraphList const & paragraphs,
111                                             ParagraphList::const_iterator const & pbegin,
112                                             ParagraphList::const_iterator const & pend)
113 {
114         LayoutPtr const & defaultstyle =
115                 buf.params().getTextClass().defaultLayout();
116         for (ParagraphList::const_iterator par = pbegin; par != pend; ++par) {
117                 if (par != pbegin)
118                         os << '\n';
119                 if (par->layout() == defaultstyle && par->emptyTag()) {
120                         par->simpleDocBookOnePar(buf, os, runparams, outerFont(std::distance(paragraphs.begin(), par), paragraphs));
121                 } else {
122                         sgml::openTag(buf, os, runparams, *par);
123                         par->simpleDocBookOnePar(buf, os, runparams, outerFont(std::distance(paragraphs.begin(), par), paragraphs));
124                         sgml::closeTag(os, *par);
125                 }
126         }
127         return pend;
128 }
129
130
131 ParagraphList::const_iterator makeEnvironment(Buffer const & buf,
132                                               odocstream & os,
133                                               OutputParams const & runparams,
134                                               ParagraphList const & paragraphs,
135                                               ParagraphList::const_iterator const & pbegin,
136                                               ParagraphList::const_iterator const & pend) {
137         ParagraphList::const_iterator par = pbegin;
138
139         LayoutPtr const & defaultstyle = buf.params().getTextClass().defaultLayout();
140         LayoutPtr const & bstyle = par->layout();
141         string item_tag;
142
143         // Opening outter tag
144         sgml::openTag(buf, os, runparams, *pbegin);
145         os << '\n';
146         if (bstyle->latextype == LATEX_ENVIRONMENT && bstyle->pass_thru)
147                 os << "<![CDATA[";
148
149         while (par != pend) {
150                 LayoutPtr const & style = par->layout();
151                 ParagraphList::const_iterator send;
152                 string id = par->getID(buf, runparams);
153                 string wrapper = "";
154                 pos_type sep = 0;
155
156                 // Opening inner tag
157                 switch (bstyle->latextype) {
158                 case LATEX_ENVIRONMENT:
159                         if (!bstyle->innertag().empty()) {
160                                 sgml::openTag(os, bstyle->innertag(), id);
161                         }
162                         break;
163
164                 case LATEX_ITEM_ENVIRONMENT:
165                         if (!bstyle->labeltag().empty()) {
166                                 sgml::openTag(os, bstyle->innertag(), id);
167                                 sgml::openTag(os, bstyle->labeltag());
168                                 sep = par->getFirstWord(buf, os, runparams) + 1;
169                                 sgml::closeTag(os, bstyle->labeltag());
170                         }
171                         wrapper = defaultstyle->latexname();
172                         // If a sub list (embedded list) appears next with a
173                         // different depth, then there is no need to open
174                         // another tag at the current depth.
175                         if(par->params().depth() == pbegin->params().depth()) {
176                                 sgml::openTag(os, bstyle->itemtag());
177                         }
178                         break;
179                 default:
180                         break;
181                 }
182
183                 switch (style->latextype) {
184                 case LATEX_ENVIRONMENT:
185                 case LATEX_ITEM_ENVIRONMENT: {
186                         if (par->params().depth() == pbegin->params().depth()) {
187                                 sgml::openTag(os, wrapper);
188                                 par->simpleDocBookOnePar(buf, os, runparams, outerFont(std::distance(paragraphs.begin(), par), paragraphs), sep);
189                                 sgml::closeTag(os, wrapper);
190                                 ++par;
191                         }
192                         else {
193                                 send = searchEnvironment(par, pend);
194                                 par = makeEnvironment(buf, os, runparams, paragraphs, par,send);
195                         }
196                         break;
197                 }
198                 case LATEX_PARAGRAPH:
199                         send = searchParagraph(par, pend);
200                         par = makeParagraph(buf, os, runparams, paragraphs, par,send);
201                         break;
202                 default:
203                         break;
204                 }
205
206                 // Closing inner tag
207                 switch (bstyle->latextype) {
208                 case LATEX_ENVIRONMENT:
209                         if (!bstyle->innertag().empty()) {
210                                 sgml::closeTag(os, bstyle->innertag());
211                                 os << '\n';
212                         }
213                         break;
214                 case LATEX_ITEM_ENVIRONMENT:
215                         // If a sub list (embedded list) appears next, then
216                         // there is no need to close the current tag.
217                         // par should have already been incremented to the next
218                         // element. So we can compare the depth of the next
219                         // element with pbegin.
220                         // We need to be careful, that we don't dereference par
221                         // when par == pend but at the same time that the
222                         // current tag is closed.
223                         if((par != pend && par->params().depth() == pbegin->params().depth()) || par == pend) {
224                                 sgml::closeTag(os, bstyle->itemtag());
225                         }
226                         if (!bstyle->labeltag().empty())
227                                 sgml::closeTag(os, bstyle->innertag());
228                         break;
229                 default:
230                         break;
231                 }
232         }
233
234         if (bstyle->latextype == LATEX_ENVIRONMENT && bstyle->pass_thru)
235                 os << "]]>";
236
237         // Closing outter tag
238         sgml::closeTag(os, *pbegin);
239
240         return pend;
241 }
242
243
244 ParagraphList::const_iterator makeCommand(Buffer const & buf,
245                                           odocstream & os,
246                                           OutputParams const & runparams,
247                                           ParagraphList const & paragraphs,
248                                           ParagraphList::const_iterator const & pbegin,
249                                           ParagraphList::const_iterator const & pend)
250 {
251         ParagraphList::const_iterator par = pbegin;
252         LayoutPtr const & bstyle = par->layout();
253
254         //Open outter tag
255         sgml::openTag(buf, os, runparams, *pbegin);
256         os << '\n';
257
258         // Label around sectioning number:
259         if (!bstyle->labeltag().empty()) {
260                 sgml::openTag(os, bstyle->labeltag());
261                 // We don't care about appendix in DOCBOOK.
262                 os << par->expandLabel(bstyle, buf.params(), false);
263                 sgml::closeTag(os, bstyle->labeltag());
264         }
265
266         // Opend inner tag and  close inner tags
267         sgml::openTag(os, bstyle->innertag());
268         par->simpleDocBookOnePar(buf, os, runparams,  outerFont(std::distance(paragraphs.begin(), par), paragraphs));
269         sgml::closeTag(os, bstyle->innertag());
270         os << '\n';
271
272         ++par;
273         while (par != pend) {
274                 LayoutPtr const & style = par->layout();
275                 ParagraphList::const_iterator send;
276
277                 switch (style->latextype) {
278                 case LATEX_COMMAND: {
279                         send = searchCommand(par, pend);
280                         par = makeCommand(buf, os, runparams, paragraphs, par,send);
281                         break;
282                 }
283                 case LATEX_ENVIRONMENT:
284                 case LATEX_ITEM_ENVIRONMENT: {
285                         send = searchEnvironment(par, pend);
286                         par = makeEnvironment(buf, os, runparams, paragraphs, par,send);
287                         break;
288                 }
289                 case LATEX_PARAGRAPH:
290                         send = searchParagraph(par, pend);
291                         par = makeParagraph(buf, os, runparams, paragraphs, par,send);
292                         break;
293                 default:
294                         break;
295                 }
296         }
297         // Close outter tag
298         sgml::closeTag(os, *pbegin);
299
300         return pend;
301 }
302
303 } // end anonym namespace
304
305
306 void docbookParagraphs(ParagraphList const & paragraphs,
307                        Buffer const & buf,
308                        odocstream & os,
309                        OutputParams const & runparams)
310 {
311         ParagraphList::const_iterator par = paragraphs.begin();
312         ParagraphList::const_iterator pend = paragraphs.end();
313
314         BOOST_ASSERT(runparams.par_begin <= runparams.par_end);
315         // if only part of the paragraphs will be outputed
316         if (runparams.par_begin !=  runparams.par_end) {
317                 par = boost::next(paragraphs.begin(), runparams.par_begin);
318                 pend = boost::next(paragraphs.begin(), runparams.par_end);
319                 // runparams will be passed to nested paragraphs, so
320                 // we have to reset the range parameters.
321                 const_cast<OutputParams&>(runparams).par_begin = 0;
322                 const_cast<OutputParams&>(runparams).par_end = 0;
323         }
324
325         while (par != pend) {
326                 LayoutPtr const & style = par->layout();
327                 ParagraphList::const_iterator lastpar = par;
328                 ParagraphList::const_iterator send;
329
330                 switch (style->latextype) {
331                 case LATEX_COMMAND: {
332                         send = searchCommand(par, pend);
333                         par = makeCommand(buf, os, runparams, paragraphs, par,send);
334                         break;
335                 }
336                 case LATEX_ENVIRONMENT:
337                 case LATEX_ITEM_ENVIRONMENT: {
338                         send = searchEnvironment(par, pend);
339                         par = makeEnvironment(buf, os, runparams, paragraphs, par,send);
340                         break;
341                 }
342                 case LATEX_PARAGRAPH:
343                         send = searchParagraph(par, pend);
344                         par = makeParagraph(buf, os, runparams, paragraphs, par,send);
345                         break;
346                 default:
347                         break;
348                 }
349                 // makeEnvironment may process more than one paragraphs and bypass pend
350                 if (std::distance(lastpar, par) >= std::distance(lastpar, pend))
351                         break;
352         }
353 }
354
355
356 } // namespace lyx