]> git.lyx.org Git - lyx.git/blob - src/output_docbook.cpp
In non-MultiPar insets, we do not want to output paragraphs at all.
[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 "ParagraphList.h"
24 #include "ParagraphParameters.h"
25 #include "sgml.h"
26 #include "Text.h"
27 #include "TextClass.h"
28
29 #include "support/lassert.h"
30 #include "support/debug.h"
31 #include "support/lstrings.h"
32
33 #include <boost/next_prior.hpp>
34
35 using namespace std;
36 using namespace lyx::support;
37
38 namespace lyx {
39
40 namespace {
41
42 ParagraphList::const_iterator searchParagraph(
43         ParagraphList::const_iterator p,
44   ParagraphList::const_iterator const & pend)
45 {
46         for (++p; p != pend && p->layout().latextype == LATEX_PARAGRAPH; ++p)
47                 ;
48
49         return p;
50 }
51
52
53 ParagraphList::const_iterator searchCommand(
54                 ParagraphList::const_iterator p,
55                 ParagraphList::const_iterator const & pend)
56 {
57         Layout const & bstyle = p->layout();
58
59         for (++p; p != pend; ++p) {
60                 Layout const & style = p->layout();
61                 if (style.latextype == LATEX_COMMAND
62                                 && style.commanddepth <= bstyle.commanddepth)
63                         return p;
64         }
65         return pend;
66 }
67
68
69 ParagraphList::const_iterator searchEnvironment(
70                 ParagraphList::const_iterator p,
71                 ParagraphList::const_iterator const & pend)
72 {
73         Layout const & bstyle = p->layout();
74         size_t const depth = p->params().depth();
75         for (++p; p != pend; ++p) {
76                 Layout const & style = p->layout();
77                 if (style.latextype == LATEX_COMMAND)
78                         return p;
79
80                 if (style.latextype == LATEX_PARAGRAPH) {
81                         if (p->params().depth() > depth)
82                                 continue;
83                         return p;
84                 }
85
86                 if (p->params().depth() < depth)
87                         return p;
88
89                 if (style.latexname() != bstyle.latexname()
90                                 && p->params().depth() == depth)
91                         return p;
92         }
93         return pend;
94 }
95
96
97 ParagraphList::const_iterator makeParagraph(Buffer const & buf,
98                                             odocstream & os,
99                                             OutputParams const & runparams,
100                                             Text const & text,
101                                             ParagraphList::const_iterator const & pbegin,
102                                             ParagraphList::const_iterator const & pend)
103 {
104         ParagraphList const & paragraphs = text.paragraphs();
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                                         text.outerFont(distance(paragraphs.begin(), par)));
112                 } else {
113                         sgml::openTag(buf, os, runparams, *par);
114                         par->simpleDocBookOnePar(buf, os, runparams, 
115                                         text.outerFont(distance(paragraphs.begin(), par)));
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                                               Text const & text,
127                                               ParagraphList::const_iterator const & pbegin,
128                                               ParagraphList::const_iterator const & pend)
129 {
130         ParagraphList const & paragraphs = text.paragraphs();
131         ParagraphList::const_iterator par = pbegin;
132
133         Layout const & defaultstyle = buf.params().documentClass().defaultLayout();
134         Layout const & bstyle = par->layout();
135         string item_tag;
136
137         // Opening outter tag
138         sgml::openTag(buf, os, runparams, *pbegin);
139         os << '\n';
140         if (bstyle.latextype == LATEX_ENVIRONMENT && bstyle.pass_thru)
141                 os << "<![CDATA[";
142
143         while (par != pend) {
144                 Layout const & style = par->layout();
145                 ParagraphList::const_iterator send;
146                 string id = par->getID(buf, runparams);
147                 string wrapper = "";
148                 pos_type sep = 0;
149
150                 // Opening inner tag
151                 switch (bstyle.latextype) {
152                 case LATEX_ENVIRONMENT:
153                         if (!bstyle.innertag().empty()) {
154                                 sgml::openTag(os, bstyle.innertag(), id);
155                         }
156                         break;
157
158                 case LATEX_ITEM_ENVIRONMENT:
159                         if (!bstyle.labeltag().empty()) {
160                                 sgml::openTag(os, bstyle.innertag(), id);
161                                 sgml::openTag(os, bstyle.labeltag());
162                                 sep = par->firstWordDocBook(os, runparams) + 1;
163                                 sgml::closeTag(os, bstyle.labeltag());
164                         }
165                         wrapper = defaultstyle.latexname();
166                         // If a sub list (embedded list) appears next with a
167                         // different depth, then there is no need to open
168                         // another tag at the current depth.
169                         if(par->params().depth() == pbegin->params().depth()) {
170                                 sgml::openTag(os, bstyle.itemtag());
171                         }
172                         break;
173                 default:
174                         break;
175                 }
176
177                 switch (style.latextype) {
178                 case LATEX_ENVIRONMENT:
179                 case LATEX_ITEM_ENVIRONMENT: {
180                         if (par->params().depth() == pbegin->params().depth()) {
181                                 sgml::openTag(os, wrapper);
182                                 par->simpleDocBookOnePar(buf, os, runparams,
183                                         text.outerFont(distance(paragraphs.begin(), par)), sep);
184                                 sgml::closeTag(os, wrapper);
185                                 ++par;
186                         }
187                         else {
188                                 send = searchEnvironment(par, pend);
189                                 par = makeEnvironment(buf, os, runparams, text, par,send);
190                         }
191                         break;
192                 }
193                 case LATEX_PARAGRAPH:
194                         send = searchParagraph(par, pend);
195                         par = makeParagraph(buf, os, runparams, text, par,send);
196                         break;
197                 case LATEX_LIST_ENVIRONMENT:
198                 case LATEX_BIB_ENVIRONMENT:
199                 case LATEX_COMMAND:
200                         // FIXME This means that we are just skipping any paragraph that
201                         // isn't implemented above, and this includes lists.
202                         ++par;
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                                           Text const & text,
248                                           ParagraphList::const_iterator const & pbegin,
249                                           ParagraphList::const_iterator const & pend)
250 {
251         ParagraphList const & paragraphs = text.paragraphs();
252         ParagraphList::const_iterator par = pbegin;
253         Layout const & bstyle = par->layout();
254
255         //Open outter tag
256         sgml::openTag(buf, os, runparams, *pbegin);
257         os << '\n';
258
259         // Label around sectioning number:
260         if (!bstyle.labeltag().empty()) {
261                 sgml::openTag(os, bstyle.labeltag());
262                 // We don't care about appendix in DOCBOOK.
263                 os << par->expandLabel(bstyle, buf.params(), false);
264                 sgml::closeTag(os, bstyle.labeltag());
265         }
266
267         // Opend inner tag and  close inner tags
268         sgml::openTag(os, bstyle.innertag());
269         par->simpleDocBookOnePar(buf, os, runparams,
270                 text.outerFont(distance(paragraphs.begin(), par)));
271         sgml::closeTag(os, bstyle.innertag());
272         os << '\n';
273
274         ++par;
275         while (par != pend) {
276                 Layout const & style = par->layout();
277                 ParagraphList::const_iterator send;
278
279                 switch (style.latextype) {
280                 case LATEX_COMMAND: {
281                         send = searchCommand(par, pend);
282                         par = makeCommand(buf, os, runparams, text, par,send);
283                         break;
284                 }
285                 case LATEX_ENVIRONMENT:
286                 case LATEX_ITEM_ENVIRONMENT: {
287                         send = searchEnvironment(par, pend);
288                         par = makeEnvironment(buf, os, runparams, text, par,send);
289                         break;
290                 }
291                 case LATEX_PARAGRAPH:
292                         send = searchParagraph(par, pend);
293                         par = makeParagraph(buf, os, runparams, text, par,send);
294                         break;
295                 default:
296                         break;
297                 }
298         }
299         // Close outter tag
300         sgml::closeTag(os, *pbegin);
301
302         return pend;
303 }
304
305 } // end anonym namespace
306
307
308 void docbookParagraphs(Text const & text,
309                        Buffer const & buf,
310                        odocstream & os,
311                        OutputParams const & runparams)
312 {
313         ParagraphList const & paragraphs = text.paragraphs();
314         ParagraphList::const_iterator par = paragraphs.begin();
315         ParagraphList::const_iterator pend = paragraphs.end();
316
317         LASSERT(runparams.par_begin <= runparams.par_end, /**/);
318         // if only part of the paragraphs will be outputed
319         if (runparams.par_begin !=  runparams.par_end) {
320                 par = boost::next(paragraphs.begin(), runparams.par_begin);
321                 pend = boost::next(paragraphs.begin(), runparams.par_end);
322                 // runparams will be passed to nested paragraphs, so
323                 // we have to reset the range parameters.
324                 const_cast<OutputParams&>(runparams).par_begin = 0;
325                 const_cast<OutputParams&>(runparams).par_end = 0;
326         }
327
328         while (par != pend) {
329                 Layout const & style = par->layout();
330                 ParagraphList::const_iterator lastpar = par;
331                 ParagraphList::const_iterator send;
332
333                 switch (style.latextype) {
334                 case LATEX_COMMAND: {
335                         send = searchCommand(par, pend);
336                         par = makeCommand(buf, os, runparams, text, par,send);
337                         break;
338                 }
339                 case LATEX_ENVIRONMENT:
340                 case LATEX_ITEM_ENVIRONMENT: {
341                         send = searchEnvironment(par, pend);
342                         par = makeEnvironment(buf, os, runparams, text, par,send);
343                         break;
344                 }
345                 case LATEX_PARAGRAPH:
346                         send = searchParagraph(par, pend);
347                         par = makeParagraph(buf, os, runparams, text, par,send);
348                         break;
349                 default:
350                         break;
351                 }
352                 // makeEnvironment may process more than one paragraphs and bypass pend
353                 if (distance(lastpar, par) >= distance(lastpar, pend))
354                         break;
355         }
356 }
357
358
359 } // namespace lyx