]> git.lyx.org Git - lyx.git/blob - src/output_docbook.C
Docbook - fix closing tags in the end of the document.
[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 #include <stack>
33
34 #ifdef HAVE_LOCALE
35 #endif
36
37 using lyx::support::atoi;
38 using lyx::support::split;
39 using lyx::support::subst;
40
41 using std::endl;
42 using std::ostream;
43 using std::stack;
44 using std::vector;
45 using std::string;
46
47
48 void docbookParagraphs(Buffer const & buf,
49                        ParagraphList const & paragraphs,
50                        ostream & os,
51                        OutputParams const & runparams)
52 {
53         vector<string> environment_stack(10);
54         vector<string> environment_inner(10);
55         vector<string> command_stack(10);
56
57         bool command_flag = false;
58         Paragraph::depth_type command_depth = 0;
59         Paragraph::depth_type command_base = 0;
60         Paragraph::depth_type cmd_depth = 0;
61         Paragraph::depth_type depth = 0; // paragraph depth
62
63         string command_name;
64
65         string item_tag;
66
67         ParagraphList::const_iterator par = paragraphs.begin();
68         ParagraphList::const_iterator pend = paragraphs.end();
69
70         Counters & counters = buf.params().getLyXTextClass().counters();
71
72         for (; par != pend; ++par) {
73
74                 LyXLayout_ptr const & style = par->layout();
75
76                 // environment tag closing
77                 for (; depth > par->params().depth(); --depth) {
78                         sgml::closeEnvTags(os, false, environment_inner[depth],
79                                 item_tag, command_depth + depth);
80                         sgml::closeTag(os, depth + command_depth, false, environment_stack[depth]);
81                         environment_stack[depth].erase();
82                         environment_inner[depth].erase();
83                 }
84
85                 if (depth == par->params().depth()
86                    && environment_stack[depth] != style->latexname()
87                    && !environment_stack[depth].empty()) {
88                                 sgml::closeEnvTags(os, false, environment_inner[depth],
89                                         item_tag, command_depth + depth);
90                         sgml::closeTag(os, depth + command_depth, false, environment_stack[depth]);
91
92                         environment_stack[depth].erase();
93                         environment_inner[depth].erase();
94                 }
95
96                 string ls = par->getDocbookId();
97                 if (!ls.empty())
98                         ls = " id = \"" + ls + "\"";
99
100                 // Write opening SGML tags.
101                 switch (style->latextype) {
102                 case LATEX_PARAGRAPH:
103                         if (!style->latexparam().empty()) {
104                                 counters.step("para");
105                                 int i = counters.value("para");
106                                 ls = subst(style->latexparam(), "#", tostr(i));
107                         }
108
109                         sgml::openTag(os, depth + command_depth,
110                                     false, style->latexname(), ls);
111                         break;
112
113                 case LATEX_COMMAND:
114                         if (depth != 0)
115                                 //error(ErrorItem(_("Error"), _("Wrong depth for LatexType Command."), par->id(), 0, par->size()));
116                                 ;
117
118                         command_name = style->latexname();
119
120                         cmd_depth = style->commanddepth;
121
122                         if (command_flag) {
123                                 if (cmd_depth < command_base) {
124                                         for (Paragraph::depth_type j = command_depth;
125                                              j >= command_base; --j) {
126                                                 sgml::closeTag(os, j, false, command_stack[j]);
127                                                 os << endl;
128                                         }
129                                         command_depth = command_base = cmd_depth;
130                                 } else if (cmd_depth <= command_depth) {
131                                         for (int j = command_depth;
132                                              j >= int(cmd_depth); --j) {
133                                                 sgml::closeTag(os, j, false, command_stack[j]);
134                                                 os << endl;
135                                         }
136                                         command_depth = cmd_depth;
137                                 } else
138                                         command_depth = cmd_depth;
139                         } else {
140                                 command_depth = command_base = cmd_depth;
141                                 command_flag = true;
142                         }
143                         if (command_stack.size() == command_depth + 1)
144                                 command_stack.push_back(string());
145                         command_stack[command_depth] = command_name;
146
147                         if (style->latexparam().find('#') != string::npos) {
148                                 counters.step(style->counter);
149                         }
150
151                         if (!style->latexparam().empty()) {
152                                 ls = style->latexparam();
153                                 if (ls.find('#') != string::npos) {
154                                         string el = expandLabel(buf.params().getLyXTextClass(),
155                                                 style, false);
156                                         ls = subst(ls, "#", el);
157                                 }
158                         }
159
160                         sgml::openTag(os, depth + command_depth, false, command_name, ls);
161
162                         // Label around sectioning number:
163                         if (!style->labeltag().empty()) {
164                                 sgml::openTag(os, depth + 1 + command_depth, false,
165                                         style->labeltag());
166                                 os << expandLabel(buf.params().getLyXTextClass(), style, false);
167                                 sgml::closeTag(os, depth + 1 + command_depth, false,
168                                         style->labeltag());
169                         }
170
171                         // Inner tagged header text, e.g. <title> for sectioning:
172                         sgml::openTag(os, depth + 1 + command_depth, false,
173                                 style->innertag());
174                         break;
175
176                 case LATEX_ENVIRONMENT:
177                 case LATEX_ITEM_ENVIRONMENT:
178                         if (depth < par->params().depth()) {
179                                 depth = par->params().depth();
180                                 environment_stack[depth].erase();
181                         }
182
183                         if (environment_stack[depth] != style->latexname()) {
184                                 if (environment_stack.size() == depth + 1) {
185                                         environment_stack.push_back("!-- --");
186                                         environment_inner.push_back("!-- --");
187                                 }
188                                 environment_stack[depth] = style->latexname();
189                                 environment_inner[depth] = "!-- --";
190                                 // outputs <environment_stack[depth] latexparam()>
191                                 sgml::openTag(os, depth + command_depth, false,
192                                                 environment_stack[depth], style->latexparam() + ls);
193                         } else {
194                                 sgml::closeEnvTags(os, false, environment_inner[depth],
195                                         style->itemtag(), command_depth + depth);
196                         }
197
198                         if (style->latextype == LATEX_ENVIRONMENT) {
199                                 if (!style->innertag().empty()) {
200                                         if (style->innertag() == "CDATA")
201                                                 os << "<![CDATA[";
202                                         else
203                                                 sgml::openTag(os, depth + command_depth, false,
204                                                         style->innertag());
205                                 }
206                                 break;
207                         }
208
209                         environment_inner[depth] = style->innertag();
210
211                         if (!environment_inner[depth].empty())
212                                 sgml::openTag(os, depth + 1 + command_depth,
213                                     false, environment_inner[depth]);
214                         break;
215                 default:
216                         sgml::openTag(os, depth + command_depth,
217                                     false, style->latexname(), ls);
218                         break;
219                 }
220
221                 par->simpleDocBookOnePar(buf, os,
222                         outerFont(par - paragraphs.begin(), paragraphs),
223                         runparams, depth + 1 + command_depth);
224
225                 // write closing SGML tags
226                 switch (style->latextype) {
227                 case LATEX_COMMAND:
228                         sgml::closeTag(os, depth + command_depth, false,
229                                 style->innertag());
230                         break;
231                 case LATEX_ENVIRONMENT:
232                         if (!style->innertag().empty()) {
233                                 if (style->innertag() == "CDATA")
234                                         os << "]]>";
235                                 else
236                                         sgml::closeTag(os, depth + command_depth, false,
237                                                 style->innertag());
238                         }
239                         break;
240                 case LATEX_ITEM_ENVIRONMENT:
241                         item_tag = style->itemtag();
242                         break;
243                 case LATEX_PARAGRAPH:
244                         sgml::closeTag(os, depth + command_depth, false, style->latexname());
245                         break;
246                 default:
247                         sgml::closeTag(os, depth + command_depth, false, style->latexname());
248                         break;
249                 }
250         }
251
252         // Close open tags
253         for (int d = depth; d >= 0; --d) {
254                 if (!environment_stack[depth].empty()) {
255                         sgml::closeEnvTags(os, false, environment_inner[d], item_tag, command_depth + d);
256                         sgml::closeTag(os, d + command_depth, false, environment_stack[d]);
257                 }
258         }
259
260         for (int j = command_depth; j >= 0 ; --j)
261                 if (!command_stack[j].empty()) {
262                         sgml::closeTag(os, j, false, command_stack[j]);
263                         os << endl;
264                 }
265 }