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