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