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