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