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