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