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