]> git.lyx.org Git - lyx.git/blob - src/output_docbook.C
Reorganized docbook export code and fixed several bugs in the process.
[lyx.git] / src / output_docbook.C
1 /**
2  * \file output_docbook.C
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 "bufferparams.h"
18 #include "counters.h"
19 #include "debug.h"
20 #include "lyxtext.h"
21 #include "paragraph.h"
22 #include "paragraph_funcs.h"
23 #include "ParagraphParameters.h"
24 #include "sgml.h"
25
26 #include "insets/insetcommand.h"
27
28 #include "support/lstrings.h"
29 #include "support/lyxlib.h"
30 #include "support/tostr.h"
31
32 #ifdef HAVE_LOCALE
33 #endif
34
35 using lyx::support::subst;
36
37 using std::endl;
38 using std::ostream;
39 using std::stack;
40 using std::vector;
41 using std::string;
42
43 namespace {
44
45 ParagraphList::const_iterator searchParagraph(ParagraphList::const_iterator const & par,
46                                               ParagraphList::const_iterator const & pend)
47 {
48         ParagraphList::const_iterator p = par + 1;
49
50         for( ; p != pend && p->layout()->latextype == LATEX_PARAGRAPH; ++p);
51
52         return p;
53 }
54
55
56 ParagraphList::const_iterator searchCommand(ParagraphList::const_iterator const & par,
57                                             ParagraphList::const_iterator const & pend)
58 {
59         LyXLayout_ptr const & bstyle = par->layout();
60         ParagraphList::const_iterator p = par + 1;
61
62         for( ; p != pend; ++p) {
63                 LyXLayout_ptr const & style = p->layout();
64                 if( style->latextype == LATEX_COMMAND && style->commanddepth <= bstyle->commanddepth)
65                         return p;
66         }
67         return pend;
68 }
69
70
71 ParagraphList::const_iterator searchEnvironment(ParagraphList::const_iterator const & par,
72                                                 ParagraphList::const_iterator const & pend)
73 {
74         LyXLayout_ptr const & bstyle = par->layout();
75         ParagraphList::const_iterator p = par + 1;
76         for( ; p != pend; ++p) {
77                 LyXLayout_ptr 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() > par->params().depth())
83                                 continue;
84                         return p;
85                 }
86
87                 if( style->latexname() != bstyle->latexname() and p->params().depth() <= par->params().depth())
88                         return p;
89         }
90         return pend;
91 }
92
93
94 ParagraphList::const_iterator makeParagraph(Buffer const & buf,
95                                             ostream & os,
96                                             OutputParams const & runparams,
97                                             ParagraphList const & paragraphs,
98                                             ParagraphList::const_iterator const & pbegin,
99                                             ParagraphList::const_iterator const & pend) {
100         ParagraphList::const_iterator par = pbegin;
101         Counters & counters = buf.params().getLyXTextClass().counters();
102         const int depth = 0;
103
104         for(; par != pend; ++par) {
105                 LyXLayout_ptr const & style = par->layout();
106                 string id = par->getDocbookId();
107         
108                 if (!style->latexparam().empty()) {
109                         counters.step("para");
110                         int i = counters.value("para");
111                         id = subst(style->latexparam(), "#", tostr(i));
112                 }
113
114                 id = id.empty()? "": " id = \"" + id + "\"";
115                 sgml::openTag(os, depth, true, style->latexname(), id);
116                 par->simpleDocBookOnePar(buf, os, outerFont(par - paragraphs.begin(), paragraphs), runparams, depth);
117         
118                 sgml::closeTag(os, depth, true, style->latexname());
119                 os << '\n';
120         }
121         return pend;
122 }
123
124
125 ParagraphList::const_iterator makeEnvironment(Buffer const & buf,
126                                               ostream & os,
127                                               OutputParams const & runparams,
128                                               ParagraphList const & paragraphs,
129                                               ParagraphList::const_iterator const & pbegin,
130                                               ParagraphList::const_iterator const & pend) {
131         ParagraphList::const_iterator par = pbegin;
132
133         Counters & counters = buf.params().getLyXTextClass().counters();
134         LyXLayout_ptr const & defaultstyle = buf.params().getLyXTextClass().defaultLayout();
135         const int depth = 0;
136
137         LyXLayout_ptr const & bstyle = par->layout();
138         string item_tag;
139         
140         string id = par->getDocbookId();
141         string env_name = bstyle->latexname();
142         // Opening outter tag
143         sgml::openTag(os, depth, false, env_name, bstyle->latexparam() + id);
144         os << '\n';
145         if (bstyle->latextype == LATEX_ENVIRONMENT and bstyle->innertag() == "CDATA")
146                 os << "<![CDATA[";
147
148         while (par != pend) {
149                 LyXLayout_ptr const & style = par->layout();
150                 string id = "";
151                 ParagraphList::const_iterator send;
152                 string wrapper = "";
153
154                 // Opening inner tag
155                 switch (bstyle->latextype) {
156                 case LATEX_ENVIRONMENT:
157                         if (!bstyle->innertag().empty() and bstyle->innertag() != "CDATA") {
158                                 sgml::openTag(os, depth, true, bstyle->innertag());
159                         }
160                         break;
161
162                 case LATEX_ITEM_ENVIRONMENT:
163                         if (!bstyle->labeltag().empty()) {
164                                 sgml::openTag(os, depth, true, bstyle->labeltag());
165                         } else {
166                                 if (!defaultstyle->latexparam().empty()) {
167                                         counters.step("para");
168                                         id = tostr(counters.value("para"));
169                                         id = " id=\""+ subst(defaultstyle->latexparam(), "#", id) + '"';
170                                         wrapper = defaultstyle->latexname();
171                                 }
172                                 sgml::openTag(os, depth, true, bstyle->itemtag());
173                         }
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, depth, true, wrapper, id);
183                                 par->simpleDocBookOnePar(buf, os, outerFont(par - paragraphs.begin(), paragraphs), runparams, depth);
184                                 sgml::closeTag(os, depth, true, wrapper);
185                                 ++par;
186                         }
187                         else {
188                                 send = searchEnvironment(par, pend);
189                                 par = makeEnvironment(buf, os, runparams, paragraphs, par,send);
190                         }
191                         break;
192                 }
193                 case LATEX_PARAGRAPH:
194                         send = searchParagraph(par, pend);
195                         par = makeParagraph(buf, os, runparams, paragraphs, par,send);
196                         break;
197                 default:
198                         break;
199                 }
200
201                 // Closing inner tag
202                 switch (bstyle->latextype) {
203                 case LATEX_ENVIRONMENT:
204                         if (!bstyle->innertag().empty() and bstyle->innertag() != "CDATA") {
205                                 sgml::closeTag(os, depth, true, bstyle->innertag());
206                                 os << '\n';
207                         }
208                         break;
209                 case LATEX_ITEM_ENVIRONMENT:
210                         sgml::closeTag(os, depth, true, bstyle->itemtag());
211                         break;
212                 default:
213                         break;
214                 }
215         }
216
217         if (bstyle->latextype == LATEX_ENVIRONMENT and bstyle->innertag() == "CDATA")
218                 os << "]]>";
219
220         // Closing outter tag
221         sgml::closeTag(os, depth, false, env_name);
222
223         return pend;
224 }
225
226
227 ParagraphList::const_iterator makeCommand(Buffer const & buf,
228                                           ostream & os,
229                                           OutputParams const & runparams,
230                                           ParagraphList const & paragraphs,
231                                           ParagraphList::const_iterator const & pbegin,
232                                           ParagraphList::const_iterator const & pend)
233 {
234         Paragraph::depth_type depth = 0; // paragraph depth
235
236         ParagraphList::const_iterator par = pbegin;
237
238         Counters & counters = buf.params().getLyXTextClass().counters();
239         LyXLayout_ptr const & bstyle = par->layout();
240         
241         string id = par->getDocbookId();
242         id = id.empty()? "" : " id = \"" + id + "\"";
243
244         if (bstyle->latexparam().find('#') != string::npos) {
245                 counters.step(bstyle->counter);
246         }
247         
248         if (!bstyle->latexparam().empty()) {
249                 id = bstyle->latexparam();
250                 if (id.find('#') != string::npos) {
251                         string el = expandLabel(buf.params().getLyXTextClass(),
252                                                 bstyle, false);
253                         id = subst(id, "#", el);
254                 }
255         }
256
257         //Open outter tag
258         sgml::openTag(os, depth, false, bstyle->latexname(), id);
259         os << '\n';
260
261         // Label around sectioning number:
262         if (!bstyle->labeltag().empty()) {
263                 sgml::openTag(os, depth, false, bstyle->labeltag());
264                 os << expandLabel(buf.params().getLyXTextClass(), bstyle, false);
265                 sgml::closeTag(os, depth, false, bstyle->labeltag());
266         }
267         
268         // Opend inner tag
269         sgml::openTag(os, depth, true, bstyle->innertag());
270
271         par->simpleDocBookOnePar(buf, os, outerFont(par - paragraphs.begin(), paragraphs),
272                                  runparams, depth);
273
274         // Close inner tags
275         sgml::closeTag(os, depth, true, bstyle->innertag());
276         os << '\n';
277         
278         ++par;
279         while (par != pend) {
280                 LyXLayout_ptr const & style = par->layout();
281                 ParagraphList::const_iterator send;
282
283                 switch (style->latextype) {
284                 case LATEX_COMMAND: {
285                         send = searchCommand(par, pend);
286                         par = makeCommand(buf, os, runparams, paragraphs, par,send);
287                         break;
288                 }
289                 case LATEX_ENVIRONMENT:
290                 case LATEX_ITEM_ENVIRONMENT: {
291                         send = searchEnvironment(par, pend);
292                         par = makeEnvironment(buf, os, runparams, paragraphs, par,send);
293                         break;
294                 }
295                 case LATEX_PARAGRAPH:
296                         send = searchParagraph(par, pend);
297                         par = makeParagraph(buf, os, runparams, paragraphs, par,send);
298                         break;
299                 default:
300                         break;
301                 }
302         }
303
304         // Close outter tag
305         sgml::closeTag(os, depth, false, bstyle->latexname());
306
307         return pend;
308 }
309
310 } // end anonym namespace
311
312
313 void docbookParagraphs(ParagraphList const & paragraphs,
314                        Buffer const & buf,
315                        ostream & os,
316                        OutputParams const & runparams)
317 {
318         ParagraphList::const_iterator par = paragraphs.begin();
319         ParagraphList::const_iterator pend = paragraphs.end();
320
321         while (par != pend) {
322                 LyXLayout_ptr const & style = par->layout();
323                 ParagraphList::const_iterator send;
324
325                 switch (style->latextype) {
326                 case LATEX_COMMAND: {
327                         send = searchCommand(par, pend);
328                         par = makeCommand(buf, os, runparams, paragraphs, par,send);
329                         break;
330                 }
331                 case LATEX_ENVIRONMENT:
332                 case LATEX_ITEM_ENVIRONMENT: {
333                         send = searchEnvironment(par, pend);
334                         par = makeEnvironment(buf, os, runparams, paragraphs, par,send);
335                         break;
336                 }
337                 case LATEX_PARAGRAPH:
338                         send = searchParagraph(par, pend);
339                         par = makeParagraph(buf, os, runparams, paragraphs, par,send);
340                         break;
341                 default:
342                         break;
343                 }
344         }
345 }