]> git.lyx.org Git - lyx.git/blob - src/output_docbook.C
more cursor dispatch
[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::iterator par = const_cast<ParagraphList&>(paragraphs).begin();
68         ParagraphList::iterator pend = const_cast<ParagraphList&>(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 = "";
97                 bool labelid = false;
98                 // Write opening SGML tags.
99                 switch (style->latextype) {
100                 case LATEX_PARAGRAPH:
101                         if (!style->latexparam().empty()) {
102                                 counters.step("para");
103                                 int i = counters.value("para");
104                                 ls = subst(style->latexparam(), "#", tostr(i));
105                         }
106                         sgml::openTag(os, depth + command_depth,
107                                     false, style->latexname(), ls);
108                         break;
109
110                 case LATEX_COMMAND:
111                         if (depth != 0)
112                                 //error(ErrorItem(_("Error"), _("Wrong depth for LatexType Command."), par->id(), 0, par->size()));
113                                 ;
114                         
115                         command_name = style->latexname();
116
117                         cmd_depth = style->commanddepth;
118                         
119                         if (command_flag) {
120                                 if (cmd_depth < command_base) {
121                                         for (Paragraph::depth_type j = command_depth;
122                                              j >= command_base; --j) {
123                                                 sgml::closeTag(os, j, false, command_stack[j]);
124                                                 os << endl;
125                                         }
126                                         command_depth = command_base = cmd_depth;
127                                 } else if (cmd_depth <= command_depth) {
128                                         for (int j = command_depth;
129                                              j >= int(cmd_depth); --j) {
130                                                 sgml::closeTag(os, j, false, command_stack[j]);
131                                                 os << endl;
132                                         }
133                                         command_depth = cmd_depth;
134                                 } else
135                                         command_depth = cmd_depth;
136                         } else {
137                                 command_depth = command_base = cmd_depth;
138                                 command_flag = true;
139                         }
140                         if (command_stack.size() == command_depth + 1)
141                                 command_stack.push_back(string());
142                         command_stack[command_depth] = command_name;
143
144                         if (style->latexparam().find('#') != string::npos) {
145                                 counters.step(style->counter);
146                         }
147                         // treat label as a special case for
148                         // more WYSIWYM handling.
149                         // This is a hack while paragraphs can't have
150                         // attributes, like id in this case.
151                         if (par->size() && par->isInset(0)) {
152                                 InsetBase * inset = par->getInset(0);
153                                 if (inset->lyxCode() == InsetOld::LABEL_CODE) {
154                                         command_name += " id=\"";
155                                         command_name += (static_cast<InsetCommand *>(inset))->getContents();
156                                         command_name += '"';
157                                         labelid = true;
158                                 }
159                         }
160                         if (!labelid && !style->latexparam().empty()) {
161                                 ls = style->latexparam();
162                                 if (ls.find('#') != string::npos) {
163                                         string el = expandLabel(buf.params().getLyXTextClass(), 
164                                                 style, false);
165                                         ls = subst(ls, "#", el);
166                                 } 
167                         }
168                         
169                         sgml::openTag(os, depth + command_depth, false, command_name, ls);
170
171                         // Label around sectioning number:
172                         if (!style->labeltag().empty()) {
173                                 sgml::openTag(os, depth + 1 + command_depth, false, 
174                                         style->labeltag());
175                                 os << expandLabel(buf.params().getLyXTextClass(), style, false);
176                                 sgml::closeTag(os, depth + 1 + command_depth, false, 
177                                         style->labeltag());
178                         }
179
180                         // Inner tagged header text, e.g. <title> for sectioning:
181                         sgml::openTag(os, depth + 1 + command_depth, false, 
182                                 style->innertag());
183                         break;
184
185                 case LATEX_ENVIRONMENT:
186                 case LATEX_ITEM_ENVIRONMENT:
187                         if (depth < par->params().depth()) {
188                                 depth = par->params().depth();
189                                 environment_stack[depth].erase();
190                         }
191
192                         if (environment_stack[depth] != style->latexname()) {
193                                 if (environment_stack.size() == depth + 1) {
194                                         environment_stack.push_back("!-- --");
195                                         environment_inner.push_back("!-- --");
196                                 }
197                                 environment_stack[depth] = style->latexname();
198                                 environment_inner[depth] = "!-- --";
199                                 // outputs <environment_stack[depth] latexparam()>
200                                 sgml::openTag(os, depth + command_depth, false, 
201                                                 environment_stack[depth], style->latexparam());
202                         } else {
203                                 sgml::closeEnvTags(os, false, environment_inner[depth], 
204                                         style->itemtag(), command_depth + depth);
205                         }
206
207                         if (style->latextype == LATEX_ENVIRONMENT) {
208                                 if (!style->innertag().empty()) {
209                                         if (style->innertag() == "CDATA")
210                                                 os << "<![CDATA[";
211                                         else
212                                                 sgml::openTag(os, depth + command_depth, false, 
213                                                         style->innertag());
214                                 }
215                                 break;
216                         }
217
218                         environment_inner[depth] = style->innertag();
219
220                         if (!environment_inner[depth].empty())
221                                 sgml::openTag(os, depth + 1 + command_depth,
222                                     false, environment_inner[depth]);
223                         break;
224                 default:
225                         sgml::openTag(os, depth + command_depth,
226                                     false, style->latexname());
227                         break;
228                 }
229
230                 par->simpleDocBookOnePar(buf, os, outerFont(par, paragraphs),
231                                          runparams, depth + 1 + command_depth, labelid);
232
233                 // write closing SGML tags
234                 switch (style->latextype) {
235                 case LATEX_COMMAND:
236                         sgml::closeTag(os, depth + command_depth, false, 
237                                 style->innertag());
238                         break;
239                 case LATEX_ENVIRONMENT:
240                         if (!style->innertag().empty()) {
241                                 if (style->innertag() == "CDATA")
242                                         os << "]]>";
243                                 else
244                                         sgml::closeTag(os, depth + command_depth, false, 
245                                                 style->innertag());
246                         }
247                         break;
248                 case LATEX_ITEM_ENVIRONMENT:
249                         item_tag = style->itemtag();
250                         break;
251                 case LATEX_PARAGRAPH:
252                         sgml::closeTag(os, depth + command_depth, false, style->latexname());
253                         break;
254                 default:
255                         sgml::closeTag(os, depth + command_depth, false, style->latexname());
256                         break;
257                 }
258         }
259
260         // Close open tags
261         for (int d = depth; d >= 0; --d) {
262                 if (!environment_stack[depth].empty()) {
263                                 sgml::closeEnvTags(os, false, environment_inner[depth], 
264                                         item_tag, command_depth + depth);
265                 }
266         }
267
268         for (int j = command_depth; j >= 0 ; --j)
269                 if (!command_stack[j].empty()) {
270                         sgml::closeTag(os, j, false, command_stack[j]);
271                         os << endl;
272                 }
273 }
274